Vurgu Duyarlı Sıralama


19

Bu iki SELECTifade neden farklı bir sıralama düzeniyle sonuçlanıyor?

USE tempdb;
CREATE TABLE dbo.OddSort 
(
    id INT IDENTITY(1,1) PRIMARY KEY
    , col1 NVARCHAR(2)
    , col2 NVARCHAR(2)
);
GO
INSERT dbo.OddSort (col1, col2) 
VALUES (N'e', N'eA')
    , (N'é', N'éB')
    , (N'ë', N'ëC')
    , (N'è', N'èD')
    , (N'ê', N'êE')
    , (N'ē', N'ēF');
GO

SELECT * 
FROM dbo.OddSort 
ORDER BY col1 COLLATE Latin1_General_100_CS_AS;
╔════╦══════╦══════╗
║ id ║ col1 ║ col2 ║
╠════╬══════╬══════╣
║ 1 ║ e ║ eA ║
║ 2 ║ é ║ éB ║
║ 4 ║ è ║ èD ║ - id 3 olmalı mı?
║ 5 ║ ê ║ êE ║
║ 3 ║ ë ║ ëC ║
║ 6 ║ ē ║ ēF ║
╚════╩══════╩══════╝
SELECT * 
FROM dbo.OddSort 
ORDER BY col2 COLLATE Latin1_General_100_CS_AS;
╔════╦══════╦══════╗
║ id ║ col1 ║ col2 ║
╠════╬══════╬══════╣
║ 1 ║ e ║ eA ║
║ 2 ║ é ║ éB ║
║ 3 ║ ë ║ ëC ║
║ 4 ║ è ║ èD ║
║ 5 ║ ê ║ êE ║
║ 6 ║ ē ║ ēF ║
╚════╩══════╩══════╝

Yanıtlar:


13

Bu soru veritabanlarıyla çok ilgili değil, daha çok Unicode kullanımı ve kuralları ile ilgilidir.

Dayanarak https://docs.microsoft.com/en-us/sql/t-sql/statements/windows-collation-name-transact-sql Latin1_General_100_CS_AS araçlarla: "Harmanlama kod sayfasına kural ve haritalar sıralama Latince1 Genel sözlüğünü kullanır 1252 "eklenmiştir CS = Büyük / Küçük Harfe Duyarlı ve AS = Accent Hassas.

Windows kod sayfası 1252 ile Unicode ( http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT ) arasındaki eşleme , uğraştığımız tüm karakterler için aynı değerleri gösterir (macron ile e hariç) Microsoft eşlemesinde mevcut olmayan, bu durumda ne yaptığına dair hiçbir fikrim yok), bu yüzden şimdilik Unicode araçlarına ve terminolojisine konsantre olabiliriz.

İlk olarak, tüm dizeleriniz için neyle uğraştığımızı bize bildirin:

0065  LATIN SMALL LETTER E
0041  LATIN CAPITAL LETTER A
00E9  LATIN SMALL LETTER E WITH ACUTE
0042  LATIN CAPITAL LETTER B
00EB  LATIN SMALL LETTER E WITH DIAERESIS
0043  LATIN CAPITAL LETTER C
00E8  LATIN SMALL LETTER E WITH GRAVE
0044  LATIN CAPITAL LETTER D
00EA  LATIN SMALL LETTER E WITH CIRCUMFLEX
0045  LATIN CAPITAL LETTER E
0113  LATIN SMALL LETTER E WITH MACRON
0046  LATIN CAPITAL LETTER F

Unicode Harmanlama Algoritması burada açıklanmıştır: https://www.unicode.org/reports/tr10/

Bazı kurallar içeriğe duyarlı olduğundan, sıralamanın birbiri ardına yalnızca bir karaktere bağlı olamayacağını açıklayan bölüm 1.3 "Bağlamsal Duyarlılık" konusuna bakın.

1.8'deki şu noktalara da dikkat edin:

Harmanlama, dizelerin bir özelliği değildir. Harmanlama sırası genel olarak birleştirme veya alt dize işlemleri altında korunmaz.

