[UDF系列]如何創建InterBase UDF

[UDF系列之五]:如何創建InterBase UDF<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

by Paul McGee (c) Borland Internation Inc.

Warton

[概述]:

用戶定義函數(UDF)是一種採用編譯語言編寫的函數,是用戶爲執行自定義的功能和常用的任務面設計的。UDF 允許程序員模塊化一個數據庫應用程序,並能嵌入到數據庫以增強數據庫自身的功能。UDF 也總是在數據庫服務器端執行。這可以減少網絡通信量。

UDF可以執行事務比如獲得服務器上可用硬盤空間,清理字符串的空格,爲一系列值計算標準偏差等等。UDF能完成任何功能只要編程語言能夠表達出來。這種編程語言能常是在C和C++之間選擇(當然,用戶可以用其它語言,比如pascal 譯者注)。

UDF在提供SQL語言不能處理的功能、查詢、更新數據庫,以及爲異源客戶工作站提供通用函數方面非常有效。

與其它功能相比,使用UDF要花費一些代價。這主要表現在兩方面:第一,在UNIX或VMS平臺,UDF是模塊化AST程序,這意謂着當UDF在執行時,沒有其它的存取操作可以發生。這就要求我們儘量使UDF儘可能的小和有效率。第二,如果數據庫服務器崩潰,你需要將數據轉移到另一臺機器上。你必須首先在新的服務器上安裝UDF。如果在相同的操作系統下,這並不難。但是當轉移到另一操作系統時,你只少需要編譯一遍UDF庫的源代碼。

[UDF示例]:

     InterBase包含幾個內置SQL 函數:UPPER,GEN_ID,CAST 。UPPER將一個字符串轉爲大寫。GEN_ID生成一個唯一長整型值,因爲一個特殊的生成器已經在數據庫中定義。這在生成主鍵時是非常有用的,比如客戶編號或職員編號。CAST將一種類型列轉化爲另一種類型的列。

    InterBase 也提供了另外一些UDF的源代碼,在examples目錄下。它們包含在udflib.c文件中。這裏定義的UDF有:lower, strcat, substr, trim, trunc, doy, moy, dow, sysdate, add2, mul, fact, abs, maxnum, sqrt, blob_linecount, blob_bytecount, substr_blob。Lower是將字符串轉化爲小寫串。Strcat連接兩個字符串。Substr返回字符串的一部分。Trim清空字符串中的空格。Trunc返回刪節後的串。doy(day of year),moy(month of year),dow(day of week)。Sysdate返回當前日期以字符串的形式(“mmm-dd-yyyy”).add2將兩整數相加在一起。Mul將兩double數相乘.maxnum返回兩數中較大者。Sqrt爲取平方。blob_bytecount返回blob的大小。Substr_blob,取blob的一部分文本。

    我們將增加幾個新的UDF:rtrim, left, right, swapcase, imonth, iday, iyear。Rtrim去掉字符串右邊的空格。Left返回一個輸入串前n個字符的串。Right則是返回右過n個字符的串。Swapcase將小寫轉大寫並將大寫轉小寫。imonth返回月份的值(1-12)。Iday返回day的值(1-31)。Iyear返回年的值如:2002。

[編寫UDF]:

    一旦你編寫的UDF,你必須創建一個動態鏈接庫,以便上UDF可以使用。然後你必須在數據庫中定義它。

在數據定義語言中定義 UDFs 非常簡單,基本的語法是:

DEFINE EXTERNAL FUNCTION name [<datatype> | CSTRING (int)

                [, <datatype> | CSTRING (int) ...]]

                RETURNS {<datatype> [BY VALUE] | CSTRING (int)}

                ENTRY_POINT "<entryname>"

                MODULE_NAME "<modulename>" ;

Name是指函數的名稱,它可達到31個字符長。第一個datatype是輸入參數。Datatype指標準的interbase數據類型:INTEGER, CHAR, VARCHAR等。或者,你可以使用CSTRING這個C風格沒用結束的字符數組。Entry_point指實際的函數名。在InterBase提供示例中,SQL函數名是lower而實際函數名在udflib.c中爲fn_lower_c。模塊名指的是函數被編譯後的輸出庫名。例如:這裏用SQL 定義函數lower和substr。

        DEFINE EXTERNAL FUNCTION lower

                VARCHAR (256)

                RETURNS CSTRING (80)

                ENTRY_POINT "fn_lower_c" MODULE_NAME "funclib";

       

        DEFINE EXTERNAL FUNCTION substr

                CSTRING (256), SMALLINT, SMALLINT

                RETURNS CSTRING (80)

                ENTRY_POINT "fn_substr" MODULE_NAME "funclib";

爲了將函數加入到函數庫中,在NT上使用Borland C++,我們應該讓lib模塊有有一個本地的拷貝:

 implib mygds32.lib /interbas/bin/gds32.dll

然後連接必要的選項生成我們新的庫funclib.dll。

 

bcc32 -v -a4 -DWIN32 -tWM -tWCD -efunclib.dll udf.c mygds32.lib

爲了在本地使用DLL,它必須在BIN目錄下(或你環境變的路徑中)。如果要在遠程使用,它必須在能運行InterBase服務的用戶的環境變量路徑之中,默認情況下,它在系統賬戶的PATH中。

[使用UDF]:

一但編譯,連接,定義之後,一個UDF就可以在SQL 語句中使用了。

它們可以做如下使用:定義計算後字段做爲表定義的一部分,在view定義中中做爲列表達式或在存儲過程和觸發器中做爲SELECT, INSERT, UPDATE, DELETE操作的一部分。

例如,使用計算結果做爲字段:

        CREATE TABLE name ( FIRST_NAME VARCHAR(20), LAST_NAME VARCHAR(20),

                FULL_NAME_UPPER COMPUTED BY

                (upper(FIRST_NAME) | " " | upper(LAST_NAME)));

view中做爲一個列表達式:

        CREATE VIEW upper_names (FIRST_NAME, LAST_NAME) AS

                SELECT upper(n.first_name), upper(n.last_name) FROM name n;

在選擇操作中:

        SELECT substr(n.FIRST_NAME, 2, 4) FROM name n WHERE

                upper(n.LAST_NAME) = '<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />MOORE';

在插入操作中:

        INSERT INTO name (FIRST_NAME, LAST_NAME)

                VALUES (rtrim(:new_fname), rtrim(:new_lname));

在更新操作中:

        UPDATE name SET LAST_NAME = rtrim(:new_lname) WHERE

                upper(n.LAST_NAME) = 'JONES';

在刪除操作中:

        DELETE FROM name WHERE left(LAST_NAME, 3) = 'SMI';

 

 

本主來自:MER Systems Inc..  http://www.mers.com

 

發佈了35 篇原創文章 · 獲贊 1 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章