触发器问题

[复制链接]
查看11 | 回复5 | 2005-2-28 12:57:00 | 显示全部楼层 |阅读模式
能不能利用触发器实现这样一种功能:
当一个表中的内容被update的时候,可以调用unix下面的proc可执行程序?
回复

使用道具 举报

千问 | 2005-2-28 12:57:00 | 显示全部楼层
通过oracle的外部过程调用应该可以实现
回复

使用道具 举报

千问 | 2005-2-28 12:57:00 | 显示全部楼层
能不能说详细一点啊
请问
回复

使用道具 举报

千问 | 2005-2-28 12:57:00 | 显示全部楼层
应该是可行的啊。
回复

使用道具 举报

千问 | 2005-2-28 12:57:00 | 显示全部楼层
在C语言中可以通过预编译器PRO*C来嵌入PL/SQL,但是在PL/SQL里能否调用C的过程和函数呢?答案是肯定的。
ORACLE8以上版本开始支持在PL/SQL里调用C及JAVA(8I后)等程序的库函数,那么具体怎么实现呢?其实很简单,下面我们来看一个例子就很清楚了:
主要步骤有以下几点:
1、编写C函数,并保存在oracle服务器上(必须是与数据库在同一服务器上或者将保存路径映射到服务器上,不然ORACLE不能调用);
2、将C函数编译并链接成动态库(必须是动态库,因为只有动态库才能被动态调用,windows下是*.dll,unix/linux下是*.so);
3、把生成的动态库存放在安装oracle数据库的操作系统用户有读和执行权的目录下;
4、检查ORACLE监听配置,看是否有配置监听分裂进程extproc;
5、在ORACLE中创建库进服务器下的动态库进行映射;
6、在ORACLE中创建函数或过程对库里的过程和函进行封装和引用;
7、调用ORACLE中的函数或过程来执行外部过程;

下面是对上述步骤进行具体说明:
(1)、我们用c写一个小函数,其功能是传入“文件名”和“字符串”两个参数,然后把“字符串”添加到“文件名”指定的文件后面,成功返回0,失败返回-1,具体如下:
/*
文件名:textout.c
*/
#include
int AppendToFile(const char *FileName,const char *Text)
{
FILE *FP;
if (!(FP=fopen(FileName,"a&quot

)){

return -1;
}
fputs(Text,FP);
fclose(FP);
return 0;
}

(2)、然后,我们用以下的命令编译textout.c成为一个共享动态库(以下是linux下的命令,如果是UNIX系统请根据具体命令格式生成动态库):

gcc -c textout.c

ld -m elf_i386 -shared -o libtextout.so -soname libtextout.a textout.o

(或:gcc -shared -Wl,-soname,libtextout.a -O3 -o libtextout.so textout.o)


(3)、上述命令会生成两个动态库,其中一个(-soname后所指明的副本)的存取权限为“777”,就是所有的用户对些文件都有全部的操作权(保证ORACLE用户可以读取并调用此库);但是,此时ORACLE用户还不一定有对此库的执行权,因为该文件所有的目录,对ORACLE用户来说并不一定有读和执行权限,所以,我们还要保证保存库文件的目录还要能够让ORACLE用户访问,所以我们可以用chmod命令对文件所在目录及其所有父目录的进行权限设置或将库拷到/usr/lib中去;在这里我选择将目录设为可读写的。
(4)、检查监听配置(通常在$ORACLE_HOME/network/admin/listener.ora中)。因为执行调用C的动态库需要ORACLE监听进行分裂出一个进程extproc来执行,所以我们的监听必须配置有extproc:
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC)) #这是extproc的IPC配置
)
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
)
)
(DESCRIPTION =
(PROTOCOL_STACK =
(PRESENTATION = GIOP)
(SESSION = RAW)
)
(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 2481))
)
)
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = /u01/app/oracle/product/8.1.7)
(PROGRAM = extproc)
#这是extproc的监听配置
)
(SID_DESC =
(GLOBAL_DBNAME = oracle.local)
(ORACLE_HOME = /u01/app/oracle/product/8.1.7)
(SID_NAME = ora1)
)
)
(5)、在ORACLE中创建库进服务器下的动态库进行映射:
create or replace library WRTLOG
as '/home/test/c/libtextout.a';--这是动态库的存放路径
(6)、在ORACLE中创建函数或过程对库里的过程和函进行封装和引用:
create or replace function AppendDiskLog(
sFileName varchar2,
sMsgvarchar2)
return Binary_integer
as external
--声明是外部引用
library WRTLOG   --引用库
NAME "AppendToFile"--库中函数名
PARAMETERS (sFileName String,sMsg STRING);--参数对应
(7)、调用ORACLE中的函数或过程来执行外部过程:
select code_type||' * '||code||' - '||mean as Line_value,
Decode(AppendDiskLog('/home/test/c/logfile.log',code_type||' * '||code||' - '||mean||chr(10)),0,'写入成功','写入失败') as WriteRlt
from tab
上述SQL语句,如果正常执行,OK,调用C库成功了!如果返回字段"WriteRlt"的值为“写入成功”,则linux后台“/home/test/c/”目录下会生成一个名为“logfile.log”的文件,其内容为返回字段“Line_value”的所有行;
如果执行出错,请根据错误提示检查上面各步中哪步出错了!
回复

使用道具 举报

千问 | 2005-2-28 12:57:00 | 显示全部楼层
以上我在RedHat Linux7.2/Oracle8.1.7下调试通过。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行