正则表达式约束拒绝Postgresql中看似有效的数据

时间:2018-08-21 14:47:28

标签: sql regex postgresql constraints

在pgAdmin 4 v3.0中使用Postgres 10.3

我在表 my_table 的列 gridref 上对GB国家网格引用具有约束:

ALTER TABLE my_table
ADD CONSTRAINT my_table_gridref_check 
CHECK (gridref::text 
~~ '[A-Z][A-Z][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'::text);

我有一个网格引用,看起来与该格式匹配(AB12345678-即2 alpha,8数值-不是真实的网格引用,而是有效的模式),但是在尝试插入具有该值的记录时,插入失败在这种限制下,出现此错误

ERROR: new row for relation "my_table" violates check constraint "my_table_gridref_check"

但是,如果我愿意

SELECT select regexp_matches('AB12345678',
'[A-Z][A-Z][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]')

然后我得到包含该网格参考的单项集。

所有这些似乎都表明应该接受网格引用 (这是我所期望的),所以我不明白为什么触发了约束。

有什么主意我做错了吗?在Postgres中使用正则表达式作为约束是否存在限制或陷阱?

1 个答案:

答案 0 :(得分:1)

我必须在文档中进行查找:

  

运算符~~等同于LIKE,~~ *等同于ILIKE。

Postgres不支持LIKE中的字符范围。

您想要~(或regexp_match()):

CHECK (gridref::text ~ '[A-Z][A-Z][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'::text);

我猜你真的想要:

CHECK (gridref::text ~ '^[A-Z][A-Z][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$'::text);

请注意锚点,以使其与整个字符串匹配。

或更简单地说:

CHECK (gridref::text ~ '^[A-Z]{2}[0-9]{8}$'::text);