Varsayılan olarak, algoritma üç tamamen özelleştirilebilir seviyeden yararlanır. Latin alfabesi için bu seviyeler kabaca şöyledir:

alphabetic ordering
diacritic ordering
case ordering.

Ancak algoritma kendi başına biraz yoğundur. Bunun özü şöyledir: Kısaca belirtildiği gibi, Unicode Harmanlama Algoritması, karakterler için eşleme verileri içeren bir giriş Unicode dizesi ve bir Harmanlama Öğesi Tablosu alır. İşaretsiz bir 16 bit tam sayı dizisi olan bir sıralama anahtarı üretir. Bu şekilde üretilen iki veya daha fazla sıralama anahtarı, üretildikleri dizeler arasında doğru karşılaştırmayı sağlamak için ikili olarak karşılaştırılabilir.

Belirli Latin sıralama kurallarını burada görebilirsiniz: http://developer.mimer.com/collations/charts/latin.htm veya daha fazlası doğrudan ve özellikle MS SQL için: http://collation-charts.org/mssql/mssql. 0409.1252.Latin1_General_CS_AS.html

İçin ekarakter o gösterileri:

e E é É è È ê Ê ë Ë

Bu, sipariş verirken sonuçlarınızı açıklar, col1kod sayfası 1252'de ē bulunmadığı için, bununla ne yaptığına dair hiçbir fikrim yok.

Veya Unicode algoritmasını el ile yaparsak, http://www.unicode.org/Public/UCA/latest/allkeys.txt adresindeki DUCET'in anahtar değerini kullanarak :

adım 1: Normalleştirme formu D, böylece her durum şöyle olur:

e => U+0065
é => U+0065 U+0301
ë => U+0065 U+0308
è => U+0065 U+0300
ê => U+0065 U+0302
ē => U+0065 U+0304

2. adım, Harmanlama dizileri üretme (dosyada arama allkeys.txt)

e => [.1D10.0020.0002]
é => [.1D10.0020.0002] [.0000.0024.0002]
ë => [.1D10.0020.0002] [.0000.002B.0002]
è => [.1D10.0020.0002] [.0000.0025.0002]
ê => [.1D10.0020.0002] [.0000.0027.0002]
ē => [.1D10.0020.0002] [.0000.0032.0002]

