--SQL Server的存储过程调用Com组件 /*--下面的部分在VB中完成首先我们先用VB 作一个最简单的组件工程名称: testSQLCOM 类名: TestMath'函数,计算两个整数相加的结果 Public Function AddMe(a As Long, b As Long) As Long AddMe = a + b End Function编译生成后,我们就可以在 Sql Server 中对这个 Com 组件进行调用了 --*//*--下面是SQL中对上面DLL的调用--*/--定义用到的变量 declare @err int,@src varchar(255),@desc varchar(255) declare @obj int,@re int--创建调用实例 exec @err=sp_OACreate 'testSQLCOM.TestMath', @obj out if @err<>0 goto lberr --如果创建失败,则进行错误处理--调用DLL中的函数 exec @err=sp_OAMethod @obj,'AddMe',@re out,100,200 if @err<>0 goto lberr --如果调用错误,则进行错误处理print '返回的结果是:' + str(@re)--完成后释放 exec sp_OADestroy @objreturnlberr: exec sp_oageterrorinfo 0,@src out,@desc out select cast(@err as varbinary(4)) as 错误号 ,@src as 错误源,@desc as 错误描述
crc32.dll好像不是EXTENDS STORED PROCEDURE,所以你是无法通过sp_addextendedproc 来加载的,你应该在DOS提示符下运行:REGSVR32 CRC32.DLL先注册该COM控件,然后SQLSERVER通过COM的方式调用.CRC32 COM Component is for ASP, .NET, Cold Fusion, VB, VC++ and other languages.The com component will quickly generate a CRC32 checksum in hex or numeric as the official polynomial used by CRC-32 in PKZip, WinZip and Ethernet.Example .asp, .net, vb & vc++ code includedsimple ASP example of usage:-Set Obj = Server.CreateObject("CRC32COM.CRC.1") dim crc crc = Obj.getCRC("C:\yourfile.dat")simple VC++ example of usage:-CRC32COMLib::ICRCPtr *test = NULL; struct __declspec(uuid("{CFA74BB7-DC31-4434-ADE6-D7D7BFBB3180}")) IClass; test = new CRC32COMLib::ICRCPtr( __uuidof(IClass) ); (*test)->numeric = false; CString crcfile = (char *)(_bstr_t)(*test)->getCRC((char *)(_bstr_t)"c:\\yourfile.dat");simple VB example of usage:-Dim obj As CRC32COMLib.CRC Set obj = New CRC32COMLib.CRC obj.Numeric = False dim crc crc = obj.getCRC("C:\yourfile.dat")simple ASP .NET using C# example of usage:-CRC32Com.CRC crc = new CRC32Com.CRC(); lblFile.Text = "C:\yourfile.dat"; lblMessage.Text = crc.getCRC(lblFile.Text);
感谢大家的支持,我写了一个java class ,总算把这个问题解决了,与大家分享代码:import java.io.*; import java.util.zip.*; public class CRC { String crcvalue; long hh; public String CRC(String textname) { try { CRC32 crc = new CRC32(); int number; //打开需压缩文件作为文件输入流 FileInputStream fin = new FileInputStream(textname);
/*--下面的部分在VB中完成首先我们先用VB 作一个最简单的组件工程名称: testSQLCOM
类名: TestMath'函数,计算两个整数相加的结果
Public Function AddMe(a As Long, b As Long) As Long
AddMe = a + b
End Function编译生成后,我们就可以在 Sql Server 中对这个 Com 组件进行调用了
--*//*--下面是SQL中对上面DLL的调用--*/--定义用到的变量
declare @err int,@src varchar(255),@desc varchar(255)
declare @obj int,@re int--创建调用实例
exec @err=sp_OACreate 'testSQLCOM.TestMath', @obj out
if @err<>0 goto lberr --如果创建失败,则进行错误处理--调用DLL中的函数
exec @err=sp_OAMethod @obj,'AddMe',@re out,100,200
if @err<>0 goto lberr --如果调用错误,则进行错误处理print '返回的结果是:' + str(@re)--完成后释放
exec sp_OADestroy @objreturnlberr:
exec sp_oageterrorinfo 0,@src out,@desc out
select cast(@err as varbinary(4)) as 错误号
,@src as 错误源,@desc as 错误描述
declare @rt int
exec @rt=sp_addextendedproc crc32 ,'crc32.dll'--声明
select @rtEXEC crc32 'H:\shenbao\doc\nn.xml'--调用dll是别人的,我不能该呀,各位大虾在想想办法,谢谢了
作者: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 ASexec sp_addextendedproc 'SetFileName', 'storeproc.dll' --声明函数
exec sp_addextendedproc 'addLine', 'storeproc.dll' declare @szFileName varchar(200)
declare @szText varchar(200)
declare @rt intSelect @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 @szTextend
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
#endifchar 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.8VC知识库测试环境:win2000 professional + SQL-Server 7.0 + VC.Net
dim crc
crc = Obj.getCRC("C:\yourfile.dat")simple VC++ example of usage:-CRC32COMLib::ICRCPtr *test = NULL;
struct __declspec(uuid("{CFA74BB7-DC31-4434-ADE6-D7D7BFBB3180}")) IClass;
test = new CRC32COMLib::ICRCPtr( __uuidof(IClass) );
(*test)->numeric = false;
CString crcfile = (char *)(_bstr_t)(*test)->getCRC((char *)(_bstr_t)"c:\\yourfile.dat");simple VB example of usage:-Dim obj As CRC32COMLib.CRC
Set obj = New CRC32COMLib.CRC
obj.Numeric = False
dim crc
crc = obj.getCRC("C:\yourfile.dat")simple ASP .NET using C# example of usage:-CRC32Com.CRC crc = new CRC32Com.CRC();
lblFile.Text = "C:\yourfile.dat";
lblMessage.Text = crc.getCRC(lblFile.Text);
import java.util.zip.*;
public class CRC
{
String crcvalue;
long hh;
public String CRC(String textname)
{
try
{
CRC32 crc = new CRC32();
int number;
//打开需压缩文件作为文件输入流
FileInputStream fin = new FileInputStream(textname);
byte[] buf=new byte[1024]; crc.reset();
while ((number = fin.read(buf)) > -1)
{
crc.update(buf, 0, number);
}
fin.close();
hh=crc.getValue();
crcvalue = Long.toHexString(hh);
} catch(IOException e)
{
System.out.println(e);
}
return crcvalue;
}
}