1. 程式人生 > 其它 >在資料庫中自定義外部函式(r4筆記第56天)

在資料庫中自定義外部函式(r4筆記第56天)

在oracle中可以使用pl/sql來實現一些複雜的功能,同時可以通過自定義的外部函式來實現很多豐富的功能,我們可以基於c/c++來寫一些函式,然後把動態連結庫放入ORACLE_HOME中方便直接呼叫。 首先這種實現方法需要依賴於資料庫層面的服務extproc,監聽器會生成一個extproc程序,然後專門來處理外部函式的呼叫。 具體的配置可以在$ORACLE_HOME/network/admin下的listener.ora和tnsnames.ora中體現。 一般通過dbca建立的庫都會預設配置extproc的部分,可以看到它使用的是ipc協議而不是tcp協議。 樣例如下:

listener.ora LIST= (DESCRIPTION= (ADDRESS_LIST= (ADDRESS=(PROTOCOL=tcp)(HOST=rac1)(PORT=1599)) (ADDRESS=(PROTOCOL=ipc)(KEY=extproc)))) SID_LIST_LIST= (SID_LIST= (SID_DESC= (GLOBAL_DBNAME=TEST01) (ORACLE_HOME=/u03/ora11g/product/11.2.0/dbhome_1) (SID_NAME=TEST01)))

tnsnames.ora

EXTPROC01= (DESCRIPTION= (ADDRESS=(PROTOCOL=ipc)(key=extproc)) (CONNECT_DATA=(SERVICE_NAME=TEST01)) )

如果配置沒有問題,可以使用tnsping來驗證一下服務是否可用。 [ora11g@rac1 admin]$ tnsping extproc01 TNS Ping Utility for Linux: Version 11.2.0.3.0 - Production on 24-FEB-2015 06:03:53 Copyright (c) 1997, 2011, Oracle. All rights reserved. Used parameter files: Used TNSNAMES adapter to resolve the alias Attempting to contact (DESCRIPTION= (ADDRESS=(PROTOCOL=ipc)(key=extproc)) (CONNECT_DATA=(SERVICE_NAME=TEST01))) OK (0 msec) 接下來我們來實現一個簡單的函式,大過年的我們就以紅包為例。我們傳入紅包的金額,直接放大100倍。比如傳入8塊,直接輸出800.

cat test.c test(n) int n; { int lucky_money; lucky_money=100*n; return (lucky_money); }

對編寫的c程式做編譯,生成動態連結庫檔案,然後直接拷貝到$ORACLE_HOME/bin下 [ora11g@rac1 extproc]$ cc -shared -o test.so test.c [ora11g@rac1 extproc]$ ll total 12 -rw-r--r-- 1 ora11g dba 83 Feb 24 05:42 test.c -rwxr-xr-x 1 ora11g dba 5609 Feb 24 05:42 test.so [ora11g@rac1 extproc]$ cp test.so $ORACLE_HOME/bin 這個時候我們就開始建立庫檔案,指向test.so,然後把許可權賦予指定的使用者。 SQL> create or replace library test_code as '$ORACLE_HOME/bin/test.so'; / Library created.

SQL> grant execute on test_code to n1; Grant succeeded.

有了庫檔案,我們就開始定義函式,這個函式最終給會呼叫連結庫檔案 create or replace function func_test (x binary_integer) return binary_integer as language C library sys.test_code name "test"; /

到此為止就大功告成了,我們的函式就建立成功了,來簡單驗證一下。 set serveroutput on var lucky_money number; var amount number; exec :lucky_money :=8888; exec :amount := func_test(8888); print amount; SQL> AMOUNT ---------- 888800 這種方式能夠遮蔽程式碼層的抽象,直接開放豐富的功能,還是比較實用的。