adım 3, Form sıralama tuşları (her seviye için, her bir harmanlama dizisi içindeki her değeri alın, ardından 0000'ı sınırlayıcı olarak koyun ve bir sonraki seviye için tekrar başlayın)

e => 1D10 0000 0020 0000 0002
é => 1D10 0000 0020 0024 0000 0002 0002
ë => 1D10 0000 0020 002B 0000 0002 0002
è => 1D10 0000 0020 0025 0000 0002 0002
ê => 1D10 0000 0020 0027 0000 0002 0002
ē => 1D10 0000 0020 0032 0000 0002 0002

4. adım, Sıralama tuşlarını karşılaştırın (her bir değerin birer birer basit ikili karşılaştırması): Dördüncü değer, hepsini sıralamak için yeterlidir, böylece son sipariş şu şekilde olur:

e
é
è
ê
ë
ē

Aynı şekilde sipariş vermek için col2:

1. adım: NFD

eA => U+0065 U+0041
éB => U+0065 U+0301 U+0042
ëC => U+0065 U+0308 U+0043
èD => U+0065 U+0300 U+0044
êE => U+0065 U+0302 U+0045
ēF => U+0065 U+0304 U+0046

2. adım: Harmanlama dizileri

eA => [.1D10.0020.0002] [.1CAD.0020.0008]
éB => [.1D10.0020.0002] [.0000.0024.0002] [.1CC6.0020.0008]
ëC => [.1D10.0020.0002] [.0000.002B.0002] [.1CE0.0020.0008]
èD => [.1D10.0020.0002] [.0000.0025.0002] [.1CF5.0020.0008]
êE => [.1D10.0020.0002] [.0000.0027.0002] [.1D10.0020.0008]
ēF => [.1D10.0020.0002] [.0000.0032.0002] [.1D4B.0020.0008]

3. adım: Form sıralama tuşları

eA => 1D10 1CAD 0000 0020 0020 0000 0002 0008
éB => 1D10 1CC6 0000 0020 0024 0020 0000 0002 0002 0008
ëC => 1D10 1CE0 0000 0020 002B 0020 0000 0002 0002 0008
èD => 1D10 1CF5 0000 0020 0025 0020 0000 0002 0002 0008
êE => 1D10 1D10 0000 0020 0027 0020 0000 0002 0002 0008
ēF => 1D10 1D4B 0000 0020 0032 0020 0000 0002 0002 0008

Adım 4: Sıralama tuşlarını karşılaştırın: İkinci değer hepsini sıralamak için yeterlidir ve aslında zaten artan sıradadır, bu yüzden son sipariş gerçekten:

eA
éB
ëC
èD
êE
ēF

Güncelleme : Yeni kurallar sağlayan alan nedeniyle daha zor olan Solomon Rutzky üçüncü vakasını ekleyerek ("göz ardı edilemez vaka" yı seçtim):

adım 1, NFD:

è 1 => U+0065 U+0300 U+0020 U+0031
ê 5 => U+0065 U+0302 U+0020 U+0035
e 2 => U+0065 U+0020 U+0032
é 4 => U+0065 U+0301 U+0020 U+0034
ē 3 => U+0065 U+0304 U+0020 U+0033
ë 6 => U+0065 U+0308 U+0020 U+0036

Adım 2, Harmanlama dizileri üretin:

è 1 => [.1D10.0020.0002] [.0000.0025.0002] [*0209.0020.0002] [.1CA4.0020.0002]
ê 5 => [.1D10.0020.0002] [.0000.0027.0002] [*0209.0020.0002] [.1CA8.0020.0002]
e 2 => [.1D10.0020.0002] [*0209.0020.0002] [.1CA5.0020.0002]
é 4 => [.1D10.0020.0002] [.0000.0024.0002] [*0209.0020.0002] [.1CA7.0020.0002]
ē 3 => [.1D10.0020.0002] [.0000.0032.0002] [*0209.0020.0002] [.1CA6.0020.0002]
ë 6 => [.1D10.0020.0002] [.0000.002B.0002] [*0209.0020.0002] [.1CA9.0020.0002]

3. adım, Form sıralama tuşları:

è 1 => 1D10 0209 1CA4 0000 0020 0025 0020 0020 0000 0002 0002 0002 0002
ê 5 => 1D10 0209 1CA8 0000 0020 0027 0020 0020 0000 0002 0002 0002 0002
e 2 => 1D10 0209 1CA5 0000 0020 0020 0020 0000 0002 0002 0002
é 4 => 1D10 0209 1CA7 0000 0020 0024 0020 0020 0000 0002 0002 0002 0002
ē 3 => 1D10 0209 1CA6 0000 0020 0032 0020 0020 0000 0002 0002 0002 0002
ë 6 => 1D10 0209 1CA9 0000 0020 002B 0020 0020 0000 0002 0002 0002 0002

4. adım, Sıralama tuşlarını karşılaştırın:

Temel olarak üçüncü değer siparişi belirler ve aslında sadece son basamağa dayanır, bu nedenle sipariş şöyle olmalıdır:

è 1
e 2
ē 3
é 4
ê 5
ë 6

İkinci güncelleme Solomon Rutzky'nin Unicode sürümleri hakkındaki yorumuna dayanıyor.

allkeys.txtŞu anda en son Unicode sürümü hakkındaki verileri kullandım , yani 10.0 sürümü

Bunun yerine Unicode 5.1'i hesaba katmamız gerekirse , bu şöyle olur: http://www.unicode.org/Public/UCA/5.1.0/allkeys.txt

Ben sadece yukarıdaki tüm karakterler için, harmanlama dizileri bunun yerine kontrol ettim:

e => [.119D.0020.0002.0065]
é => [.119D.0020.0002.0065] [.0000.0032.0002.0301]
ë => [.119D.0020.0002.0065] [.0000.0047.0002.0308]
è => [.119D.0020.0002.0065] [.0000.0035.0002.0300]
ê => [.119D.0020.0002.0065] [.0000.003C.0002.0302]
ē => [.119D.0020.0002.0065] [.0000.005B.0002.0304]

ve:

eA => [.119D.0020.0002.0065] [.1141.0020.0008.0041]
éB => [.119D.0020.0002.0065] [.0000.0032.0002.0301] [.1157.0020.0008.0042]
ëC => [.119D.0020.0002.0065] [.0000.0047.0002.0308] [.116F.0020.0008.0043]
èD => [.119D.0020.0002.0065] [.0000.0035.0002.0300] [.1182.0020.0008.0044]
êE => [.119D.0020.0002.0065] [.0000.003C.0002.0302] [.119D.0020.0008.0045]
ēF => [.119D.0020.0002.0065] [.0000.005B.0002.0304] [.11D5.0020.0008.0046]

ve:

è 1 => [.119D.0020.0002.0065] [.0000.0035.0002.0300] [*0209.0020.0002.0020] [.1138.0020.0002.0031]
ê 5 => [.119D.0020.0002.0065] [.0000.003C.0002.0302] [*0209.0020.0002.0020] [.113C.0020.0002.0035]
e 2 => [.119D.0020.0002.0065] [*0209.0020.0002.0020] [.1139.0020.0002.0032]
é 4 => [.119D.0020.0002.0065] [.0000.0032.0002.0301] [*0209.0020.0002.0020] [.113B.0020.0002.0034]
ē 3 => [.119D.0020.0002.0065] [.0000.005B.0002.0304] [*0209.0020.0002.0020] [.113A.0020.0002.0033]
ë 6 => [.119D.0020.0002.0065] [.0000.0047.0002.0308] [*0209.0020.0002.0020] [.113D.0020.0002.0036]

daha sonra aşağıdaki sıralama tuşlarını hesaplar:

e => 119D 0000 0020 0000 0002 0000 0065
é => 119D 0000 0020 0032 0000 0002 0002 0000 0065 0301
ë => 119D 0000 0020 0047 0000 0002 0002 0000 0065 0308
è => 119D 0000 0020 0035 0000 0002 0002 0000 0065 0300
ê => 119D 0000 0020 003C 0000 0002 0002 0000 0065 0302
ē => 119D 0000 0020 005B 0000 0002 0002 0000 0065 0304

ve:

eA => 119D 1141 0000 0020 0020 0000 0002 0008 0000 0065 0041
éB => 119D 1157 0000 0020 0032 0020 0000 0002 0002 0008 0000 0065 0301 0042
ëC => 119D 116F 0000 0020 0047 0020 0000 0002 0002 0008 0000 0065 0308 0043
èD => 119D 1182 0000 0020 0035 0020 0000 0002 0002 0008 0000 0065 0300 0044
êE => 119D 119D 0000 0020 003C 0020 0000 0002 0002 0008 0000 0065 0302 0045
ēF => 119D 11D5 0000 0020 005B 0020 0000 0002 0002 0008 0000 0065 0304 0046

ve:

è 1 => 119D 0209 1138 0000 0020 0035 0020 0020 0000 0002 0002 0002 0002 0000 0065 0300 0020 0031
ê 5 => 119D 0209 113C 0000 0020 003C 0020 0020 0000 0002 0002 0002 0002 0000 0065 0302 0020 0035
e 2 => 119D 0209 1139 0000 0020 0020 0020 0000 0002 0002 0002 0000 0065 0020 0032
é 4 => 119D 0209 113B 0000 0020 0032 0020 0020 0000 0002 0002 0002 0002 0000 0065 0301 0020 0034
ē 3 => 119D 0209 113A 0000 0020 005B 0020 0020 0000 0002 0002 0002 0002 0000 0065 0304 0020 0033
ë 6 => 119D 0209 113D 0000 0020 0047 0020 0020 0000 0002 0002 0002 0002 0000 0065 0308 0020 0036

bu da yine bu üç sıralı sonucu verir:

e
é
è
ê
ë
ē

ve

eA
éB
ëC
èD
êE
ēF

ve

è 1
e 2
ē 3
é 4
ê 5
ë 6

Merhaba Patrick. Bu ayrıntılı bilgiyi gönderdiğiniz için teşekkür ederiz. Birkaç not: 1) Kod'u yoksayabilirsiniz VARCHAR. Burada kullanılmayan (yani Unicode olmayan) veriler içindir. Bu yüzden ēkarakter gayet iyi çalışıyor. 2) "harmanlama çizelgeleri" bilgisi biraz modası geçmiş. Bu Harmanlamanın önceki bir sürümü içindir ve 2009'dan beri hiçbir şey yayınlamamıştır. 3) Buradaki Unicode sürümü kesinlikle en son sürüm değildir (Sürüm 10). _100_Bu Unicode 5.0 veya 5.1 olacağını bu yüzden serisi Harmanlamalar, SQL 2008 ile birlikte gelen unicode.org/standard/versions/#TUS_Earlier_Versions
Solomon Rutzky

