程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> DB2數據庫 >> DB2教程 >> DB2中實現正則表達式(1)

DB2中實現正則表達式(1)

編輯:DB2教程

正則表達式

正則表達式用於查找和替換字符串中的模式。正則表達式是用某種語法定義的,正則表達式引擎采用這種語法並將它與字符串進行比較。引擎返回字符串是否與語法匹配的指示;也即,該字符串是否包含能夠從該語法派生的子串。此外,引擎還能夠返回匹配的子串。術語“模式(pattern)”用來表示語法。

最基本的模式僅由單個字母組成。當與該模式進行比較時,包含這個字母的字符串就是一個“匹配”。例如,如果模式是“a”,則字符串“abcd”就是一個匹配,而字符串“xyz”則不是。正則表達式的強大功能來自於預定義的運算符(也稱為元字符),它們可以用很小的空間來表示模式。根據“方言”和受支持的功能,可以使用不同的元字符。通常,其中的一些可用字符如下:

| — 二中擇一[ ] — 分組* — 多次出現(也匹配零次出現)+ — 多次出現(至少一次)? — 隨意的出現次數\\\\ — 反斜槓

不同的系統實現了常用正則表達式的各種擴展。編程語言 Perl 中使用的正則表達式支持進一步的縮寫。本文中所用的庫實現了這些擴展。下面摘錄了其中部分可以在 Perl 正則表達式語言中使用的縮寫:

\\s — 任意空白字符\\w — 任意字母數字字符\\d — 任意數字字符

另一個更高級的示例是模式“[A-Z]* = ([0-9]|0x00);”。與這個模式相匹配的字符串包含這樣的子串:它由幾個大寫字母、後面跟上一個空格、一個等號、另一個空格,然後是一個數字或字符串“0x00”組成。該子串的最後一個字符必須是分號。使用 Perl,這個模式可以表示為“\\w* = (\\d|0x00);”。“NM = 0x00;”和“X = 7;”是兩個可以與該模式匹配的字符串。但字符串“Z = 123;”不能匹配,因為 123 是由三個數字所組成的。

DB2 中的字符串匹配

除了 Extender 以外,DB2 還允許幾種用於文本比較的函數和運算符。但那些函數和運算符要麼在用於模式匹配的功能方面有限制,要麼就是會給可能使用它們的查詢帶來復雜性。這裡簡要地摘錄幾個可用的功能:

= 或 <> 謂詞:逐字符地比較兩個字符串是否相等。
LIKE 謂詞:使用通配符的基本模式匹配。
LOCATE 函數:在字符串中查找子串。

盡管也可以用 SQL 運算符表示模式“[A-Z]* = ([0-9]|0x00);”,但那樣會很麻煩。例如,下列 SELECT 語句的 WHERE 子句中所使用的謂詞會匹配字符串“str”中等號之後的部分,如 清單 1所示:

清單 1. 使用 LIKE 匹配模式

SELECT strFROM   strTableWHERE ( str LIKE '% = 0;%' OR str LIKE '% = 1;%' OR str LIKE '% = 2;%' OR str LIKE '% = 3;%' OR str LIKE '% = 4;%' OR str LIKE '% = 5;%' OR str LIKE '% = 7;%' OR str LIKE '% = 7;%' OR str LIKE '% = 8;%' OR str LIKE '% = 9;%' OR str LIKE '% = 0x00;%' )

這增加了可以匹配“[A-Z]*”子模式的謂詞的復雜度,這可以使用對整個字符串進行迭代並進行逐字符比較的函數來完成,但您會發現使用內置功能既冗長又復雜。

示例方案

讓我們定義下列清單( 清單 2)並插入幾行:

清單 2. 創建我們的樣本表

CREATE TABLE strTable ( c1 INTEGER, str VARCHAR(500) );INSERT INTO strTable VALUES ( 1, 'some text;' ),                            ( 2, 'variable = 1234;' ),                            ( 3, 'var2 = ''string variable'';' ),                            ( 4, 'xyz = ' ),                            ( 5, 'myVar = 0x00;' ),                            ( 6, '# comment' ),                            ( 7, 'abc = def' );                            

這個 清單及其數據被用於下面的所有示例。

SELECT * FROM strTable;C1          STR----------- ------------------------------          1 some text;          2 variable = 1234;          3 var2 = 'string variable';          4 xyz =           5 myVar = 0x00;          6 # comment          7 abc = def  7 record(s) selected.

實現模式匹配函數

您可以使用 DB2 的可擴展機制,在 SQL 語句內使用 UDF,以便顯著地改善這種情形。通過定義名為 regex1 的 UDF(它采用模式和字符串作為輸入參數), 清單 1中的 WHERE 子句現在可以寫得象 清單 3中所示的那樣:

清單 3. 使用 regex UDF 來簡化模式匹配

SELECT strFROM   strTableWHERE regex1('\\w* = (\\d|0x00);', str) = 1

在本示例中,使用帶有 Perl 擴展的正則表達式來匹配完整的模式,而不僅僅是 清單 1中給出的 LIKE 謂詞所對應的部分模式。正如您所看到的,使用函數來為該模式編寫謂詞比用 LIKE 謂詞表示同樣的語義要容易得多。

實現 UDF

在我的示例實現中,我選擇了現有的名為 PCRE(Perl 兼容的正則表達式,Perl-compatible regular expression)的模式匹配引擎。該引擎提供了用來處理模式和執行匹配的 C API。該引擎和查詢中所用的 SQL 語言之間“缺失的部分”是 UDF。該 UDF 由兩部分組成:

  • 在數據庫中創建(或注冊)該函數的 CREATE FUNCTION 語句。
  • 該函數的主體,它實現了用於正則表達式匹配引擎的 C API 調用的封裝器

清單 4顯示了用於創建該函數的 SQL 語句。

清單 4. 注冊 regex1 函數

CREATE FUNCTION regex1(pattern VARCHAR(2048), string CLOB(10M))    RETURNS INTEGER    SPECIFIC regexSimple    EXTERNAL NAME 'regexUdf!regexpSimple'    LANGUAGE C    PARAMETER STYLE DB2SQL    DETERMINISTIC    NOT FENCED    RETURNS NULL ON NULL INPUT    NO SQL    NO EXTERNAL ACTION    ALLOW PARALLEL;

注:請參閱 DB2 SQL Reference以獲取所有子句的詳細含義。可以修改參數的長度以適應您的需求。我在此處展示某些值並沒有任何推薦使用它們的用意。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved