外部程序其实是储存在DLL或是共享库中的二进制程序并且可以通过PL/SQL声明从存储程序中访问得到它这既使得它们成为了存储程序开发者们最强大的开发工具之一 但是事实上人们很少使用这些外部程序也许是因为人们觉得创建DLL和共享库安装程序以及引用PL/SQL这一系列过程让人觉得非常繁琐而对应的文档并不能起到什么帮助作用因为这些文档提供的都是一些深奥的例子它描述了使用的变量以及子程序使问题变得更加令人费解 你可以在许多不同的程序编译语言中来创建DLL以及共享库你也可通过转化脚本语言为二进制代码来实现DLL以及共享库的创建DLL与共享库作为独立与操作系统的一部分其实就是像调用执行文件的一部分那样被连接和调用的具有公共入口的二进制映像这里有一个用C描述的用于二进制处理的DLL /* bitopc */ #ifdef WIN #define DLLEXP __declspec(dllexport) #else #define DLLEXP #endif /* WIN */ DLLEXP int bitand(int rint l) { return r & l; } DLLEXP int bitor(int rint l){ return r | l; } DLLEXP int bitxor(int rint l) { return r ^ l; } DLLEXP int bitshr(int nint s) { return n << s; } DLLEXP int bitshl(int nint s) { return n >> s; } DLLEXP int bitset(int nint b) { return n | (<<b); } DLLEXP int bitclr(int nint b) { return n ^ (<<b); } DLLEXP int bittst(int nint b) { return (n & (<<b)) ? : ; } 其中唯一超出标准C范围的就是DLLEXP宏他为Windows提供了这些函数名并且可能被UNIX所忽视将这些资源代码与你的编译文档相对照从而你可以从中了解更多关于如何创建DLL的信息在UNIX环境下使用GNU编译器的话则包括以下命令行 GNU C/C++: cc shared o libbitopso bitopc 从数据库中调用DLL和共享库的下一步就是使用CREATE LIBRARY命令并给出完整的路径例如 CREATE OR REPLACE LIBRARY SCOTTbitop AS /home/scott/bitop/libbitopso 通常只有DBA账号拥有执行这个命令的权限但此命令可通过其他用户的行为发出 然后这个用户能调用PL/SQL和外部程序来调用任何DLL和共享库代码如下 create or replace package bit_op as function bit_and(l pls_integerr pls_integer) return pls_integer as language c name bitand library bitop;
function bit_or(r pls_integerl pls_integer) return pls_integer as language c name bitor library bitop;
function bit_xor(r pls_integerl pls_integer) return pls_integer as language c name bitxor library bitop;
function bit_shr(n pls_integers pls_integer) return pls_integer as language c name bitshr library bitop;
function bit_shl(n pls_integers pls_integer) return pls_integer as language c name bitshl library bitop;
function bit_set(n pls_integerb pls_integer) return pls_integer as language c name bitset library bitop;
function bit_clr(n pls_integerb pls_integer) return pls_integer as language c name bitclr library bitop;
function bit_tst(n pls_integerb pls_integer) return pls_integer as language c name bittst library bitop; end bit_op; / 注意这个过程不需要程序包如果数据库已经设立好可以接受通过监听器发出的外部程序请求那么这个过程就完成了然后你就可以使用以下的查询命令 select bit_opbit_and() from dual where bit_opbit_tst() = ; 如果你没有建立好数据库来接收外部指令请求那么你必须配置其他的监听器来完成内部联接 外部程序请求将通过SQL*Net发送给专门的监听服务再Oraclei中许多这种过程都是手工处理的而在Oraclei中大部分可以通过设置完成了 即设在你的数据库中存在tnsnamesora这样一个文件你要确保你有能告诉客户端怎样联接到数据库并发出外部请求的设置设置如下 EXTPROC_CONNECTION_DATAworld = (DESCRIPTION= (ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC_KEY)) (CONNECT_DATA=(SID=EXTPROC_AGENT)) ) 请注意EXTPROC_CONNECTION_DATA这个名字是强制不变的而world则需要设置为与你的数据库具有相同的域同时EXTPROC_KEY和EXTPROC_AGENT则必须与你的listenerora文件中的设置相匹配其中listenerora文件设置如下 EXTERNAL_PROCEDURE_LISTENER = (ADDRESS_LIST = (ADDRESS = (PROTOCOL=IPC)(KEY=EXTPROC_KEY)) ) SID_LIST_EXTERNAL_PROCEDURE_LISTENER = (SID_LIST = (SID_DESC = (SID_NAME=EXTPROC_AGENT) (ORACLE_HOME = c:\oracle\ora) (PROGRAM = EXTPROC) ) ) 在Oraclei数据库中EXTPROC_CONNECTION_DATA应该已经被定义用于连接PLSExtProc并且能在你自己的外部请求中使用但是任何没有在监听方的环境变量EXTPROC_DLL 中明确指出的DLLOraclei都拒绝了对其的访问权从而增加了一些附加安全定义在外部过程中这个变量需要使用SID_DESC中的ENV参数具体代码如下 SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (SID_NAME = PLSExtProc) (ORACLE_HOME = /u/app/oracle/product/) (PROGRAM = extproc) (ENVS=EXTPROC_DLLS=ANY) ) (SID_DESC = (GLOBAL_DBNAME = ) (ORACLE_HOME = /u/app/oracle/product/) (SID_NAME = ikan) ) ) 为了得到更好的安全性变量EXTPROC_DLLS可以设置为DLL序列或是共享库序列也可以设为ANY从而与叙访问任何DLL和共享库你可以通过一下这条命令手工的进行连接测试 |