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(DB2认证 DB2培训 ) 中的字符串匹配

除了 Extender 以外,DB2 还允许几种用于文本比较的函数和运算符。但那些函数和运算符要么在用于模式匹配的功能方面有限制,要么就是会给可能使用它们的查询带来复杂性。这里简要地摘录几个可用的功能:

= 或 谓词:逐字符地比较两个字符串是否相等。

LIKE 谓词:使用通配符的基本模式匹配。

LOCATE 函数:在字符串中查找子串。

尽管也可以用 SQL 运算符表示模式“[A-Z]* = ([0-9]|0x00);”,但那样会很麻烦。例如,下列 SELECT 语句的 WHERE 子句中所使用的谓词会匹配字符串“str”中等号之后的部分,如 清单 1所示:

清单 1. 使用 LIKE 匹配模式

SELECT str

FROM strTable

WHERE ( 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 str

FROM strTable

WHERE 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以获取所有子句的详细含义。可以修改参数的长度以适应您的需求。我在此处展示某些值并没有任何推荐使用它们的用意。

第二部分由一小段 C 代码组成,它实现了 UDF 入口点。在查询执行期间,DB2 为每个要与模式匹配的行调用这个入口点。 清单 5中的示例列出了该代码的清单。有关 pcre_* 函数和宏的描述,请参考 PCRE 库的文档。有关 C 代码的编译和共享库的构建,请参考 DB2 Application Development Guide。

清单 5. 实现 rege1x UDF 入口点的 C 代码

#include

#include

void regexpSimple(

// input parameters

SQLUDF_VARCHAR *pattern, SQLUDF_CLOB *str,

// output

SQLUDF_INTEGER *match,

// null indicators

SQLUDF_NULLIND *pattern_ind, SQLUDF_NULLIND *str_ind,

SQLUDF_NULLIND *match_ind,

SQLUDF_TRAIL_ARGS)

{

pcre *re = NULL;

const char *error = NULL;

int errOffset = 0;

int rc = 0;

// we assume successful return

*match_ind = 0;

// compile the pattern to its internal representation

re = pcre_compile(pattern, 0 /* default options */, &error,

&errOffset, NULL);

if (re == NULL) {

snprintf(SQLUDF_MSGTX, 70, "Regexp compilation failed at "

"offset %d: %s\\n", errOffset, error);

strcpy(SQLUDF_STATE, "38900");

(*pcre_free)(re);

return;

}

// match the string againts the pattern

rc = pcre_exec(re, NULL, str->data, str->length, 0,

0 /* default options */, NULL, 0);

switch (rc) {

case PCRE_ERROR_NOMATCH:

*match = 0;

break;

case PCRE_ERROR_BADOPTION:

snprintf(SQLUDF_MSGTX, 70, "An unrecognized bit was set in the "

"options argument");

strcpy(SQLUDF_STATE, "38901");

break;

case PCRE_ERROR_NOMEMORY:

snprintf(SQLUDF_MSGTX, 70, "Not enough memory available.");

strcpy(SQLUDF_STATE, "38902");

break;

default:

if (rc < 0) {

snprintf(SQLUDF_MSGTX, 70, "A regexp match error "

"occured: %d", rc);

strcpy(SQLUDF_STATE, "38903");

}

else {

*match = 1;

}

break;

}

// cleanup

(*pcre_free)(re);

return;

}

用法示例

下列查询试图从表 strTable 中找出包含注释文本的所有字符串。注释以“#”开头,所以模式是“#”后跟非空文本。

SELECT c1, str

FROM strTable

WHERE regex1(‘#\\s*\\w+‘, str) = 1;

结果只包含 c1 = 6 的行。

C1 STR

----------- -------------------------

6 # comment;

1 record(s) selected.

在第二个示例中,我们试图找到这种赋值形式的字符串;即“text = text”。为了进一步缩小范围,我们只查找那些右端为数值的赋值。将十六进制表示法作为有效数值对待。

SELECT c1, str

FROM strTable

WHERE regex1(‘\\w+\\s*=\\s*(\\d+|0x\\d\\d)‘, str) = 1;

除了 c1 为 2 或 5 的两行以外,其它行都不包含数值的赋值,因此不会出现在结果中:

C1 STR

----------- -------------------------

2 variable = 1234;

5 myVar = 0x00;

2 record(s) selected.

时间: 2024-10-06 08:52:13

DB2中如何实现正则表达式的相关文章

DB2中如何将非自动存储转换成自动存储空间管理方式

DB2 10引入根据温度管理数据存储的表空间更管理方式,但是需要数据库启用自动存储管理,具体在存储路径在某个目录下即可,要讲非自动存储的表空间转换成自动存储的管理方式需要两个步骤,尤其是从低版本升级过来的数据库. ALTER DATABASE EMPLOYEE ADD STORAGE ON '/data' 这样即可,但是对于原来使用DMS或SMS方式管理的表空间需要做重定向恢复,其实就是先做全备份,然后指定redirect restore即可,在原来的实例下恢复: RESTORE DATABAS

DB2中循环日期跑数据

1.数据库版本: 2.具体实现方式: CREATE OR REPLACE PROCEDURE DB2USER.RUN_PROCEDURE_BY_LOOP(IN begin_date VARCHAR(8),IN end_date VARCHAR(8)) /****************************************************************************** NAME: PURPOSE: REVISIONS: Ver Date Author De

Sybase脚本移植到DB2中

? DB2 目前碰到一个任务,需要将原本基于Sybase的系统移植到DB2.前期工作中主要都是对SQL脚本的改写.鉴于目前对Sybase和DB2都不是很熟,所以开此记录日志.记录在过程中所遇到的各种问题. db2中的系统表介绍 DB2 Command Line Processor(DB2 CLP)是所有 DB2 产品中都有的,可以使用这个应用程序运行 DB2 命令.操作系统命令或 SQL 语句. 在 DB2 数据库被创建的时候,DB2 会创建一些系统表.这些系统表中记录了所有数据库对象的信息,表

iOS中3种正则表达式的使用与比较

之前我在博文中介绍过iOS中自带正则表达式的使用( 传送门),后来我发现其实iOS中有三种方式来实现正则表达式的匹配.现在将他们都记录在这里: 1.利用NSPredicate(谓词)匹配 例如匹配有效邮箱: NSString *email = @“[email protected]163.com”: NSString *regex = @"[A-Z0-9a-z._%+-][email protected][A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"; NSPredic

DB2中的is null与=‘’

在DB2中,null和''是完全不同的两个东西. NULL是一个不确定值它不能通过列值过滤,只能通过IS NULL 或者IS NOT NULL方式过滤 而''可以用in,=,<>,>,<来比较判断. 此外,若一个属性的值为null,则select显示时,会以-代替,而''则直接什么都不显示

DB2 中日期 比较

在DB2中的Date 一共识别三种格式,最常见的是这样 '2013-12-12' 对,你没看错,DB2认为这样的字符串就是Date数据 然后我们可以利用函数这样寻找日期区间 select * from users where g_time between '2003-05-04 ' and '2003-05-08' 也可以利用操作符来进行常规的日期大小比较 select * from users where g_time >= '2003-05-04 ' 这篇文档更加详细http://www.c

DB2中三个有关锁变量DB2_EVALUNCOMMITTED,DB2_SKIPDELETED和DB2_SKIPINSERTED的使用

本文主要解释下DB2中三个有关锁变量DB2_EVALUNCOMMITTED,DB2_SKIPDELETED和DB2_SKIPINSERTED的使用 实验环境: DB2 v9.7.0.6 AIX 6.1.0.0 採用默认的隔离级别CS STUDENT表的DDL与初始内容 CREATE TABLE "E97Q6C  "."STUDENT"  ( "AGE" INTEGER , "NAME" CHAR(8) ) IN "U

PHP中的常用正则表达式集锦

PHP中的常用正则表达式集锦: 匹配中文字符的正则表达式: [\u4e00-\u9fa5] 评注:匹配中文还真是个头疼的事,有了这个表达式就好办了 匹配双字节字符(包括汉字在内):[^\x00-\xff] 评注:可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1) 匹配空白行的正则表达式:\n\s*\r 评注:可以用来删除空白行 匹配HTML标记的正则表达式:<(\S*?)[^>]*>.*?</\1>|<.*? /> 评注:网上流传的版本太糟糕,

DB2中的系统表SYSIBM.SYSDUMMY1

ORACLE中有一张系统数据库表DUAL用来访问系统的相关信息 SELECT SYSDATE FROM DUAL;  --返回当前系统日期 ----------------------------------------------------------------------------------------- db2中的系统表为SYSIBM.SYSDUMMY1,不太好记 SELECT CURRENT DATE FROM SYSIBM.SYSDUMMY1  --返回当前系统日期SELECT