allKeys.txt Unicode sürümü arasındaki değişiklikleri, yeni karakterlerin eklenmesinin yanı sıra düşünmüyorum , bu yüzden yukarıdakiler doğru kalmalı, ancak elbette önceki eski verilerle yeniden yapılabilir, sadece birkaç saat içine tekrar koyma enerjisinden yoksundur. CP1252'ye gelince, sadece MS-SQL tarafından verilen tanımdan geliyordu (bu ürünü kendim kullanmıyorum).
Patrick Mevzek

1) Muhtemelen versiyonlar arasında büyük değişiklikler yok, ama en azından ağırlık / sınıflandırma düzeltmelerinin olduğundan eminim. Ama evet, kesinlikle zaman kısıtlamaları alıyorum ;) 2) CP1252 ile ilgili olarak, Kod Sayfaları kavramı Unicode içinde mevcut olmadığından bahsediyorum. Unicode, kod sayfalarına asla ihtiyaç duymamanın bir yoludur. MS dokümanı kuşkusuz bu konuda net değildir, ancak en üstte " Unicode olmayan karakter verilerini depolamak için kullanılan kod sayfası " ndan bahsedilmektedir . Bir karakterin CP1252'de olmadığı doğrudur, ancak Kod Sayfaları burada devreye girmez.
Solomon Rutzky

