[转]数据库的触发器trigger中如何执行socket操作
用户在执行insert,update, delete操作后,用触发器可以捕获到。我把想变化的数据用socket传到另一台机器上去,数据库的触发器中如何执行socket操作?
编一dll,这个dll负责把变化的数据用socket传到另一台机器上去,然后在触发器中调用这个dll,调用的方法和dll的范例在这里:
在存储过程中调用外部的动态连接库(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
编一dll,这个dll负责把变化的数据用socket传到另一台机器上去,然后在触发器中调用这个dll,调用的方法和dll的范例在这里:
在存储过程中调用外部的动态连接库(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