程序如何得到“SQL数据库的数据被修改”的即时通知??
有一个EXE程序在运行,现在试图使用它来监视SQL数据库内某个指定的表的数据变化信息:当有其它用户修改了数据库数据(比如ASP等),该EXE程序能够即时地得到通知,并在第一时间内可以对修改后的数据进行处理。
SQL数据库有相关的接口,或者回调机制吗?(该EXE使用标准ODBC接口来访问SQL数据库)
不知道如何实现,盼高手能提供一些经验。
谢谢!!
问题点数:200、回复次数:16Top
1 楼huangbeyond(校园人渣)回复于 2003-09-02 22:40:58 得分 0
先顶一次。Top
2 楼small_wei(small)回复于 2003-09-03 01:27:13 得分 50
对要监控的表做一个触发器(可以是insert ,update etc..),在触发器中调用一DLL程序,将相关的数据通过消息发送给你的程序就行了。
在存储过程中调用外部的动态连接库(MS SQL Server7.0/2000环境)
问题的提出:
一般我们要根据数据库的纪录变化时,进行某种操作。我们习惯的操作方式是在程序中不停的查询表,判断是否有新纪录。这样耗费的资源就很高,如何提高这种效率,我想在表中创建触发器,在触发器中调用外部动态连接库通过消息或事件通知应用程序就可实现。而master的存储过程中最好能调用外部的动态连接库,我们在触发器中调用master的存储过程即可。
说明: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的在线帮助。
Top
3 楼njtlxm(似是故人来)回复于 2003-09-03 09:04:53 得分 50
用SQL 里的存储过程调用外部的exe或者bat也一样,调用的时候传入修改数据的关键参数(比如:表名+主键)就可以了。Top
4 楼cdwy411(VC$ORACLE)回复于 2003-09-03 10:34:58 得分 0
做个触发器吧!!!
一有变动,自动触发函数处理!!Top
5 楼r3000()回复于 2003-09-03 11:50:19 得分 50
触发器,DLL什么得都是笨的不能再笨的办法,定义触发器会严重影响效率。
以下纯属猜测或者说提醒,本人并没有实践。
实际上表的插入、删除、更新等的变化,SQL Sever内部都有记载(系统表、日志)
,只要你的EXE不断监视此记载即可。
Top
6 楼huangbeyond(校园人渣)回复于 2003-09-03 13:36:11 得分 0
to:r3000()
如果"EXE不断监视此记载",的确是非常消耗系统资源的啊........
非常感谢上面几位的帮助,我现在在加紧时间测试,一旦完成,立即结贴
还有别的朋友有更好的,或者其它的方法吗?Top
7 楼jnxulei(石头)回复于 2003-09-03 15:46:39 得分 0
对表的所有操作在日志中有记载,你仔细研究一下日志文件Top
8 楼jnxulei(石头)回复于 2003-09-03 15:48:03 得分 0
对表的所有操作在日志中有记载,但俺没有研究过日志文件Top
9 楼huangbeyond(校园人渣)回复于 2003-09-03 22:50:39 得分 0
继续推......Top
10 楼small_wei(small)回复于 2003-09-04 01:28:33 得分 0
日志文件用户应该是用不上的Top
11 楼r3000()回复于 2003-09-04 10:18:03 得分 0
"如果"EXE不断监视此记载",的确是非常消耗系统资源的啊........"
消耗的仅是客户端资源,对于server端,不过是一个查询用户,比触发器要节约的多。
我只是建议一个思路,印象中,见过类似的东西,没有用触发器和DLL.
Top
12 楼huangbeyond(校园人渣)回复于 2003-09-04 12:00:25 得分 0
TO:small_wei(small)
我遇上一个难题:我的EXE和SQL服务器并不在一台计算机上,如果使用触发器-DLL的话,那么,就要涉及“机器间进程通讯的问题”。这样一来,触发器-DLL就要使用“WINSOCK等系统通讯技术”来进行更新通知。这样会导致各个程序之间复杂度大大加剧。
还有什么别的好办法吗?Top
13 楼zhaolaoxin()回复于 2003-09-04 12:26:20 得分 0
没有其他方法,只能用数据库自身的触发器功能来执行一个程序,所有要做的其它工作由这个程序完成。Top
14 楼ZHENG017()回复于 2003-09-04 13:32:11 得分 50
就使用dcom呗。新建一个trigger,在trigger像下边这样调用:(从msdn中copy出来的)
关键是使用"sp_OACreate",在msdn中index "sp_OACreate"
DECLARE @object int
DECLARE @hr int
DECLARE @src varchar(255), @desc varchar(255)
EXEC @hr = sp_OACreate 'SQLDMO.SQLServer', @object OUT
IF @hr <> 0
BEGIN
EXEC sp_OAGetErrorInfo @object, @src OUT, @desc OUT
SELECT hr=convert(varbinary(4),@hr), Source=@src, Description=@desc
RETURN
END
Top
15 楼21bird(世纪笨鸟:csdn的blog啊啥时能不出错?!)回复于 2003-09-13 15:17:00 得分 0
用odbc的.exe啊?
那好像就没戏了,不过我刚查到oledb倒是提供了实现此功能的接口。
书上说oledb服务器在rowset发生改变的时候,会发送通告。
要接收这些通告,客户必须实现IRowsetNotify接口,并将其注册到服务器去。
应该可以用atl oledb实现。具体请查阅相关文档。
想知道asp程序做的改变?asp一般都是用ado的,其实ado调用的就是oledb~~~~
所以我想他一定会发送那种通告……Top
16 楼mahatma_cn(研究硕士生)回复于 2003-09-13 23:53:18 得分 0
ado啊,满足你的要求Top
17 楼chen_pin(小品)回复于 2003-09-14 11:19:29 得分 0
UP_ItTop



