2014-09-19 45 views
5

我有一個編碼爲'UTF8'的Postgresql 9.3數據庫。但是,數據庫中有一列不應包含除ASCII以外的任何內容。如果非ascii進入,它會導致我無法控制的另一個系統出現問題。因此,我想爲該列添加約束。注意:我已經有了一個BEFORE INSERT觸發器 - 所以這可能是一個檢查的好地方。Postgresql約束檢查非ASCII字符

在PostgreSQL中完成此操作的最佳方式是什麼?

回答

8

您可以定義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); 

,但它不可能是超高效,而且使用的子查詢會迫使你在觸發器而不是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位)編碼,所以這種方法是不可能的。

3

使用圍繞regular expression構建的CHECK約束。

假設你的意思是某列不應該包含什麼,但小寫字母從一個ž,大寫字母從一個ž,以及數字通過 ,像這樣的東西應該工作。

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

這是當他們談論「只有ASCII」相對於數據庫列人們通常意味着,但ASCII還包括標點符號字形,算術運算符,等你想允許去之間的字符方括號。