Tuesday, March 29, 2005

Dynamic SQL FAQ 1: Convert conditional dynamic SQL string to stored proc

A lot of programmers coded the SQL query in dynamic SQL either in presentation layer or inside stored procedure, it has created a lot of problems in performance, security, maintenanbility, network and memory. More in The Curse and Blessings of Dynamic SQL.

From today onwards, I will compose a FAQ how to convert dynamic SQL to proper stored proc.

Dynamic SQL FAQ 1: Convert conditional dynamic SQL string to stored proc

The first FAQ I always heard is "I have a query based on a parameter, if the parameter is ALL, there will be no filter, if the parameter is a comma delimeter string (CSV), the query result will be filtered by the multiple values string in CSV format.

It has 2 challenges here:-
1) How to split the comma delimeter string
2) How to filter the result when it is not 'All'

It can be achieved easily by using dynamic SQL, the sample below is using SQL Server Northwind database with querying from SQL Query Analyser:-

declare @strSQL varchar(1000), @param varchar(100)
set @param = 'All'
set @param = '1,2,3'
set @strSQL = 'select * from employees'
if @param <> 'All'
set @strSQL = @strSQL + ' where employeeid in (' + @param + ')'
exec(@strSQL)

Let's see the 1st challenge, to split the CSV string, we can use the split function provided from Microsoft SQL Server Magazine Treat Yourself to Fn_Split():
This UDF lets you emulate VB's Split() function and parameter arrays


Then you can split the string by using the query easily:-

SELECT value FROM dbo.fn_split(@s, ',')

To filter either 'All' or not 'All', we have to use the power of "OR" operator, then the above dynamic SQL can be converted to proper SQL query as below:-

declare @s varchar(100)

set @s = '1,2,3'
--set @s = 'All'

select * from employees
where (@s <> 'All' AND employeeid in (SELECT value FROM dbo.fn_split(@s, ',')))
OR (@s = 'All')

Let's give me FIVE!

Thursday, March 24, 2005

Microsoft JET Database Engine error '80004005' Unspecified error

When you try to access JET data source like MS Access or MS Excel from your Active Server Pages (ASP), you may get this problem

Microsoft JET Database Engine error '80004005'

Unspecified error

You have set the permission of your IUSR_ComputerName user to full control, may be you already give full control permission to everyone, but the problem still occur.

You also reinstalled your JET with latest service pack, rebooted the server, but the problem still exists.

The problem actually is you have set the environment variables TMP and TEMP to invalid temporary folder.

Please access the Microsoft Knowledge base for more details:-
PRB: "Disk or Network Error" or "Unspecified Error" Returned when Using Jet
http://support.microsoft.com/kb/251254

After set the environment variables correctly, please remember to restart your computer. If it still can not work, you may need to change the temporary folder or set the temporary folder have EVERYONE full control.

Good luck!

Tuesday, March 22, 2005

IIS Log Analysis with Log Parser 2.2

How to analyze your website usage? How many users access your web site? Where is the top 10 URL in your web application? There are many questions you may ask after you deployed your web application into production web server.

You may think to write a small program to read from your web server log files, it will not be simple, you have to spend sometime to study web server log file, programming it open the log file by date, aggregate the data, filter the data, order the data, accept input from users and etc..

Wait a minute, there is a better way to do this: -

Thanks to Microsoft, they have provided a very powerful log analysis tool - Log Parser, now it is version 2.2, you can download it at http://www.microsoft.com/downloads/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07&displaylang=en. There is also an unofficial Log Parser support website at http://www.logparser.com/

The beauty part of the Log Parser is it combines the power of SQL query to query the data like RDBMS. It can be output to chart, grid, XML, SQL and other formats.

I have execute the Log Parser in my IIS web server to trace my web pages usage on March 2005 by using the following log parser command plus SQL query:-
logparser -i:IISW3C -o:Datagrid
"SELECT
date,
cs-uri-stem,
count(*) AS ACCESS_PER_DAY
FROM
c:\winnt\system32\logfiles\w3svc1\ex0503*.log
WHERE
cs-uri-stem LIKE '/myreport/%.asp'
GROUP BY
date,
cs-uri-stem
ORDER BY 
DATE"


It gives me the output in Grid:-
date       cs-uri-stem     ACCESS_PER_DAY
2005-03-08 /myreport/A.asp              1
2005-03-08 /myreport/B.asp              2
2005-03-08 /myreport/A.asp              6


Cool!

Friday, March 18, 2005

Disable Control+C in javascript

How to disable control+C in your web page to prevent user simply copy your text? Here is the code:-


<html>
<head>
<script language="javascript">
<!--
function Disable_Control_C() {
var keystroke = String.fromCharCode(event.keyCode).toLowerCase();

if (event.ctrlKey && keystroke == 'c') {
event.returnValue = false; // disable Ctrl+C
}
}
//--!>
</script>
</head>
<body onkeydown="javascript:Disable_Control_C()">
Hello World!
</body>
</html>

NOTE: You may need to disable the right click and menu bar to prevent user to copy from your text.

Wednesday, March 16, 2005

Convert dynamic SQL to stored procedure by using CASE

I always access other programmer code, I saw the code interesting and challenging today - the code is in ASP VBScript + dynamic SQL, the purpose of the code is to generate the SQL query string based on web page querystring, the code is as below:-

StrSQL = "select * from fact_drive_failures2 where day_id = " & request("day_id")
If request("floor") <> "" Then
StrSQL = strSQL & " and floor_id = " & request(“floor_id”)
End If

I believe this is a very common practice for many programmers. With the dynamic SQL string with the ASP code, it has many pitfalls in security, performance, permission, network traffic and many more disadvantages...

I convert this code to MS SQL Server stored procedure:-

CREATE PROCEDURE dbo.GET_DATA
(

@pn_DayId int,
@pv_FloorId varchar(1000)

)
AS
Select * from fact_data
where day_id = @pn_dayid
and floor_id =
case @pv_Floor = ‘’ then floor_id
else @pv_floor end

Now the stored procedure can be called by front-end application without worrying the string concatenation, easier to maintain, better security and the performance is much better.

My blog is alive!

Finally, my blog is alive!

I have been in software devlopment in Microsoft and Unix with more than 10 years experience, I have trained many software developers either during my work, speaking in technical conference and IT training center, it is glad to share my tips and tricks online here.

Let's start!