Evet, kod sayfası hakkında Unicode ile ilgili hiçbir şey söylemedim. Bu harmanlama adının "kod sayfası 1252" ile çalıştığını söyleyen yalnızca MS SQL belgelerindendir. Muhtemelen hiçbir anlam ifade etmiyor (Bana göre değil, yine de bir kullanıcı değil) ama bu yazılımın belgelerinde yazılan şey bu. İşi yeniden yapmaya gelince, bunu yapmaktan çekinmeyin ya da eğer varsa ve isterseniz, burada Unicode 5 ve sonuncusu arasındaki oyundaki karakterlerle ilgili sıralama değişikliklerini sağlayın. Cevabımın olduğu gibi olduğuna inanıyorum, kesin ve sonuçları başka şekilde değil girdiye göre oluşturuyor.
Patrick Mevzek

3) yeniden: cümle # 1: Çoğunlukla Unicode ile ilgili olsa da, MS bu spesifikasyonu uyguladığı ve hepsini yapmamış olabileceği ve / veya bazı hatalar yapmış olabileceği için bu soru bir OS sorunu. .NET'te belirli bir karakterin içinde yer alan "kategori" veya "blok" u nasıl belirlediğine dair 2 hata buldum (küçük bir karakter segmentini yanlış tanımlıyorlardı). Ayrıca, bu ise artık SQL Server özgü davranış ne olabilir bu nedenle SQL Server, (sürümleri arasındaki tutarlılık için) zaman içinde bir noktada her Harmanlama ait etkin bir anlık vardır çünkü sadece, biraz, en azından, bir SQL Server sorunu.
Solomon Rutzky

16

