Shaun Mccran

My digital playground

10
M
A
R
2009

SQL Stored Procedures, SELECT Template script

This article deals with creating a SQL stored procedure for selecting a record.

In each of these stored procedure templates I am declaring a variety of documentation parameters in the header.

I've found these handy in the past when you are working in a team environment, or when you go back to a procedure at a later date. Its much easier to read a simple description in the header, than trawl through the SQL code looking for what it is doing.

So, this declares the procedure name, any parameters and return codes, and also details what it does, and who made it.

In a modified version of this I also hold the SVN revision number here.

view plain print about
1/********************************************************************************/
2/*         Company Name                             */
3/********************************************************************************/
4/* Procedure Name : dbo.ssp_stored_procname */
5/* Parameters : */
6/* Return Codes : */
7/* */
8/* Description : Description of what it does, params etc */
9/* */
10/* */
11/* */
12/* */
13/* */
14/* Author : Authorname */
15/* Date written : Date */
16/* History : version number */
17/* */
18/********************************************************************************/

The next block of code performs a select on the sysObjects table (part of the Master database). It is checking for the existence of itself. If it finds itself, it will drop the procedure. Note that throughout all of these scripts we are telling the user at each stage what is going on, by printing useful english output back to the screen.

view plain print about
1IF EXISTS (SELECT 1 FROM sysobjects where id = object_id('dbo.ssp_stored_procname') and sysstat & 0xf = 4)
2BEGIN
3    PRINT 'Dropping old version of dbo.ssp_stored_procname'
4    DROP PROCEDURE dbo.ssp_stored_procname
5END
6GO

By now we have identified wether or not the procedure previously existed, and if it did, we have dropped it, so we know that we are all good to go. So to create our Insert procedure, we print out a message to the user, then using the "CREATE PROCEDURE" command we create our procedure.

At this point you substitute the "@field" value with your field name, and the [datatype] and (datasize) with the correct values. As an example of this the first line in this proc will create a field named 'varName' with a data type of varchar with a character limit of 100. Just list your fields one after another, seperating with a comma.

view plain print about
1PRINT 'Creating procedure dbo.ssp_stored_procname - START'
2GO
3
4CREATE PROCEDURE dbo.ssp_stored_procname
5    (varName        [varchar](100),
6     @field             [int],
7     @field            [datatype](datasize),
8     @field            [datatype],
9     @field            [datatype],
10     @field            [datatype])

After that we create the SQL code, as per usual. We have a Select statement, listing the fields, and the SQL variable declaration (@var). Then we check for any errors, and return a success message if it all worked ok!

view plain print about
1Select Fields
2from Table
3Where (Conditions)
4RETURN @@ERROR
5GO
6
7PRINT 'Creating procedure dbo.ssp_stored_procname - END'
8GO

By using a script like this I've found that its really simple to have a repeatable standard process that is easy to implement across a team of developers, ensuring you get the same results, no matter who writes the query. It is also very useful if you have a seperate implementation team, as these scripts are re-runnable, they clear up after themselves.

Download the full template here.

04
M
A
R
2009

SQL Stored Procedures, INSERT Template script

This article deals with creating a SQL stored procedure for inserting a record.

In each of these stored procedure templates I am declaring a variety of documentation parameters in the header.

I've found these handy in the past when you are working in a team environment, or when you go back to a procedure at a later date. Its much easier to read a simple description in the header, than trawl through the SQL code looking for what it is doing.

So, this declares the procedure name, any parameters and return codes, and also details what it does, and who made it.

In a modified version of this I also hold the SVN revision number here.

view plain print about
1/********************************************************************************/
2/*         Company Name                             */
3/********************************************************************************/
4/* Procedure Name : dbo.ssp_stored_procname */
5/* Parameters : */
6/* Return Codes : */
7/* */
8/* Description : Description of what it does, params etc */
9/* */
10/* */
11/* */
12/* */
13/* */
14/* Author : Authorname */
15/* Date written : Date */
16/* History : version number */
17/* */
18/********************************************************************************/

The next block of code performs a select on the sysObjects table (part of the Master database). It is checking for the existence of itself. If it finds itself, it will drop the procedure. Note that throughout all of these scripts we are telling the user at each stage what is going on, by printing useful english output back to the screen.

view plain print about
1IF EXISTS (SELECT 1 FROM sysobjects where id = object_id('dbo.ssp_stored_procname') and sysstat & 0xf = 4)
2BEGIN
3    PRINT 'Dropping old version of dbo.ssp_stored_procname'
4    DROP PROCEDURE dbo.ssp_stored_procname
5END
6GO

