我想为没有控制字符且周围没有空格的文本行定义一个域。
另外,我想要一个具有相同限制的域,除了它允许嵌入没有前置空格的新行(任何行上都没有尾随空格的文本块)。
经过一些实验,我对文本行有两种可行的解决方案:
CREATE DOMAIN textline1 AS text
CHECK ((VALUE = btrim(VALUE)) AND
(VALUE !~ '[[:cntrl:]]') AND
(length(VALUE) > 0));
CREATE DOMAIN textline2 AS text
CHECK ((VALUE = btrim(VALUE)) AND
(VALUE !~ '[^[:print:]]') AND
(length(VALUE) > 0));
两者都有效,但我不确定它们是最有效的。我的用例不包括非常大的表,因此性能并不重要,但最大限度地提高效率仍然很好。
对于我尝试过的第二种情况
CREATE DOMAIN textblock AS text
CHECK ((VALUE = btrim(VALUE, E' \n')) AND
(VALUE !~ E'[[^:print:]\n]') AND
(VALUE !~ E' \n') AND
(length(VALUE) > 0));
这可行,但似乎过于复杂,我不确定效率,但尚未提出替代定义。
原帖中的检查条件比必要的更复杂:每个域都可以使用单个正则表达式进行检查。
以下两个域定义满足所描述的要求:
CREATE DOMAIN textline AS TEXT CHECK (VALUE ~ '^(?=\S)[[:print:]\t]*(?<=\S)$');
CREATE DOMAIN textblock AS TEXT CHECK (VALUE ~ '^(?=\S)[[:print:]\n\r\t]*(?<=\S)$');
其中每一个都使用单个正则表达式来验证值。这些表达式应该相当有效。由于它们仅在分配值时执行,因此除了执行大量批量插入或更新之外,最佳效率不应成为重要问题。表达式之间的唯一区别是
textblock
接受嵌入的回车符和换行符,但 textline
拒绝嵌入的回车符和换行符。检查从值开头的零长度前瞻开始,以确保第一个字符不属于 space
类。下一部分验证该值是否仅包含允许的字符。最后一次检查是在值末尾进行零长度向后查找,以确保最后一个字符不属于 space
类。
用于检查
textline
的正则表达式已使用以下查询和结果进行了审查:
WITH
test_cases (id, label, value, accept) AS (
VALUES
(1, 'empty text', '', FALSE),
(2, 'newline only text', E'\n', FALSE),
(3, 'space only text', ' ', FALSE),
(4, 'text with leading whitespace', ' a', FALSE),
(5, 'text with trailing whitespace', 'a ', FALSE),
(6, 'control characters', CHR(1), FALSE),
(7, 'multiline text', E'a\nz', FALSE),
(8, 'single non-space printable character', 'a', TRUE),
(9, 'text with no spaces', 'az', TRUE),
(10, 'text with embedded spaces', 'a z', TRUE),
(11, 'text with embedded tabs', E'a\tz', TRUE)
)
SELECT
id,
label,
accept,
accept IS NOT DISTINCT FROM (value ~ '^(?=\S)[[:print:]\t]*(?<=\S)$') AS passed
FROM
test_cases;
id | 标签 | 接受 | 通过了 |
---|---|---|---|
1 | 空文本 | 假 | 真实 |
2 | 仅换行文本 | 假 | 真实 |
3 | 仅限空格文本 | 假 | 真实 |
4 | 带有前导空格的文本 | 假 | 真实 |
5 | 带有尾随空格的文本 | 假 | 真实 |
6 | 控制字符 | 假 | 真实 |
7 | 多行文本 | 假 | 真实 |
8 | 单个非空格可打印字符 | 真实 | 真实 |
9 | 文字不带空格 | 真实 | 真实 |
10 | 带有嵌入空格的文本 | 真实 | 真实 |
11 | 带有嵌入选项卡的文本 | 真实 | 真实 |
使用相同的过程来验证
textblock
的表达式:
WITH
test_cases (id, label, value, accept) AS (
VALUES
(1, 'empty text', '', FALSE),
(2, 'newline only text', E'\n', FALSE),
(3, 'space only text', E' ', FALSE),
(4, 'text with leading whitespace', ' x', FALSE),
(5, 'text with trailing whitespace', 'x ', FALSE),
(6, 'control characters', CHR(1), FALSE),
(7, 'multiline text', E'a\nz', TRUE),
(8, 'single non-space printable character', 'a', TRUE),
(9, 'text with no spaces', 'az', TRUE),
(10, 'text with embedded spaces', 'a z', TRUE),
(11, 'text with embedded tabs', E'a\tz', TRUE),
(12, 'text with embedded carriage returns', E'a\rz', TRUE)
)
SELECT
id,
label,
accept,
accept IS NOT DISTINCT FROM (value ~ '^(?=\S)[[:print:]\n\r\t]*(?<=\S)$') AS passed
FROM
test_cases;
id | 标签 | 接受 | 通过了 |
---|---|---|---|
1 | 空文本 | 假 | 真实 |
2 | 仅换行文本 | 假 | 真实 |
3 | 仅限空格文本 | 假 | 真实 |
4 | 带有前导空格的文本 | 假 | 真实 |
5 | 带有尾随空格的文本 | 假 | 真实 |
6 | 控制字符 | 假 | 真实 |
7 | 多行文本 | 真实 | 真实 |
8 | 单个非空格可打印字符 | 真实 | 真实 |
9 | 文字不带空格 | 真实 | 真实 |
10 | 带有嵌入空格的文本 | 真实 | 真实 |
11 | 带有嵌入选项卡的文本 | 真实 | 真实 |
12 | 嵌入回车符的文本 | 真实 | 真实 |