1、扩展存储过程的引入
首先,我们需要知道在SQLServer(7.0以上版本)中有一个扩展存储过程,名叫sp_addextendedproc,这是干什么用的呢,查它的帮助呀,不就知道了J,在SQLServer的帮助中是这样描述的:向 Microsoft SQL Server 注册新扩展存储过程的名称。语法为:sp_addextendedproc [@functname=] 'procedure' , [@dllname=] 'dll'。由此我们知道,它的功能是把已经写好在外部DLL文件中的函数引入到SQLServer中,提供给其它SQL代码调用。其用法示例为:
USE master
GO
EXEC sp_addextendedproc 'xp_hello', 'c:/xp_hello.dll'
上面的语句表示把外部DLL文件 c:/xp_hello.dll 中的函数 xp_hello 引入到SQLServer中,在执行完上面的语句后,主库中就多了一个名为 xp_hello的扩展存储过程,我们在其它脚本中就可以调用此扩展存储过程了。有一点限定的是,sp_addextendedproc只能在master中执行,如果在其它库中调用xp_hello,需要加上master限定库名。
2、编写外部DLL文件
好了,我们知道了怎样在SQLServer中加载外部扩展存储过程,接下来,我们要做什么呢,对了,在外部DLL中怎样编写符合SQLServer调用的函数。在VC6以上版本中,我们在安装的目录下能找到一个VC++头文件,名叫srv.h,它主要是提供给编程人员编写SQLServer扩展存储过程用的,人们称它为ODS(Open Data Services)开放数据服务接口头文件,里面为众多的常量、结构体、以及从DLL文件opends60.dll中导入的众多函数。因此,我们在编写自己的DLL文件时,需要包含此头文件,然后编写符合SQLServer扩展存储过程要求的、声明导出方式为 cdecl约定(由调用者清除堆栈)的函数。编写示例:
SRVRETCODE xp_hello(SRV_PROC* pSrvProc)
{
srv_sendmsg(pSrvProc, SRV_MSG_ERROR, XP_HELLO_ERROR, SRV_INFO, 1,
NULL, 0, (DBUSMALLINT) __LINE__,
"Usage: exec xp_hello <@param1 output>",
SRV_NULLTERM);
srv_senddone(pSrvProc, (SRV_DONE_ERROR | SRV_DONE_MORE), 0, 0);
}
功能:这个示例显示怎样调用的输出字符串。上面的示例是在VC环境下开发的示例,实际上,只要遵守调用约定,用什么语言都可以实现,由于本人对Delphi比对VC熟悉,我在这里重点讲解在Delphi下的编写过程。
在Delphi下开发,需要把VC下的头文件srv.h翻译为Delphi单元文件,便于调用,经过本人努力,已经翻译为OdsApi7.pas单元文件,内容如下:
{******************************************************************************}
{ @UnitName : OdsApi7 }
{ @Project : Algorism }
{ @Copyright : 1989 - 1999 Microsoft Corporation. }
{ @Translator : 杨连山, yangls@263.net }
{ @CreateDate : 2005-6-22 14:37:53 }
{ @LastUpdate : 2005-6-22 14:37:53 by 杨连山 }
{ }
{ @Description : ODS(Open Data Services)开放数据服务接口单元文件, 转换自VC7下的}
{ srv.h头文件. }
{ }
{ @Comment : 转换者: 杨连山 }
{ 1、您可以免费使用和分发本单元文件, 但不能作为商业应用之全部或部分.}
{ 2、在使用中如造成任何损失, 本转换者概不负责. }
{ 3、转换者不保证本单元转换全部正确, 如您发现或修正后, 有义务反馈 }
{ 最新版给转换者. 发到 yangls@263.net }
{ 4、请保留以上说明信息 }
{ }
{ @History : 2005-06-22 杨连山转换 }
{ }
{******************************************************************************}
unit OdsApi7;
interface
{$DEFINE DYNAMIC_LINK}
{$IFDEF DYNAMIC_LINK}
{$STACKFRAMES ON}
{$WARNINGS OFF}
{$ENDIF}
uses Windows;
// ODS uses pack(4) on all CPU types
{$ALIGN ON}
{$MINENUMSIZE 4}
// Formats of data types
type
DBBOOL = System.LongBool;
DBBYTE = System.BYTE;
DBTINYINT = System.Shortint;
DBSMALLINT = System.SmallInt;
DBUSMALLINT = System.Word;
DBINT = System.Integer;
DBCHAR = System.Char;
PDBCHAR = ^DBChar;
DBBINARY = System.BYTE;
DBBIT = (_0, _1);
DBFLT8 = System.Double;
TDBDATETIME = record // Format for SRVDATETIME
dtdays: Longint; // number of days since 1/1/1900
dttime: LongWord; // number 300th second since mid
end;
TDBMONEY = record // Format for SRVMONEY
mnyhigh: Longint;
mnylow: LongWord;
end;
DBFLT4 = Single;
DBMONEY4 = Longint;
TDBDATETIME4 = record // Format for SRVDATETIM4
numdays: Word; // number of days since 1/1/1900
nummins: Word; // number of minutes sicne midnight
end;
const
MAXNUMERICLEN = 16;
type
TDBNUMERIC = record // Format for SRVNUMERIC,SRVNUMERICN,SRVDECIMAL,SRVDECIMALN
precision: BYTE;
scale: BYTE;
sign: BYTE;
val: array[0..MAXNUMERICLEN - 1] of BYTE;
end;
TDBDECIMAL = TDBNUMERIC;
// Constants used by APIs
const
// Type Tokens
SRV_TDS_NULL = BYTE($1f);
SRV_TDS_TEXT = BYTE($23);
SRV_TDS_GUID = BYTE($24);
SRV_TDS_VARBINARY = BYTE($25);
SRV_TDS_INTN = BYTE($26);
SRV_TDS_VARCHAR = BYTE($27);
SRV_TDS_BINARY = BYTE($2d);
SRV_TDS_IMAGE = BYTE($22);
SRV_TDS_CHAR = BYTE($2f);
SRV_TDS_INT1 = BYTE($30);
SRV_TDS_BIT = BYTE($32);
SRV_TDS_INT2 = BYTE($34);
SRV_TDS_DECIMAL = BYTE($37);
SRV_TDS_INT4 = BYTE($38);
SRV_TDS_DATETIM4 = BYTE($3a);
SRV_TDS_FLT4 = BYTE($3b);
SRV_TDS_MONEY = BYTE($3c);
SRV_TDS_DATETIME = BYTE($3d);
SRV_TDS_FLT8 = BYTE($3e);
SRV_TDS_NUMERIC = BYTE($3f);
SRV_TDS_NTEXT = BYTE($63);
SRV_TDS_BITN = BYTE($68);
SRV_TDS_DECIMALN = BYTE($6a);
SRV_TDS_NUMERICN = BYTE($6c);
SRV_TDS_FLTN = BYTE($6d);
SRV_TDS_MONEYN = BYTE($6e);
SRV_TDS_DATETIMN = BYTE($6f);
SRV_TDS_MONEY4 = BYTE($7a);
SRV_TDS_BIGVARBINARY = BYTE($A5);
SRV_TDS_BIGVARCHAR = BYTE($A7);
SRV_TDS_BIGBINARY = BYTE($AD);
SRV_TDS_BIGCHAR = BYTE($AF);
SRV_TDS_NVARCHAR = BYTE($e7);
SRV_TDS_NCHAR = BYTE($ef);
// Datatypes
// Also: values of symbol parameter to srv_symbol when type = SRV_DATATYPE
SRVNULL = SRV_TDS_NULL;
SR