外部程序使一切變得簡單
2024-07-21 02:38:50
供稿:網(wǎng)友
外部程序其實是儲存在DLL或是共享庫中的二進制程序,并且可以通過PL/SQL聲明從存儲程序中訪問得到它。這既使得它們成為了存儲程序開發(fā)者們最強大的開發(fā)工具之一。
但是,事實上人們很少使用這些外部程序,也許是因為人們覺得創(chuàng)建DLL和共享庫,安裝程序以及引用PL/SQL這一系列過程讓人覺得非常繁瑣。而對應(yīng)的文檔并不能起到什么幫助作用,因為這些文檔提供的都是一些深奧的例子,它描述了使用的變量以及子程序使問題變得更加令人費解。
你可以在許多不同的程序編譯語言中來創(chuàng)建DLL以及共享庫,你也可通過轉(zhuǎn)化腳本語言為二進制代碼來實現(xiàn)DLL以及共享庫的創(chuàng)建。DLL與共享庫作為獨立與操作系統(tǒng)的一部分,其實就是像調(diào)用執(zhí)行文件的一部分那樣被連接和調(diào)用的具有公共入口的二進制映像。這里有一個用C描述的用于二進制處理的DLL:
/* bitop.c */
#ifdef WIN32
#define DLLEXP __declspec(dllexport)
#else
#define DLLEXP
#endif /* WIN32 */
DLLEXP int bitand(int r,int l) { return r & l; }
DLLEXP int bitor(int r,int l) { return r l; }
DLLEXP int bitxor(int r,int l) { return r ^ l; }
DLLEXP int bitshr(int n,int s) { return n << s; }
DLLEXP int bitshl(int n,int s) { return n >> s; }
DLLEXP int bitset(int n,int b) { return n (1<<b); }
DLLEXP int bitclr(int n,int b) { return n ^ (1<<b); }
DLLEXP int bittst(int n,int b) { return (n & (1<<b)) ? 1 : 0; }
其中唯一超出標(biāo)準(zhǔn)C范圍的就是DLLEXP宏,他為Windows提供了這些函數(shù)名并且可能被UNIX所忽視。將這些資源代碼與你的編譯文檔相對照,從而你可以從中了解更多關(guān)于如何創(chuàng)建DLL的信息。在UNIX環(huán)境下使用GNU編譯器的話,則包括以下命令行:
GNU C/C++: cc -shared -o libbitop.so.1 bitop.c
從數(shù)據(jù)庫中調(diào)用DLL和共享庫的下一步就是使用CREATE LIBRARY命令,并給出完整的路徑,例如:
CREATE OR REPLACE LIBRARY SCOTT.bitop AS '/home/scott/bitop/libbitop.so.
通常只有DBA賬號擁有執(zhí)行這個命令的權(quán)限,但此命令可通過其他用戶的行為發(fā)出。
然后,這個用戶能調(diào)用PL/SQL和外部程序來調(diào)用任何DLL和共享庫,代碼如下:
create or replace package bit_op
as
function bit_and(l pls_integer,r pls_integer) return pls_integer
as language c name "bitand" library bitop;
--
function bit_or(r pls_integer,l pls_integer) return pls_integer
as language c name "bitor" library bitop;
--
function bit_xor(r pls_integer,l pls_integer) return pls_integer
as language c name "bitxor" library bitop;
--
function bit_shr(n pls_integer,s pls_integer) return pls_integer
as language c name "bitshr" library bitop;
--
function bit_shl(n pls_integer,s pls_integer) return pls_integer
as language c name "bitshl" library bitop;
--
function bit_set(n pls_integer,b pls_integer) return pls_integer
as language c name "bitset" library bitop;
--
function bit_clr(n pls_integer,b pls_integer) return pls_integer
as language c name "bitclr" library bitop;
--
function bit_tst(n pls_integer,b pls_integer) return pls_integer
as language c name "bittst" library bitop;
end bit_op;
/
注重這個過程不需要程序包。
假如數(shù)據(jù)庫已經(jīng)設(shè)立好可以接受通過監(jiān)聽器發(fā)出的外部程序請求,那么這個過程就完成了。然后你就可以使用以下的查詢命令:
select bit_op.bit_and(24,56) from dual where bit_op.bit_tst(24,5) = 1;
假如你沒有建立好數(shù)據(jù)庫來接收外部指令請求,那么你必須配置其他的監(jiān)聽器來完成內(nèi)部聯(lián)接。
外部程序請求將通過SQL*Net發(fā)送給專門的監(jiān)聽服務(wù)。再Oracle8i中,許多這種過程都是手工處理的。而在Oracle9i中,大部分可以通過設(shè)置完成了。
即設(shè)在你的數(shù)據(jù)庫中存在tnsnames.ora這樣一個文件,你要確保你有能告訴客戶端怎樣聯(lián)接到數(shù)據(jù)庫并發(fā)出外部請求的設(shè)置,設(shè)置如下:
EXTPROC_CONNECTION_DATA.world =
(DESCRipTION=
(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC_KEY))
(CONNECT_DATA=(SID=EXTPROC_AGENT))
)
請注重,EXTPROC_CONNECTION_DATA,這個名字是強制不變的。而.world則需要設(shè)置為與你的數(shù)據(jù)庫具有相同的域。同時EXTPROC_KEY和EXTPROC_AGENT則必須與你的listener.ora文件中的設(shè)置相匹配。其中l(wèi)istener.ora文件設(shè)置如下:
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/ora81)
(PROGRAM = EXTPROC)
)
)
在Oracle9i數(shù)據(jù)庫中,EXTPROC_CONNECTION_DATA應(yīng)該已經(jīng)被定義用于連接PLSExtProc,并且能在你自己的外部請求中使用。但是,任何沒有在監(jiān)聽方的環(huán)境變量EXTPROC_DLL 中明確指出的DLL,Oracle9i都拒絕了對其的訪問權(quán),從而增加了一些附加安全定義。在外部過程中,這個變量需要使用SID_DESC中的ENV參數(shù),具體代碼如下:
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = /u01/app/oracle/prodUCt/9.2.0)
(PROGRAM = extproc)
(ENVS="EXTPROC_DLLS=ANY")
)
(SID_DESC =
(GLOBAL_DBNAME = ikan.us.oracle.com)
(ORACLE_HOME = /u01/app/oracle/product/9.2.0)
(SID_NAME = ikan)
)
)
為了得到更好的安全性,變量EXTPROC_DLLS可以設(shè)置為DLL序列或是共享庫序列。也可以設(shè)為ANY從而與敘訪問任何DLL和共享庫。你可以通過一下這條命令手工的進行連接測試: