中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 编程语言 > Visual C++ > 数据库操作
在存储过程中调用外部的动态连接库(MS SQL Server7.0/2000环境)
作者:未知 时间:2005-07-20 14:18 出处:VC知识库 责编:chinaitpower
              摘要:在存储过程中调用外部的动态连接库(MS SQL Server7.0/2000环境)

在存储过程中调用外部的动态连接库(MS SQL Server7.0/2000环境)
作者:ac952_z_cn

问题的提出:
一般我们要根据数据库的纪录变化时,进行某种操作。我们习惯的操作方式是在程序中不停的查询表,判断是否有新纪录。这样耗费的资源就很高,如何提高这种效率,我想在表中创建触发器,在触发器中调用外部动态连接库通过消息或事件通知应用程序就可实现。而master的存储过程中最好能调用外部的动态连接库,我们在触发器中调用master的存储过程即可。

下载源代码 大小:14K

说明:VC6需要安装较新的Platform SDK才能顺利编译本代码,VC.Net可以直接编译本代码。另外还需要连接Opends60.lib
为了使没有较新Platform SDK的朋友也能编译本例子,已经将VC.Net中的Srv.h和Opends60.lib放到压缩包中

程序实现:
我们来实现一个存储过程中调用外部的dll(storeproc.dll)的函数SetFileName和addLine。

存储过程如下(需放到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 <windows.h>
#include <srv.h>			//要加入这个.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_SHARE_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

关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有