Oracle SQL - REGEXP_LIKE 在 CHECK 约束中没有按预期工作
Posted
技术标签:
【中文标题】Oracle SQL - REGEXP_LIKE 在 CHECK 约束中没有按预期工作【英文标题】:Oracle SQL - REGEXP_LIKE not working as expected in CHECK constraint 【发布时间】:2020-10-24 04:27:41 【问题描述】:我正在使用 Oracle SQL,并且我想添加一个 CHECK 约束,以便在创建表时检查正则表达式。但是,REGEXP_LIKE 函数的行为与在线 RegEx 测试工具不同。
假设我想创建一个名为Testing
的表,其中只有一个名为roomNo
的属性。我希望roomNo
只存储 4 个数字,可选地后跟一个大写字母(例如,1234
、1234A
):
CREATE TABLE Testing (
roomNo char(5),
CONSTRAINT check_roomNo CHECK (REGEXP_LIKE(roomNo, '^\d4[A-Z]?$'))
);
insert into Testing values ('1234X');
insert into Testing values ('1234'); -- Unexpected error here
当我运行这个脚本时,我可以成功地将1234X
插入到表中,但是Oracle SQL 在插入1234
时会抛出一个错误:
Error starting at line : 5 in command -
insert into Testing values ('1234')
Error report -
ORA-02290: check constraint (USER.CHECK_ROOMNO) violated
我不太明白为什么这是一个错误,因为当我在在线 RegEx 测试工具中测试 RegEx ^\d4[A-Z]?$
时,它可以匹配 1234X
和 1234
。 Here is a link 到使用我在 REGEXP_LIKE 函数中使用的 RegEx 的 RegEx 测试工具。非常感谢!
【问题讨论】:
【参考方案1】:经过一番挖掘,我发现roomNo
的数据类型为char(5)
是这个问题的罪魁祸首。
根据char
in here上的Oracle文档:
当您将字符值插入 CHAR 数据库列时,Oracle 不会去除尾随空格。如果值小于列的定义宽度,Oracle 将值填充到定义的宽度
当我在表中插入1234
时,由于1234
的长度比列的定义宽度短(即宽度为5),Oracle 在字符串的右侧添加空白填充,以便字符串存储为1234
,1234
后面有一个空格。
因此,字符串1234
无法匹配正则表达式^\d4[A-Z]?$
,因为字符串的最后一个字符(即空格)不匹配[A-Z]
。
我能想到的一个解决方案是使用^\d4[A-Z ]?$
的正则表达式,以便它可以匹配位于第 5 个字符的单个空格。
编辑:
另一种解决方案是使用RTRIM()
函数去除右边的拖尾空格:
CONSTRAINT check_roomNo CHECK (REGEXP_LIKE(RTRIM(roomNo), '^\d4[A-Z]?$'))
【讨论】:
有;由于值的长度不固定为 5 个字符,请切换到 VARCHAR2 数据类型。 这也是我的第一个想法。char
只是麻烦 - 我的建议是避免它,除非您确实需要将尾随空格附加到较短的值。我无法想象为什么有人会想要附加尾随空格。以上是关于Oracle SQL - REGEXP_LIKE 在 CHECK 约束中没有按预期工作的主要内容,如果未能解决你的问题,请参考以下文章
Oracle SQL - REGEXP_LIKE 包含字符串“NA”以外的字符
Oracle:Oracle 8i 中 REGEXP_LIKE 函数的替代方案