Burada gördüğünüz davranış, genel anlamda Unicode Harmanlama Algoritmasının (UCA) karmaşık, çok düzeyli sıralamaya izin vermesinden kaynaklanmaktadır. Daha spesifik olarak:

  1. Sıralama Karşılaştırma değildir:

    İki dizenin aynı mı yoksa farklı mı olduğunu belirlemek oldukça basittir (belirli bir yerel ayar / dil ve duyarlılık kümesi göz önüne alındığında). Ancak 2 veya daha fazla dizenin sırasını belirlemek oldukça karmaşık olabilir.

  2. Sıralama bir dizi adımda yapılır, her adım karakter karaktere değil tüm dizeye uygulanır:

    1. Standart: temel karakterleri sıralar (aksan ve büyük / küçük harf farkından bağımsız olarak)
    2. Vurgu duyarlıysa, aksan / aksan ağırlıkları uygulayın
    3. Büyük / küçük harf duyarlıysa, kasa ağırlıklarını uygulayın

Göre sıralama yaparken col1(tek karakteri), ilk hepsi "olduğu için tüm karakterlerin aynı ağırlığa sahip olduğunu belirlerse e ". Ardından, aksan / aksan ağırlıklarını uygular. Kasa farklılıkları yoktur, bu nedenle üçüncü adım hiçbir şeyi değiştirmez. Yani tek farklar 2. adımdadır, bu nedenle bu satırlar için tercih edilen bir düzen vardır col1.

Sıralama ölçütü col2(iki karakter), her iki karakter sıralama ağırlığını belirlemek için kullanıldığından (örneğin " ea ", " eb ", vb.) Her satırın farklı bir ağırlığa sahip olduğunu belirler . Ardından, aksan / aksan ağırlıklarını uygular. Kasa farklılıkları yoktur, bu nedenle üçüncü adım hiçbir şeyi değiştirmez. Yani bu sefer 1. ve 2. adımlarda farklılıklar var. Ancak, 1. adımdaki farklılıklar, 2. adımın ağırlıkları dikkate alınmadan önce her bir dizeye uygulandığından, 2. adımdaki ağırlıkların sipariş üzerinde herhangi bir etkisi yoktur; ancak iki veya daha fazla sıra için adım 1'deki ağırlıklar aynıysa geçerlidir.

Örnek kodun sorudan aşağıdaki uyarlaması, umarım yukarıda açıklanan sıralama davranışını gösterir. Harmanlamanın büyük / küçük harfe duyarlı olduğunu göstermeye yardımcı olacak bazı ek satırlar ve ek bir sütun ekledim (orijinal örnek verilerin tümü küçük harf olduğu için):

KURMAK

USE [tempdb];

-- DROP TABLE dbo.OddSort;
CREATE TABLE dbo.OddSort
(
    id INT IDENTITY(1,1) PRIMARY KEY,
    col1 NVARCHAR(5) COLLATE Latin1_General_100_CS_AS,
    col2 NVARCHAR(5) COLLATE Latin1_General_100_CS_AS,
    col3 NVARCHAR(5) COLLATE Latin1_General_100_CS_AS
);
GO

INSERT dbo.OddSort (col1, col2, col3)
VALUES (N'e', N'eA', N'e A')
     , (N'ê', N'êE', N'ê E')
     , (N'é', N'éH', N'é H')
     , (N'ë', N'ëC', N'ë C')
     , (N'E', N'EG', N'E G')
     , (N'Ë', N'ëh', N'ë h')
     , (N'è', N'èD', N'è D')
     , (N'é', N'éB', N'é B')
     , (N'ë', N'ëH', N'ë H')
     , (N'ē', N'ēF', N'ē F');

TEST 1

SELECT [id], [col1], UNICODE([col1]) AS [CodePoint]
FROM dbo.OddSort 
ORDER BY col1;

İadeler:

id    col1    CodePoint
1     e       101
5     E       69
8     é       233
3     é       233
7     è       232
2     ê       234
4     ë       235
9     ë       235
6     Ë       203
10    ē       275

