SQL筆記:Microsoft SQL Server的Unicode N Prefix問題

在 SQL Server 中處理 Unicode 字串常數時,您必需在所有的 Unicode 字串前加上大寫字母 N 做為前置詞,如《SQL Server 線上叢書》主題<使用 Unicode 資料>所述。「N」前置詞代表的是 SQL-92 標準中的國家語言,且必須為大寫。如果您沒有在 Unicode 字串常數前面加上 N 做為前置詞,則 SQL Server 會在使用字串前,先將其轉換成目前資料庫的非 Unicode 字碼頁。

這個標記法是為現有應用程式提供回溯相容性的必要項目。例如,"SELECT 'Hello'" 必須繼續傳回非 Unicode 字串,因為許多應用程式會預期這是 SQL Server 6.5 的行為,而 SQL Server 6.5 不支援 Unicode 資料;而加入新語法 “SELECT N'Hello'" 可以在 SQL Server 7.0 之間來回傳送 Unicode 字串。

每當您傳送 Unicode 資料至 SQL Server 的時候,都必須在 Unicode 字串前面加上 N 做為前置詞。如果應用程式有啟用 Unicode,並且沒有為 Unicode 字串常數加上 N 做為前置詞就將資料傳送至 SQL Server 7.0,則可能會遇到字元資料遺失的情況。如果 SQL Server 將沒有加上 N 做為前置詞的 Unicode 字串,從 Unicode 轉換成 SQL Server 資料庫字碼頁,則 Unicode 字串中任何不存在於 SQL Server 字碼頁中的字元將會遺失。請注意,此轉譯與 Autotranslation、OemToAnsi 或 AutoAnsiToOem 轉換無關,這些轉換都是發生在用戶端的 ODBC、OLEDB 或資料程式庫層。

如果應用程式並沒有將 Unicode 資料傳送至 SQL Server,且用戶端的 ANSI 字碼頁和 SQL Server 字碼頁相符合,就不需要在字串常數前面加上 N 做為前置詞,您也不會因為沒加上前置詞而造成資料遺失。然而,SQL Server 7.0 可以讓您在安裝期間選取不同於排序順序的 Unicode 定序;在某些情況下,這可能會造成以 N 為前置詞的字串的相關作業,與沒有前置詞的作業產生不同的結果。例如,假設安裝 SQL Server 7.0 時,選取了二進位編碼排序順序 (排序順序是用於比較非 Unicode 字串時),並選取標準 Unicode 做為 Unicode 定序 (Unicode 定序是用於比較 Unicode 字串)。比較兩個非 Unicode 字串 ("ABC" = "abc") 的運算式會傳回 False,因為根據二進位編碼排序順序,大寫字母 A 並不等於小寫字母 a。相對地,運算式 (N'ABC' = N'abc') 會傳回 True。因為字串前面有加上 N 做為前置詞,字串就會被轉換成 Unicode,並使用 Unicode 定序來比較這些字串。與二進位編碼排序順序不同的是,標準 Unicode 定序不會區分大小寫,所以會將這兩個字串視為相同。

請注意,如果這兩個字串常數運算元中,有一個加上 N 前置詞,而另一個沒有加上 N 前置詞,則非 Unicode 字串會轉換成 Unicode,且比較這兩個字串時會使用 Unicode 定序。

微軟官方對於 nvarchar 欄位編碼,要 insert 或 select 前面必須要加上 N 字元的解答:You must precede all Unicode strings with a prefix N when you deal with Unicode string constants in SQL Server

※ 其實,如果你不是跨資料庫進行交易之類的工作,在同一個資料庫下且為Microsoft SQL Server 2008版以後,有沒有加 N 其實都沒有問題。跨資料庫查詢的話就要特別注意這個問題了,例如SQL Server 2000跟SQL Server 2005對查之類的,就要很小心,建議加上比較保險,以免出現靈異現象。

Microsoft SQLServer Unicode NVarChar N-Prefix