【问题标题】:Oracle SQL - REGEXP_LIKE not working as expected in CHECK constraintOracle SQL - REGEXP_LIKE 在 CHECK 约束中没有按预期工作
【发布时间】:2020-10-24 04:27:41
【问题描述】:

我正在使用 Oracle SQL,并且我想添加一个 CHECK 约束,以便在创建表时检查正则表达式。但是,REGEXP_LIKE 函数的行为与在线 RegEx 测试工具不同。

假设我想创建一个名为Testing 的表,其中只有一个名为roomNo 的属性。我希望roomNo 只存储 4 个数字,可选地后跟一个大写字母(例如,12341234A):

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]?$ 时,它可以匹配 1234X1234Here is a link 到使用我在 REGEXP_LIKE 函数中使用的 RegEx 的 RegEx 测试工具。非常感谢!

【问题讨论】:

    标签: sql regex oracle check-constraints


    【解决方案1】:

    经过一番挖掘,我发现roomNo的数据类型为char(5)是这个问题的罪魁祸首。

    根据charin here上的Oracle文档:

    当您将字符值插入 CHAR 数据库列时,Oracle 不会去除尾随空格。如果值小于列的定义宽度,Oracle 将值填充到定义的宽度

    当我在表中插入1234 时,由于1234 的长度比列的定义宽度短(即宽度为5),Oracle 在字符串的右侧添加空白填充,以便字符串存储为1234 1234 后面有一个空格。

    因此,字符串1234 无法匹配正则表达式^\d{4}[A-Z]?$,因为字符串的最后一个字符(即空格)不匹配[A-Z]

    我能想到的一个解决方案是使用^\d{4}[A-Z ]?$ 的正则表达式,以便它可以匹配位于第 5 个字符的单个空格。

    编辑:

    另一种解决方案是使用RTRIM()函数去除右边的拖尾空格:

    CONSTRAINT check_roomNo CHECK (REGEXP_LIKE(RTRIM(roomNo), '^\d{4}[A-Z]?$'))
    

    【讨论】:

    • 有;由于值的长度不固定为 5 个字符,请切换到 VARCHAR2 数据类型。
    • 这也是我的第一个想法。 char 只是麻烦 - 我的建议是避免它,除非您确实需要将尾随空格附加到较短的值。我无法想象为什么有人会想要附加尾随空格。
    猜你喜欢
    • 2017-02-15
    • 1970-01-01
    • 2013-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多