Yukarıdaki sonuçlarda neler görebiliriz:

  1. Kod Noktası sıralama düzenini belirlemiyor
  2. Aksanlı karakterler aksanlı karakterlerden önce sıralanır (aynı harf içinde: f yine de bunların hepsinden sonra gelir). Açıkça, vurgu ağırlıkları kasa ağırlıklarından önce uygulanır.
  3. Küçük harf, aynı aksanlı (veya aksanlı olmayan) karakterde büyük harften önce sıralar (yani e sonra E ve ë sonra Ë ). Bu terzilik, Windows Harmanlamalarının çoğu tarafından kullanılırken, SQL Server Harmanlamalarının çoğu önce büyük harfle sıralanır.

TEST 2

SELECT [id], [col2]
FROM dbo.OddSort 
ORDER BY col2;

İadeler:

id    col2
1     eA
8     éB
4     ëC
7     èD
2     êE
10    ēF
5     EG
3     éH
6     ëh
9     ëH

Yukarıdaki sonuçlarda neler görebiliriz:

  1. Birinci seviye sıralama gerçekten temel karakterlerdir. Aksanlar / aksanlar olsaydı ëC (id = 4), ēF (id = 10) ve EG (id = 5) satırları oldukları yerde olmazdı. Muhafaza olsaydı, EG (id = 5) satırı olduğu yerde olmazdı.
  2. İkinci seviye sıralama gerçekten aksan / aksan. Bu, son üç satırın neden ëh -> éH -> ëH yerine éH -> ëh -> ëH olduğunu açıklar (örneğin 6 -> 3 -> 9 yerine ID 3 -> 6 -> 9).
  3. Üçüncü seviye sıralama gerçekten kasa. Bu nedenle son 2 satır ëh -> ëH'dir , çünkü küçük harf önce sıralanır .

TEST 3

SELECT [id], [col3]
FROM dbo.OddSort 
ORDER BY col3;

İadeler:

id    col3
1     e A
8     é B
4     ë C
7     è D
2     ê E
10    ē F
5     E G
3     é H
6     ë h
9     ë H

Yukarıdaki sonuçlarda neler görebiliriz:

  1. Sıralama düzeni, Test 2'deki ile tamamen aynıdır. Buradaki test değerlerindeki tek fark, her karakter arasında bir boşluk bulunması ve bağlamsal kuralların olasılığını ortadan kaldırmasıdır. Bu nedenle, col2sorudaki sıralama düzenindeki farkın nedeninin yine "Bağlamsal Duyarlılık" değil , "Çok Düzeyli Karşılaştırma" dan kaynaklandığını biliyoruz .

