我有一个Postgresql 9.3数据库,编码为'UTF8'。但是,数据库中有一列不应包含除ASCII之外的任何内容。如果非ascii进入那里,它会导致另一个我无法控制的系统出现问题。因此,我想为列添加约束。注意:我已经有一个BEFORE INSERT触发器 - 所以这可能是一个检查的好地方。
在PostgreSQL中实现此目的的最佳方法是什么?
答案 0 :(得分:8)
为此,您可以将ASCII
定义为ordinal 1 to 127
,因此以下查询将标识带有"非ascii"的字符串。值:
SELECT exists(SELECT 1 from regexp_split_to_table('abcdéfg','') x where ascii(x) not between 1 and 127);
但它不太可能超级高效,并且使用子查询会强制您在触发器而不是CHECK约束中执行此操作。
相反,我使用正则表达式。如果您想要所有可打印字符,那么您可以在检查约束中使用范围,例如:
CHECK (my_column ~ '^[ -~]*$')
this will match everything from the space to the tilde,这是可打印的ASCII范围。
如果您想要所有ASCII,可打印和不可打印的,可以use byte escapes:
CHECK (my_column ~ '^[\x00-\x7F]*$')
最严格的正确方法是convert_to(my_string, 'ascii')
,如果失败则会引发异常......但PostgreSQL不提供ascii
(即7位)编码,所以这种方法是不可能的。
答案 1 :(得分:3)
使用围绕regular expression构建的CHECK约束。
假设您的意思是某个列永远不应包含除 a 到 z 的小写字母以外的任何内容,则 A 中的大写字母为 Z ,数字 0 到 9 ,这样的事情应该有效。
alter table your_table
add constraint allow_ascii_only
check (your_column ~ '^[a-zA-Z0-9]+$');
人们通常在谈论"只有ASCII"关于数据库列,但ASCII还包括标点符号,算术运算符等的字形。您想要允许的字符位于方括号之间。