Automation and T-SQL
By Bill
Wunder
T-SQL does 4
things well: select, insert, update, and delete. That’s not to
say that you can’t write a select, insert, update or delete that
behaves poorly any more than it absolutely limits the use of
T-SQL to the primary SQL statements. The reality is that a huge
pool of experts have developed an impressively sophisticated
query processing engine to assure that the queries against even
a moderately complex database perform optimally. For everything
beyond the basic quartet of SQL statements the query processor
is not going to be able to offer as much under the hood
assistance to a T-SQL script or stored procedure. To be sure,
T-SQL has steadily improved over the years in areas such as
string manipulation, the shell interface, and even table pivot
operations: things that, to this day, a ‘real’ programming
language or application executable can do better and faster than
a T-SQL script or stored procedure. Still, we’ve all found
compelling and valid reasons to use the tools we’re given and
the rich collection of T-SQL features should not be ignored.
One set of
T-SQL tools that strays far from traditional SQL into the realm
of OLE automation are affectionately know as the sp_OAs. These
are a set of seven extended stored procedures steeped in
mysticism and fraught with the perils of memory leaks, weak
documentation, and the need for T-SQL to actually handle an
error. The memory leak issue is important and in my opinion
persistent (see Microsofts KB articles Q282229 and Q320130 for
examples). If you use a component that leaks memory and it is
called 50,000 times a day you likely will have an unstable SQL
Server. If you call it 500 times a day you might get away with
it if you have a large pool of physical memory and reboot every
night . I don’t recommend the sp_OAs for either scenario.
However, If you have to roll out a conversion script intended to
be executed once on a server or you have a job sequence that
must be carefully controlled and occurs relatively infrequently
the OLE automation might be just the ticket.
As an example:
I found myself in a situation where I had three possible
versions of a script that I needed to execute during a data
conversion. One of my goals for any conversion script is that a
single script should make all changes, The idea being that if
the person applying the conversion has only the task of
initiating the only conversion script there is greater
confidence that no part of the conversion is forgotten or missed
or fails and no one notices, so having three possible versions
was troublesome to me. The factors to determine which script
would be appropriate at first seemed quite convoluted. At the
beginning everyone fully expected to have to ask an offsite user
to manually check several criteria on multiple servers and then
select the appropriate script. As we dug into the problem, we
discovered that the correct script could be selected based on
the version of only two .dlls. Even at that no one was
particularly comfortable with the need for a manual check given
our concern for the sensitivity of the data and what could
happen if someone made a mistake. We had limited time to get a
conversion process tested and ready. Using the sp_OAs to get the
version of the two files proved to be a snap. Right in the T-SQL
script I could decide the appropriate version and could
therefore fulfill my objective of making the entire conversion
happen in one script.
The coolest
thing this script illustrates is how easy it is to actually use
the automation stored procedures. If you’re at all familiar with
ActiveX or shell scripting and programming to an object model
then implementing OLE automation with the sp_OAs is a breeze. If
you’re not, taking the time to understand what is happening in
this simple code segment is going to help prepare you for a
future of unlimited possibilities. It is very different from a
traditional SQL query!
Since I
already knew that the Windows Scripting Host’s FileSystemObject
included the GetFileVersion method. All I had to figure out was
how to implement the call from T-SQL. Take a quick step through
of the solution I used (This works on SQL2K SP3 on WIN2K SP3
server and the .dll referenced in the example should be on any
server so feel free to try it out -- in your test or development
environment of course!):
--
determine the fully qualified name(s) of file
declare
@FileSpec varchar(255), @Version varchar(15)
set
@FileSpec = 'C:\WINNT\system32\ver.dll'
-- get
all file versions before script makes any changes
declare
@oFSO int, @oFile int
declare
@hr int
declare
@src varchar(255), @desc varchar(255)
exec @hr
= sp_OACreate 'Scripting.FileSystemObject', @oFSO OUT
if @hr
<> 0 begin
exec
sp_OAGetErrorInfo @oFSO, @src OUT, @desc OUT
Goto
ErrorHandler
end
--
execute the GetFileVersion method on the file
exec @hr
= sp_OAMethod @oFSO, 'GetFileVersion', @Version OUT, @FileSpec
if @hr <> 0 begin
exec
sp_OAGetErrorInfo @oFSO, @src OUT, @desc OUT
Goto
ErrorHandler
end
--
Always clean up the OLE server
exec @hr
= sp_OADestroy @oFSO
if @hr
<> 0 begin
exec
sp_OAGetErrorInfo @oFSO, @src OUT, @desc OUT
Goto
ErrorHandler
end
--
caution, closes automation environment for everyone
exec
sp_OAStop
-- do
some stuff
if
@Version = ''
print 'not there'
if
@Version like '3.0%'
print 'old'
if
@Version like '3.1%'
print 'current'
GoTo
Done
ErrorHandler:
If @oFSO
is not null
exec @hr = sp_OADestroy @oFSO
exec
sp_OAStop
Raiserror('Unable to get version for file %s. error: %u source:
%s desc: %s',19,1,@FileSpec, @hr, @src, @desc) with log
Done:
As you can
see, not much in the way of T-SQL fundamentals in this script,
yet I was able to take care business with a single T-SQL Script
and all the user had to do was open the file in Query Analyzer
and hit f5. Just the way we like it. The operations used to
implement a COM object using the sp_OAs will always include:
-
create
the object - This will give you access to the object
model
-
execute a method, or access/modify a property
-
destroy the object you created
SQL Server
Books on Line doesn’t do much to demystify the sp_OAs. If you
see a possible use for OLE automation or you need to access an
object model in your T-SQL work and you learn from examples you
can also have a look at the script
admin db - table function to get Agent job status I have
posted or check out
the stored procedures I have used to script out entire servers intended
primarily for SQL 7 for some additional working examples. In
both of these examples I use the automation procedures to access
the DMO object model .
I'd also like
to show you how easy and powerful object models like DMO are in
a DTS ActiveX task or the Windows scripting host, so stay tuned.
Bill
|