Postgresql约束检查非ascii字符

Dav*_*d S 6 postgresql postgresql-9.3

我有一个Postgresql 9.3数据库编码'UTF8'.但是,数据库中有一列不应包含除ASCII之外的任何内容.如果非ascii进入那里,它会导致另一个我无法控制的系统出现问题.因此,我想为列添加约束.注意:我已经有一个BEFORE INSERT触发器 - 所以这可能是一个检查的好地方.

在PostgreSQL中实现这一目标的最佳方法是什么?

Cra*_*ger 9

您可以定义ASCIIordinal 1 to 127用于此目的,因此下面的查询将确定为"非ASCII"值的字符串:

SELECT exists(SELECT 1 from regexp_split_to_table('abcdéfg','') x where ascii(x) not between 1 and 127);
Run Code Online (Sandbox Code Playgroud)

但它不太可能超级高效,并且使用子查询会强制您在触发器而不是CHECK约束中执行此操作.

相反,我会使用正则表达式.如果您想要所有可打印字符,则可以在检查约束中使用范围,例如:

CHECK (my_column ~ '^[ -~]*$')
Run Code Online (Sandbox Code Playgroud)

这将匹配从空间到波浪号的所有内容,这是可打印的ASCII范围.

如果您想要所有ASCII,可打印和不可打印,您可以使用字节转义:

CHECK (my_column ~ '^[\x00-\x7F]*$')
Run Code Online (Sandbox Code Playgroud)

最严格的正确方法是,convert_to(my_string, 'ascii')如果失败则引发异常......但PostgreSQL不提供ascii(即7位)编码,因此这种方法是不可能的.


Mik*_*ll' 5

使用围绕正则表达式构建的 CHECK 约束。

假设您的意思是某个列不应该只包含从az的小写字母、从AZ的大写字母以及数字09,这样的事情应该可以工作。

alter table your_table
add constraint allow_ascii_only
check (your_column ~ '^[a-zA-Z0-9]+$');
Run Code Online (Sandbox Code Playgroud)

这就是人们在谈论与数据库列有关的“仅 ASCII”时通常的意思,但 ASCII 还包括用于标点符号、算术运算符等的字形。您希望允许在方括号之间放置的字符。