Given that a recent blog of mine lamented the dangers of using xprocs, I thought it would be a good time to show some of the wonderful stuff you can do thanks to SQL Server extensibility features such as xprocs and COM objects. It’s not that xprocs or in-process COM objects are inherently evil -- it’s just that they can be misused and that they can be challenging for the average developer to code properly.
In today’s blog, I’ll show you how to filter T-SQL queries using Regular Expressions. Regular Expressions, you’ll recall, allow sophisticated string searching and matching that goes beyond simple wildcards. T-SQL’s LIKE operator (and PATINDEX() function, which has similar functionality) supports basic wildcards and some simple pattern matching, but has never had anything approaching Regular Expression support. People who’ve written much T-SQL have no doubt encountered situations where they needed string searches that exceeded the meager capabilities of LIKE.
Lurking on any machine that has Windows Scripting Host installed (virtually all machines these days, although scripting can be disabled), is a powerful Regular Expressions facility, the VBScript.RegExp scripting object. You can get to it from any COM client that supports the IDispatch interface. IDispatch, you’ll recall, is COM’s popular late-binding interface – it allows applications to use COM components without knowing anything about them at compile-time. In T-SQL, we get to IDispatch via the sp_OA stored procedures. Via a simple UDF, we can access the RegExp object as though it were part of T-SQL:
DROP function dbo.fn_regex
dbo.fn_regex(@pattern varchar(255), @matchstring varchar(8000))
declare @obj int
declare @res int
declare @match bit
exec @res=sp_OACreate 'VBScript.RegExp',@obj OUT
IF (@res <> 0) BEGIN
exec @res=sp_OASetProperty @obj, 'Pattern', @pattern
exec @res=sp_OASetProperty @obj, 'IgnoreCase', 1
exec @res=sp_OAMethod @obj, 'Test',@match OUT, @matchstring
exec @res=sp_OADestroy @obj
The UDF above does several interesting things. Note the fact that we call the sp_OA procs directly from our function. If you’ve done much UDF coding, you’re probably aware of the fact that you can’t call regular stored procedures from a UDF. Fortunately for us, although the sp_OA procs are prefixed with "sp_", they’re actually extended procedures, which you can call from a UDF. Equally fortunate is the fact that they aren’t “spec procs”—extended procedures implemented internally by the server. Their entry points are in ODSOLE70.DLL, so they’re callable from a UDF just like any other regular xproc.
The algorithm we use here is embarrassingly simple: We create the object, set some properties, then call the Test method to see whether we have a match. As the code below illustrates, once we’ve wrapped our Regular Expression functionality in a UDF, we can use it to filter a query.
So, even though xprocs and COM objects can be abused and can certainly cause problems when not coded properly, on balance, SQL Server, coupled with the objects and facilities lying around on most users’ machines, offers some great extensibility and power with minimal effort.
This technique first appeared in my last book, The Guru’s Guide to SQL Server Architecture and Internals. That book has lots of additional details about Regular Expression use from T-SQL, including how to do so using the .NET Framework’s Regex object rather than VBScript.RegExp. See it for additional Regular Expression search techniques as well as for more info on SQL Server's SQLOLE facility, the component that makes all of this possible.