怎么实现扩展存储函数!

方欣 2003-08-25 10:50:29
SQL SERVER 2000提供了通过VC语言写扩展存储过程,现在我想写一个扩展存储函数,有没有什么方法。
...全文
71 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
nboys 2003-08-25
  • 打赏
  • 举报
回复
在SQL Server的存储过程中调用Com组件

SQL server 的 T-Sql 语言的功能是 非常的强大,但是有个时候 也确实是有些限制和不方便,为什么不象 asp 一样 大量的借用组件呢?开始在 Sql online book 中查找,终于找到了 一个 Sql 的 系统存储过程 sp_OACreate,下面大家就一起去 看看这个 存储过程的神气之处吧

s首先我们先用VB 作一个最简单的组件 ,因为是介绍性的文章,所以这个组件是非常的的简单,在具体的
工作中,可以写个 比这个 业务复杂的多的 组件
Project Name: testSQLCOM
Class Name: TestMath
Public Function AddMe(a As Long, b As Long) As Long
AddMe = a + b
End Function
编译生成后,我们就可以在 Sql Server 中对这个 Com 组件进行调用了
declare @i int
declare @intRet int
declare @intRetCode int
DECLARE @strErr varchar (255)
DECLARE @strErr1 varchar (255)
/* 首先创建Com 实例 */
exec @ret_code = sp_OACreate "testSQLCOM.TestMath", @i out
IF @intRetCode <> 0
BEGIN
/* 创建实例 失败 */
EXEC sp_OAGetErrorInfo @i, @strErr OUT, @strErr1 OUT
PRINT "创建实例失败,失败的原因是:: " + @strErr + " " + @strErr1
RETURN
END

/* 创建成功,开始调用 */
EXEC @intRetCode = sp_OAMethod @i,'AddMe',@ret OUT,100,200
IF @intRetCode <> 0
BEGIN
/* 调用方法出错 */
EXEC sp_OAGetErrorInfo @i, @strErr OUT, @strErr1 OUT
PRINT "调用方法失败,失败的原因是:: " + @strErr + " " + @strErr1
EXEC sp_OADestroy @i
RETURN
END
PRINT "返回的结果是" + Str(@intRet)
exec sp_OADestroy @i

以前是存储过程的输出

Step 4:
返回的结果是 300
方欣 2003-08-25
  • 打赏
  • 举报
回复
回 pengdali(大力 V2.0) 大侠:
我希望的是char * function(char *)的形式,返回一个varchar,而不是返回一个整型。
liuyun2003 2003-08-25
  • 打赏
  • 举报
回复
收藏先。
pengdali 2003-08-25
  • 打赏
  • 举报
回复
在存储过程中调用外部的动态连接库(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
myckd 2003-08-25
  • 打赏
  • 举报
回复
先写一个扩张存储过程,然后用SQL语句写一个函数,在函数中调用此存储过程!这样的话,调用函数就和调用存储过程效果一样。

22,206

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