DB2 內建字串比較功能有限:=/<> 僅精確比對,LIKE 僅支援 % _ 萬用字元,LOCATE 僅找子字串。複雜模式(如 \\w* = (\\d|0x00);)用 SQL 組合極其冗長且難維護。
利用 DB2 可擴充架構,以 C 語言封裝 PCRE (Perl Compatible Regular Expressions) 函式庫,建立標量 UDF regex1(pattern, string) 回傳 1/0 表示比對成功與否。
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;
NOT FENCED:進程內執行,效能最佳;需確保 C 代碼健壯,避免導致 DB2 引擎崩潰。DETERMINISTIC:相同輸入必得相同輸出,利於優化器重寫。
-- 範例表
CREATE TABLE strTable (c1 INT, 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');
-- 使用 regex1 簡潔比對
SELECT str FROM strTable
WHERE regex1('\\w* = (\\d|0x00);', str) = 1;
結果將精確命中第 2、5 筆,避開 LIKE 需列舉 0~9 十個條件的笨拙寫法。
pcre.h,連結 libpcre。PARAMETER STYLE DB2SQL:void regexpSimple(SQLUDF_VARCHAR *pattern, SQLUDF_CLOB *str, SQLUDF_INTEGER *result, SQLUDF_NULLIND *patInd, SQLUDF_NULLIND *strInd, SQLUDF_NULLIND *resInd, SQLUDF_TRAIL_ARGS)*resInd = -1 返回。pcre_compile(pattern, 0, &errptr, &erroffset, NULL)。pcre_exec(re, NULL, str->data, str->length, 0, 0, ovector, OVECCOUNT)。pcre_free(re)。.dll/.so),置於 sqllib/function 目錄。FENCED,上線前經嚴測再改 NOT FENCED。\\d \\w \\s 等),功能強大但複雜模式可能回溯導致效能劣化,建議加上執行逾時機制 (PCRE 8.30+ 支援 pcre_jit_stack 與匹配限制)。| 方案 | 優點 | 缺點 |
|---|---|---|
| SQL LIKE/LOCATE 組合 | 零部署、純 SQL | 複雜模式極難寫、效能差 |
| Java UDF (java.util.regex) | 跨平台、功能完整 | JVM 啟動開銷、FENCED 模式較慢 |
| C UDF + PCRE (本文) | 原生效能、Perl 語法、無外部依賴 | 需 C 開發部署、NOT FENCED 風險 |