Tuesday, February 21, 2006

Developers: “Express Yourself” Part 1

Seems that Oracle are taking a leaf out of the many open source database projects and releasing a community version of there 10g database called Oracle 10g Express Edition, also known as XE

Basically this gives you many (not all) of the features of 10g on a very limited licence, like a different/limited administration toolset, no clustering or multiprocessor support and limited storage capacity to name a few, but essentially the core database is much the same, well from a developers perspective anyway.

One of the attractive features of XE is that its small enough to be installed on a developers workstation, thus not tying down resources otherwise managed by a wider group, normally involving DBAs and such. XE is excellent for you early development and “crash and burn” design prototyping.

The management tool they supply isn’t that bad actually, its web based so a plus for remote administration without the need to install a client. If you look past the clunky-ness of webforms, it does pretty much everything you would ask, including basic import and export of data

Getting database tools like Toad to work with XE isn’t too much hassle, but if you have previously installed an older Oracle Client you might need to modify the path statement so that the XE drivers take precedence over the older bin files, also you’d need to modify the .ora file accordingly. So far I have been using XE with Toad 8.5 and Crystal Reports 11 with no issue.

You can download XE from this location for the windows version.

http://download.oracle.com/otn/nt/oracle10g/xe/OracleXE.exe

For Part 2 of “Express Yourself” I plan to talk about MS SQL Server 2005 Express Edition and the suite of other Express tools that work with it.

Sunday, February 19, 2006

Handling Parameter Lists in MS SQL Server 2000 stored procedures.

Because of how SQL Server compiles stored procedures, it cannot handle a parameter being used in the IN clause that contains a parameter list.

There are a few ways to handle this, one very common seems to be to generate a dynamic SQL statement and concatenate the contents of the parameter to the SQL statement string, then execute using the sp_executesql function. Easy peezy.

Example 1

@vBillingCentres = “'1016','1049','1049A','1122A','1122C','1303','1369','1450','1615','1617'” passed in from Client to stored procedure.

DECLARE @SQLString nvarchar(4000)

SET @SQLString = N’SELECT * FROM tbl_test01 t where t.BillingCentre in ('+ @vBillingCentres +')’

EXECUTE sp_executesql @SQLString

This works nicely, although the use of dynamic SQL negates the performance that one can achieve using pre-compiled SQL Statements. The other major complaint is that as the procedure/SQL gets more and more complex, it can become more difficult to manage the string concatenation leading to issues with maintenance and debugging.

A Nicer Way

Ideally we don’t want to have to parse our stored procedures to differently from the norm, we would also like to take advantage of compiled code, and well, I’m a little bit of a neat freak when it comes to code, so yes, its gotta look right.

Using a SQL Server 2000 user defined functions we can create a function that we pass the parameter list, and returns a table object. Thus we can simple join on its output.

Example 2:

SELECT * FROM tbl_test01 T, fn_GetBillingCentreTble(@vBillingCentres) B

WHERE T.BillingCentre = B.BillingCentre

I think that most will agree that maintaining example 2 is far easier than example 1, there is a catch.

Depending on your requirements, the code sitting behind the function might need to be relatively complex. I have provided an example that I have used, and its by no means optimised. But in places were you have many many procedures needing this processing, it makes sense to invest some time in this functionality in my opinion.

This is the basic structure of the function (it will not compile, you’d need to work out your own logic anyway)


CREATE FUNCTION Fn_GetBillingCentreTble (@vBillCentres varchar(4000))

RETURNS @vTBL_BillingCentres TABLE (BillingCentre varchar(8) primary key)

AS

BEGIN

DECLARE @pos int

DECLARE @TempString varchar(5000)

DECLARE @curBillCentre varchar(50)

DECLARE @tTBL_BillingCentres TABLE (BillingCentre varchar(8) primary key) -- a temporay table variable used to store results

select @TempString = rtrim(ltrim(@vBillCentres)) -- trim and assign input parameter to working variable

if (@TempString <> '') -- split the BillingCentres if input string is not blank

begin

select @pos = charindex(',', @TempString)

while (@pos > 0)

begin

select @curBillCentre = substring(@TempString,1,@pos -1)

select @curBillCentre = rtrim(ltrim(replace(replace(@curBillCentre, '''', ' '),'"', ' ')))

if (LEN(@curBillCentre) >= 1 and LEN(@curBillCentre) <= 8)

begin

insert into @tTBL_BillingCentres values(@curBillCentre)

end

select @TempString = substring(@TempString,@pos +1,LEN(@TempString) - @pos)

select @pos = charindex(',', @TempString)

end

end

-- Copy the content of the local table variable to the one that will be returned

insert into @vTBL_BillingCentres

select BillingCentre from @tTBL_BillingCentres

return

END

I guess the only issue here is that we use a temp table, but really, its very lightweight in this example as there are limits to the size of the parameter list that is passed in.

Either way, in practice, both these approaches work
Well I have just started this blog, its hardly a new one, but I have decided to try to seperate my techie, geeky blog entries from my day to day life entries.

Im not 100% sure which is going to be what, but since I already have a bunch of personal stuff on my other blog at MSN Spaces( http://spaces.msn.com/aprilstaines/), i may as well make this the techie one.