Ek Notlar:

  1. Tam kuralları elde etmekle ilgili olarak, olması gerektiği kadar kolay değildir. Bu kuralların somut açıklamalarını elde etmedeki sorun, Unicode sıralama kurallarının kesinlikle belgelenmesine rağmen bir tavsiye olmasıdır. Bu önerileri uygulamak Microsoft gibi satıcılara bağlıdır. Microsoft, önerileri tam olarak Unicode belgelerinde belirtildiği gibi uygulamadı, bu nedenle orada bir bağlantı kesildi (HTML veya CSS spesifikasyonlarının satıcılar arasında ne tam olarak ne de aynı şekilde uygulandığına benzer). Ardından, Windows Harmanlamalarının farklı sürümleri vardır ( 100SQL Server 2008 ile birlikte gelen sürümü kullanıyorsunuz ) ve Unicode veya ICU Harmanlama demosunun geçerli sürümünden çok daha eski bir Unicode sürümüne bağlıkullanıyor. Örneğin, SQL Server 2008 için "Harmanlama ve Unicode Desteği" belgelerinin SQL Server 2008 Harmanlamalarındaki Yenilikler bölümü Harmanlama_100_ dizileri için "yeni" olanlarla ilgili 2 ilginç nokta yapar :

    1. Unicode 5.0 vaka tablosu.

      Unicode 5.0, Temmuz 2006'da yayınlandı (o zaman, karakter veritabanı serbest bırakıldı ve tam özellik 2006'nın sonlarında izlendi). Mevcut sürüm, Haziran 2017'de yayınlanan 10.0'dur. Ve son 4 yılın yayınlanma şekli göz önüne alındığında, 11.0 sürümünün 2018'in ortasında çıkması muhtemeldir.

    2. Daha önce ağırlıklı olmayan karakterlere eşit olarak karşılaştırılacak ağırlık eklenmiştir.

      Bu ağırlıklar büyük olasılıkla Unicode Standardında tanımlanmıştır, sadece bu uygulamasında değil.

     
    Yine de, yukarıda bağlantılı UCA belgeleri başlamak için iyi bir yerdir.

  2. Windows / .NET / SQL Server tarafından kullanılan Sıralama Anahtarları, Unicode Standardında (Bkz. @ Patrick'in cevabı) gösterilen veya ICU'da uygulananlarla aynı değildir . Windows / .NET / SQL Server'ın ne kullandığını görmek için CompareInfo.GetSortKey Yöntemini deneyebilirsiniz . Bu değerleri iletmek ve sıralama anahtarını almak için bir SQLCLR UDF oluşturdum. .NET Framework 4.5 - 4.6.1'in yüklü olduğu Windows 10'da SQL Server 2017 kullandığımı, bu nedenle .NET'in Unicode 6.0.0 kullanması gerektiğini lütfen unutmayın . Ayrıca, Level4 bu dizeler için kullanılmamaktadır.

    CHAR    L1     L2     L3     L4
    e      0E21
    E      0E21           12
    ë      0E21    13
    Ë      0E21    13     12

    Test 1 için bu sıralama anahtarlarına bakıldığında ve düzeylerin bir ORDER BYyan tümce içinde birden çok sütun gibi sıralandığını (L3, aynı L1 değerleri içinde sıralanan L2'nin aynı değerleri içinde sıralanır), davranışın nedenini göstermelidir. soruda Unicode'un çok seviyeli sıralama kabiliyeti olduğu belirtiliyor. Aynı şekilde:

    CHAR       L1         L2       L3       L4
    EG      0E210E25              1212
    éH      0E210E2C      0E      0212
    ëh      0E210E2C      13
    ëH      0E210E2C      13      0212

    Test 2 için bazı sıralama tuşlarına baktığımızda, önce temel karakterlerin sıralandığını (L1), sonra aksanların sıralandığını (L2) ve ardından kasanın sıralandığını (L3) görebiliriz.

  3. Veri türü olduğundan NVARCHAR, yalnızca Unicode Kod Noktaları ve sıralama algoritmalarıyla ilgileniriz, bu nedenle UNICODE()TEST 1'de işlevin kullanılması. Kod Sayfaları çoğu Harmanlama tarafından belirtilirken, yalnızca VARCHARverilerle ilgilidir . Bunun anlamı, Kod Latin1_General*, burada yoksayılabilen Harmanlama serileri tarafından belirtilir .

  4. Varsayılan Unicode Harmanlama Öğesi Tablosunda (DUCET) ( Harmanlama serileriyle eşleşmesi gereken Sürüm 5.0.0 ) açıklanan ağırlıklar _100_ABD İngilizcesi için uygundur, ancak diğer yerel ayarlar / diller için uygun değildir. Diğer diller için gereken başlangıç DUCET ile ve daha sonra Ortak Yerel Veri Deposu (CLDR) projesi ile tanımlanan yerel ayara özel geçersiz kılma kurallarını uygular. Söyleyebileceğim kadarıyla, 1.4 / 1.4.1 sürümleri 2006 yılında yayınlandı. Bu geçersiz kılmaları almak için, http://unicode.org/Public/cldr/1.4.0/core.zip adresinden CLDR 1.4 "çekirdek" dosyasını indirin. , daha sonra, bu zip dosyasında harmanlama klasörüne gidin ve kullanılan yerel ayara karşılık gelen XML dosyasını bulun. Bu dosyalar yalnızca geçersiz kılmaları içerir ve tam bir karşılaştırma kuralları kümesi değildir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.