Sql-Server

Arabic_100_CS_AS_KS_WS_SC_UTF8 和 Latin1_General_100_CS_AS_KS_WS_SC_UTF8 有什麼區別?

  • June 17, 2021

從 SQL Server 2019 開始,它支持 UTF-8 作為排序規則。但是,根據以下查詢:

SELECT COLLATIONPROPERTY('Arabic_100_CS_AS_KS_WS_SC_UTF8', 'CodePage')
SELECT COLLATIONPROPERTY('Latin1_General_100_CS_AS_KS_WS_SC_UTF8', 'CodePage');

65001兩者都返回Windows 中的 Unicode程式碼頁。此外,所有新的_UTF8排序規則都使用程式碼頁65001

SELECT * FROM sys.fn_helpcollations() WHERE name LIKE '%_UTF8';

Arabic_100_CS_AS_KS_WS_SC_UTF8using和Latin1_General_100_CS_AS_KS_WS_SC_UTF8as collat​​ion之間有什麼區別嗎?

是的,所有_UTF8排序規則都使用程式碼頁 65001,因為這UTF-8 的程式碼頁。您甚至可以通過以下方式在 DOS / 命令視窗中使用 65001:

chcp 65001

儘管並非所有程序和字型都可以與它無縫協作。

對於_UTF8排序規則,程式碼頁不受文化(即Latin1_Generalvs Arabic)的控制,_UTF8因為程式碼頁指示用於VARCHAR數據的特定 8 位編碼(即 8 位字元數據)。對於非 Unicode 8 位編碼,文化通常與作為字元集的程式碼頁相關聯(例如,Latin1 是程式碼頁 Windows-1252,它在 128-255 範圍內的字元與作為程式碼的 Windows-1255 不同希伯來語頁面)。但是對於 UTF-8,它8 位編碼,用於單數、無所不包的字元集,即 Unicode。

至於Arabic_100_CS_AS_KS_WS_SC_UTF8Latin1_General_100_CS_AS_KS_WS_SC_UTF8去之間的差異,它實際上只是對各種字元進行排序和比較的特定文化規則。當然,這兩種語言並沒有真正共享任何字元,但是在某些程式碼點的處理方式上仍然存在差異。

查看“Windows Server 2008 排序權重表”文件(據我所知,這是版本_100_排序規則的主要依據),我找不到這兩個排序規則之間的任何排序/比較差異。因此,就行為而言,它們可能是相同的。但是,在它們仍然具有不同的 LCID(區域設置/文化標識符)的意義上它們並不相同,因此將它們的值轉換為非 UTF8VARCHAR可能會導致數據失去/損壞,以及查看排序規則的任何程序/功能確定某些其他行為可能表現不同。


話雖如此,我確實找到了使用烏爾都語排序規則時阿拉伯字元行為差異的範例,因為這些排序規則確實對預設排序權重進行了一些修改(9 在“Windows Server 2008 排序權重表”文件中註冊) .

查看“Teh Marbuta”字元(U+0629),它在預設表(即用於美國英語/Latin1 的表)中的權重為 29,其排序權重低於“Peheh”字元(U +06A6),預設權重為 137。41 表示字元在哪個“腳本”中,這兩個都是阿拉伯字元。但是,烏爾都語排序規則將“Teh Marbuta”(U+0629)的排序權重修改為 183,然後其排序權重高於“Peheh”(U+06A6),仍然為 137。

-- Default
0x0629  41  29  2   2   ;Arabic Teh Marbuta -- ة
0x06a6  41  137 2   2   ;Arabic Peheh       -- ڦ

-- Urdu modifications
0x0629  41  183 2   2   ;Teh Marbuta        -- ة

如果我們使用Latin1_General_100_CS_AS_KS_WS_SC_UTF8or對這兩個字元進行排序Arabic_100_CS_AS_KS_WS_SC_UTF8,我們應該得到預設行為。而且,即使我們使用Yakut排序規則,它使用西里爾字母並且對預設排序權重有自己的修改,它不會修改這些阿拉伯字元中的任何一個,因此它們的行為應該與使用Latin1_GeneralArabic排序規則時相同:

SELECT *
FROM   (VALUES (1, NCHAR(0x0629)), (2, NCHAR(0x06a6))) tmp(ID, TheChar)
ORDER BY tmp.[TheChar] COLLATE Latin1_General_100_CS_AS_KS_WS_SC_UTF8 ASC

SELECT *
FROM   (VALUES (1, NCHAR(0x0629)), (2, NCHAR(0x06a6))) tmp(ID, TheChar)
ORDER BY tmp.[TheChar] COLLATE Arabic_100_CS_AS_KS_WS_SC_UTF8 ASC


SELECT *
FROM   (VALUES (1, NCHAR(0x0629)), (2, NCHAR(0x06a6))) tmp(ID, TheChar)
ORDER BY tmp.[TheChar] COLLATE Yakut_100_CS_AS_KS_WS_SC_UTF8 ASC

上面顯示的所有三個查詢都返回以下結果:

ID    TheChar
1     ة
2     ڦ

但是,當我們切換到Urdu排序規則時,這兩個字元的順序確實發生了變化:

SELECT *
FROM   (VALUES (1, NCHAR(0x0629)), (2, NCHAR(0x06a6))) tmp(ID, TheChar)
ORDER BY tmp.[TheChar] COLLATE Urdu_100_CS_AS_SC_UTF8 ASC

返回:

ID    TheChar
2     ڦ
1     ة

最後,請記住,雖然很少遇到這種情況,但排序規則也會影響大寫/小寫映射。我相信這僅限於Azeri_*Turkish排序規則,並且僅限於字母“i”和“I”(這些文化有一個帶點的大寫“I”和一個不帶點的小寫“i”),但仍然最好注意潛在的:

SELECT UPPER(N'i' COLLATE Arabic_100_CS_AS_KS_WS_SC_UTF8) AS [Arabic],
  UPPER(N'i' COLLATE Turkish_100_CS_AS_KS_WS_SC_UTF8) AS [Turkish],
  UPPER(N'i' COLLATE Azeri_Cyrillic_100_CS_AS_KS_WS_SC_UTF8) AS [Azeri_Cyrillic],
  UPPER(N'i' COLLATE Azeri_Latin_100_CS_AS_KS_WS_SC_UTF8) AS [Azeri_Latin];

返回:

Arabic   Turkish   Azeri_Cyrillic   Azeri_Latin
I        İ         İ                İ

引用自:https://dba.stackexchange.com/questions/294387