荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: DuMiYue (TH@Figo), 信区: Visual
标  题: 在存储过程中调用外部的动态连接库(MS SQL Server7.0
发信站: 荔园晨风BBS站 (Tue Mar 19 14:20:48 2002), 转信

 [ 本文适合中级读者 已阅读6次 ]
在存储过程中调用外部的动态连接库(MS SQL Server7.0/2000环境)
作者:ac952_z_cn
问题的提出:
一般我们要根据数据库的纪录变化时,进行某种操作。我们习惯的操作方式是在程序中
不停的查询表,判断是否有新纪录。这样耗费的资源就很高,如何提高这种效率,我想
在表中创建触发器,在触发器中调用外部动态连接库通过消息或事件通知应用程序就可
实现。而master的存储过程中最好能调用外部的动态连接库,我们在触发器中调用mast
er的存储过程即可。
下载源代码 大小:14K
说明:VC6需要安装较新的Platform SDK才能顺利编译本代码,VC.Net可以直接编译本代
码。另外还需要连接Opends60.lib
为了使没有较新Platform SDK的朋友也能编译本例子,已经将VC.Net中的Srv.h和Opend
s60.lib放到压缩包中
程序实现:
我们来实现一个存储过程中调用外部的dll(storeproc.dll)的函数SetFileName和addLi
ne。
存储过程如下(需放到master库中): CREATE PROCEDURE sp_testdll AS
exec sp_addextendedproc ''SetFileName'', ''storeproc.dll''      --声明函数
exec sp_addextendedproc ''addLine'', ''storeproc.dll''
declare @szFileName varchar(200)
declare @szText varchar(200)
declare @rt int
Select @szFileName = ''c:\welcome.txt''
EXEC @rt = SetFileName @szFileName      --调用SetFileName函数,参数为
--szFileName
;
if @rt = 0
begin
select @szText = ''welcome 01''
Exec @rt = addLine @szText                                      --调用addLine
select @szText = ''welcome 02''
Exec @rt = addLine @szText
end
exec sp_dropextendedproc ''SetFileName''
exec sp_dropextendedproc ''addLine''
dbcc SetFileName(free)
dbcc addLine(free)
动态连接库的实现:这种动态连接库和普通的有所不同。该动态连接库要放入SQL的执行
目录下,或直接放到Window的System32目录下,并重起SQL-Server #include
#include                        //要加入这个.h文件
#define XP_NOERROR      0
#define XP_ERROR        1
#ifndef _DEBUG
#define _DEBUG
#endif
char szFileName[MAX_PATH+1];
void WriteInfo(const char * str);
extern "C" SRVRETCODE WINAPI SetFileName(SRV_PROC* pSrvProc)
{
        WriteInfo("SetFileName start");
        int paramCount = srv_rpcparams(pSrvProc);
        if (paramCount != 1){
                WriteInfo("Param Err start");
                return XP_ERROR;
        }
        BYTE            bType;
        unsigned long   cbMaxLen;
        unsigned long   cbActualLen;
        BOOL            fNull;
        int ret = srv_paraminfo(pSrvProc, 1, &bType, &cbMaxLen, &cbActualLen,
                        NULL, &fNull);
        if (cbActualLen){
                ZeroMemory(szFileName, MAX_PATH+1);
                memcpy(szFileName, srv_paramdata(pSrvProc, 1), cbActualLen);
                WriteInfo("Set filename ok");
                return (XP_NOERROR);
        }
        else {
                WriteInfo("Set filename param failed");
                return XP_ERROR;
        }
}
extern "C" SRVRETCODE WINAPI addLine(SRV_PROC* pSrvProc)
{
        WriteInfo("addline start");
        int paramCount = srv_rpcparams(pSrvProc);
        if (paramCount != 1){
                WriteInfo("addline param err");
                return XP_ERROR;
        }
        BYTE            bType;
        unsigned long   cbMaxLen;
        unsigned long   cbActualLen;
        BOOL            fNull;
        bool            rt = false;
        int ret = srv_paraminfo(pSrvProc, 1, &bType, &cbMaxLen, &cbActualLen,
                        NULL, &fNull);
        if (cbActualLen){
                int n;
                char srt[3] = {0x0d, 0x0a, 0};
                char * c = new char[cbActualLen + 3];
                if (!c)return XP_ERROR;
                ZeroMemory(c, cbActualLen + 3);
                memcpy(c, srv_paramdata(pSrvProc, 1), cbActualLen);
                memcpy(c+cbActualLen, srt, 3);
                HANDLE hf = CreateFile(szFileName, GENERIC_WRITE,
FILE_SHARE_WRITE|FILE_SH
ARE_READ, NULL,
                                  OPEN_ALWAYS, 0, NULL);
                if (hf == INVALID_HANDLE_VALUE){
                        WriteInfo("addline create file err ");
                        delete []c;
                        return XP_ERROR;
                }
                WriteInfo("addline create file ok ");
                DWORD dwWt;
                n = strlen(c);
                SetFilePointer(hf, 0, NULL, FILE_END);
                if (WriteFile(hf, c, n, &dwWt, NULL) && dwWt == n)
                {
                        WriteInfo("addline write file ok ");
                        rt = true;
                }
                delete []c;
                CloseHandle(hf);
        }
        return rt ? XP_NOERROR:XP_ERROR;
}
inline void WriteInfo(const char * str){
    #ifdef _DEBUG
        char srt[3] = {0x0d, 0x0a, 0};
        HANDLE hf = CreateFile("c:\\storeproc.log", GENERIC_WRITE,
FILE_SHARE_WRITE
|FILE_SHARE_READ, NULL,
                                  OPEN_ALWAYS, 0, NULL);
        if (hf != INVALID_HANDLE_VALUE){
                SetFilePointer(hf, 0, NULL, FILE_END);
                DWORD dwWt;
                WriteFile(hf, str, strlen(str), &dwWt, NULL);
                WriteFile(hf, srt, strlen(srt), &dwWt, NULL);
                CloseHandle(hf);
        }
        else {
                MessageBox(NULL, "Write info err", "Message",
MB_OK|MB_ICONINFORMATION);
        }
        #endif
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpReserved)
{
        return TRUE;
}
编译完成后,把动态链接库放到WINNT/System32目录下,启动SQL Server。我们可以打开
SQL Server Query Analyzer调用存储过程sp_testdll以测试其运行是否正确。
具体可参考SQL-Server的在线帮助。
笔者环境:win2000 professional + SQL-Server7.0(2000也可)
VC6.0+SP5+Platform SDK 20001.8
VC知识库测试环境:win2000 professional + SQL-Server 7.0 + VC.Net

--
他能够不知不觉令到我倾心
    也能够一句说话而留下痛恨
        感情最光辉一刹热暖我一生
            爱人远走了以后仍然是爱人

※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 218.30.30.9]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店