PostgreSQL:.csv 正则表达式 - 测试字符串(数字)中的重复子字符串
PostgreSQL: .csv regex - test for repeating substrings within a string (digits)
简介:
我在 PostgreSQL 中有以下场景,我想在将 .csv 字符串插入 table 之前对它执行一些数据验证(参见 fiddle here) .
我已经设法得到一个正则表达式(在 CHECK
约束中),它不允许字符串中有空格(例如“12 34
”)并且也不允许前面的零(“00343
").
现在,锦上添花的是,如果我可以使用正则表达式来禁止包含重复整数的字符串 - 即,如果序列 \d+
与同一序列中的另一个 \d+
匹配字符串。
这是否超出了正则表达式的能力范围?
我的table如下:
CREATE TABLE test
(
data TEXT NOT NULL,
CONSTRAINT d_csv_only_ck
CHECK (data ~ '^([ ]*([1-9]\d*)+[ ]*)(,[ ]*([1-9]\d*)+[ ]*)*$')
);
我可以按如下方式填充它:
INSERT INTO test VALUES
('992,1005,1007,992,456,456,1008'), -- want to make this line unnacceptable - repeats!
('44,1005,1110'),
('13, 44 , 1005, 10078 '), -- acceptable - spaces before and after integers
('11,1203,6666'),
('1,11,99,2222'),
('3435'),
(' 1234 '); -- acceptable
但是:
INSERT INTO test VALUES ('23432, 3433 ,00343, 567'); -- leading 0 - unnacceptable
失败了(它应该如此),也失败了(再次,它应该如此)
INSERT INTO test VALUES ('12 34'); -- spaces within numbers - unnacceptable
问题:
但是,如果您注意到第一个字符串,它会重复 992
和 456
。
我希望能够匹配这些。
所有这些规则不必在同一个正则表达式中 - 我可以使用第二个 CHECK
约束。
我想知道我所问的是否可以使用正则表达式?
我确实找到了这个 which appears to go some (all?) of the way to solving my issue, but I'm afraid it's beyond my skillset to get it to work - I've included a small test at the bottom of the fiddle。
如果您需要任何进一步的信息,请告诉我。
p.s。顺便说一句,我对正则表达式不是很有经验,我欢迎任何关于我上面的基本的输入。
自从 PostegreSQL 正则表达式 does not support backreferences 以来,您不能应用此限制,因为您需要一个带有反向引用的否定前瞻。
看看这个 PCRE 正则表达式:
^(?!.*\b(\d+)\b.*\b\b) *[1-9]\d* *(?:, *[1-9]\d* *)*$
参见 this regex demo。
详情:
^
- 字符串开头
(?!.*\b(\d+)\b.*\b\b)
- 字符串中的任何位置都不允许出现与整个单词相同的两个数字
*
- 零个或多个空格
[1-9]\d*
- 一个非零数字,然后是任何零个或多个数字
*
- 零个或多个空格
(?:, *[1-9]\d* *)*
- 零次或多次出现
, *
- 逗号和零个或多个空格
[1-9]\d*
- 一个非零数字,然后是任何零个或多个数字
*
- 零个或多个空格
$
- 字符串结尾。
即使您在 PostgreSQL 代码中将 \b
替换为 \y
(PostgreSQL 正则表达式单词边界),由于答案顶部提到的缺点,它也不会工作。
简介:
我在 PostgreSQL 中有以下场景,我想在将 .csv 字符串插入 table 之前对它执行一些数据验证(参见 fiddle here) .
我已经设法得到一个正则表达式(在 CHECK
约束中),它不允许字符串中有空格(例如“12 34
”)并且也不允许前面的零(“00343
").
现在,锦上添花的是,如果我可以使用正则表达式来禁止包含重复整数的字符串 - 即,如果序列 \d+
与同一序列中的另一个 \d+
匹配字符串。
这是否超出了正则表达式的能力范围?
我的table如下:
CREATE TABLE test
(
data TEXT NOT NULL,
CONSTRAINT d_csv_only_ck
CHECK (data ~ '^([ ]*([1-9]\d*)+[ ]*)(,[ ]*([1-9]\d*)+[ ]*)*$')
);
我可以按如下方式填充它:
INSERT INTO test VALUES
('992,1005,1007,992,456,456,1008'), -- want to make this line unnacceptable - repeats!
('44,1005,1110'),
('13, 44 , 1005, 10078 '), -- acceptable - spaces before and after integers
('11,1203,6666'),
('1,11,99,2222'),
('3435'),
(' 1234 '); -- acceptable
但是:
INSERT INTO test VALUES ('23432, 3433 ,00343, 567'); -- leading 0 - unnacceptable
失败了(它应该如此),也失败了(再次,它应该如此)
INSERT INTO test VALUES ('12 34'); -- spaces within numbers - unnacceptable
问题:
但是,如果您注意到第一个字符串,它会重复 992
和 456
。
我希望能够匹配这些。
所有这些规则不必在同一个正则表达式中 - 我可以使用第二个 CHECK
约束。
我想知道我所问的是否可以使用正则表达式?
我确实找到了这个
如果您需要任何进一步的信息,请告诉我。
p.s。顺便说一句,我对正则表达式不是很有经验,我欢迎任何关于我上面的基本的输入。
自从 PostegreSQL 正则表达式 does not support backreferences 以来,您不能应用此限制,因为您需要一个带有反向引用的否定前瞻。
看看这个 PCRE 正则表达式:
^(?!.*\b(\d+)\b.*\b\b) *[1-9]\d* *(?:, *[1-9]\d* *)*$
参见 this regex demo。 详情:
^
- 字符串开头(?!.*\b(\d+)\b.*\b\b)
- 字符串中的任何位置都不允许出现与整个单词相同的两个数字*
- 零个或多个空格[1-9]\d*
- 一个非零数字,然后是任何零个或多个数字*
- 零个或多个空格(?:, *[1-9]\d* *)*
- 零次或多次出现, *
- 逗号和零个或多个空格[1-9]\d*
- 一个非零数字,然后是任何零个或多个数字*
- 零个或多个空格
$
- 字符串结尾。
即使您在 PostgreSQL 代码中将 \b
替换为 \y
(PostgreSQL 正则表达式单词边界),由于答案顶部提到的缺点,它也不会工作。