By now we have identified wether or not the procedure previously existed, and if it did, we have dropped it, so we know that we are all good to go. So to create our Insert procedure, we print out a message to the user, then using the "CREATE PROCEDURE" command we create our procedure.

At this point you substitute the "@field" value with your field name, and the [datatype] and (datasize) with the correct values. As an example of this the first line in this proc will create a field named 'varName' with a data type of varchar with a character limit of 100. Just list your fields one after another, seperating with a comma.

view plain print about
1PRINT 'Creating procedure dbo.ssp_stored_procname - START'
2GO
3
4CREATE PROCEDURE dbo.ssp_stored_procname
5    (varName        [varchar](100),
6     @field             [int],
7     @field            [datatype](datasize),
8     @field            [datatype],
9     @field            [datatype],
10     @field            [datatype])

After that we create the SQL code, as per usual. We have an Insert statement, listing the fields, and the SQL variable declaration (@var). Then we check for any errors, and return a success message if it all worked ok!

view plain print about
1AS INSERT INTO table
2     ([field],
3     [field],
4     [field],
5     [field],
6     [field],
7     [field])
8VALUES
9    (@field,
10     @field,
11     @field,
12     @field,
13     @field,
14     @field)
15
16RETURN @@ERROR
17GO
18
19PRINT 'Creating procedure dbo.ssp_stored_procname - END'
20GO

By using a script like this I've found that its really simple to have a repeatable standard process that is easy to implement across a team of developers, ensuring you get the same results, no matter who writes the query. It is also very useful if you have a seperate implementation team, as these scripts are re-runnable, they clear up after themselves.

Download the full template here.

02
M
A
R
2009

MS SQL Stored procedure templates

Over the course of working with one employer, I headed up an investigation into our current server performance, and how would could potentially aim for at least a 25% to 30% increase on our current user thresholds before our capacity maxed out.

After looking through a series of server logs, and data transactions it was easy to see that the server technology being used, Coldfusion, is not the most efficient data handler in the world.

So after stripping back our application layer, taking a peek under the hood, and changing around 600 or so instances of data connectivity from inline SQL code, to Stored Procedures, we had more than exceeded our target gain. In fact under stress testing we had achieved a consistent increase of around 65% threshold. As a quick set of figures, the server loads had changed from CF, running at 75%-80% dropping to 20%-25%, and SQL server running at 6% increased to around 15%.

Based on these figures, and architectural methodologies I've learnt since, I would always recommend stored procedures over inline SQL code. This has lead me to develop a standard set of SQL templates for developers to use.

They are self checking, repeatable SQL templates that will action the desired changes, and check for any existing conditions up front. The idea is that a non technical resource could run them, and receive a useable English response.

1. Select statement
2. Update Statement
3. Insert statement
4. Delete statement

26
F
E
B
2009

Differences between cfQueryParam "cf_sql_date" and "cf_sql_timestamp"

I was recently looking at a report generator, and came across a conflict in the mySql query dealing with the date objects.

The report returns a set of records between two dates, using cfqueryparam, but there seemed to be a problem in running the query using certain dates.

Running it from a browser provided differing results from running it directly in a sql interface. So where was the error?

The original code was using the "cf_sql_date" type to pass the date time off to the sql engine. It appears that this data type is not transferred as a date time value, but as an incompatible numeric value, that is not comparable to the mySql datetime I am querying against.

view plain print about
1AND table.ap_startdate >= <cfqueryparam cfsqltype="CF_SQL_DATE" value="#createodbcdate(arguments.rangefrom)#">
2
3AND table.ap_enddate <= <cfqueryparam cfsqltype="CF_SQL_DATE" value="#createodbcdate(arguments.rangeto)#">

There are a wealth of articles online about passing date values into a variety of database technologies, but this Adobe post was very helpful.

This article shows a handy table of cfsqltypes and how they map to different database management systems.

Using something like sql profiler you can clearly see the difference between cf_sql_date and cf_sql_timestamp, where cf_sql_date is being truncated to just a date value (actually evaluates as a numeric value) and a full date time stamp that cf_sql_timestamp generates.

view plain print about
1AND table.ap_startdate >= <cfqueryparam cfsqltype="cf_sql_timestamp" value="#createodbcdate(arguments.rangefrom)#">
2
3AND table.ap_enddate <= <cfqueryparam cfsqltype="cf_sql_timestamp" value="#createodbcdate(arguments.rangeto)#">

Changing the code to the above example completely resolves this issue.

_UNKNOWNTRANSLATION_ /