问题描述
我正在使用 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,'^\d{4}[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 ^\d{4}[A-Z]?$
时,它可以同时匹配1234X
和1234
。 Here is a link到使用我在REGEXP_LIKE函数中使用的RegEx的RegEx测试工具。非常感谢!
解决方法
经过一番挖掘,我发现数据类型为roomNo
的{{1}}是此问题的罪魁祸首。
根据char(5)
in here上的Oracle文档:
在CHAR数据库列中插入字符值时,Oracle不会删除尾随空格。如果该值短于该列的定义宽度,则Oracle空白该值至定义宽度
当我将char
插入表中时,由于1234
的长度比列的定义宽度短(即宽度为5),因此Oracle在字符串的右侧添加了空白填充以便将字符串存储为1234
,并在1234
之后留一个空格。
因此,由于字符串的最后一个字符(即空格)与1234
不匹配,因此字符串1234
无法与RegEx ^\d{4}[A-Z]?$
匹配。
我能想到的解决方案是使用[A-Z]
的RegEx,以便它可以匹配位于第5个字符的单个空格。
编辑:
另一种解决方案是使用^\d{4}[A-Z ]?$
函数删除右侧的尾部空格:
RTRIM()