Systemy wielojęzyczne wymagają starannego doboru kolacji, by poprawnie obsłużyć wszystkie używane języki.
Kolacja serwera, bazy i poszczególnych kolumn
W SQL Server termin „kolacja” oznacza zestaw reguł określających porównywanie i sortowanie tekstu oraz sposób interpretowania znaków. Kolacja może definiować między innymi językowe reguły sortowania, stronę kodową, rozróżnianie wielkości liter i rozróżnianie akcentów. Przykładowo sufiks _CI oznacza porównywanie niewrażliwe na wielkość liter, _CS — wrażliwe na wielkość liter, _AI — niewrażliwe na akcenty, a _AS — wrażliwe na akcenty. Kolacja serwera jest ustawiana podczas instalacji SQL Server, natomiast każda baza danych może mieć własną kolację domyślną, niezależną od kolacji instancji.
Kolacja bazy jest dziedziczona przez kolumny tekstowe tworzone bez jawnie wskazanej kolacji. Można jednak ustawić inną kolację dla konkretnej kolumny albo zastosować ją tylko w pojedynczym wyrażeniu za pomocą COLLATE. Ma to znaczenie przy porównywaniu danych pochodzących z różnych baz, przy łączeniu tabel oraz podczas sortowania wyników. Dwie kolumny zawierające tekst mogą mieć różne kolacje, dlatego zapytanie porównujące je bez dodatkowego wskazania reguł może zakończyć się błędem konfliktu kolacji.
Unicode i dobór typów tekstowych w SQL Server
W środowisku wielojęzycznym podstawowym wyborem są typy Unicode: nvarchar i nchar. Wartości zapisane w tych typach mogą przechowywać znaki wielu alfabetów, w tym polskiego, cyrylicy, greki, hebrajskiego, arabskiego, chińskiego czy japońskiego, bez uzależniania treści od pojedynczej strony kodowej. nvarchar jest przeznaczony dla tekstu o zmiennej długości, a nchar dla tekstu o stałej długości. Typ nvarchar(max) pozwala przechowywać większe wartości niż zwykły nvarchar. Typy varchar i char nie są automatycznie równoważne z Unicode; ich zakres znaków zależy od użytej kolacji i strony kodowej.
Literał tekstowy przeznaczony do zapisania jako Unicode powinien mieć prefiks N, na przykład N'Łódź – 東京'. Bez tego prefiksu SQL Server może najpierw zinterpretować tekst jako literał nieunicode, co prowadzi do utraty znaków jeszcze przed zapisaniem wartości w kolumnie nvarchar. Ten problem występuje często przy skryptach instalacyjnych, importach i ręcznie tworzonych zapytaniach. Samo użycie kolumny Unicode nie naprawia danych, które zostały już wcześniej zamienione na niewłaściwą stronę kodową.
SQL Server 2019 i nowsze wersje wprowadziły kolacje UTF-8 dla typów char i varchar. Pozwalają one przechowywać znaki Unicode w kodowaniu UTF-8, ale nie oznacza to, że każda istniejąca kolacja lub każda aplikacja automatycznie zacznie poprawnie obsługiwać taki tekst. Przed zmianą typu albo kolacji trzeba sprawdzić długości pól, indeksy, ograniczenia, procedury składowane oraz sposób bindowania parametrów przez sterownik.
Sortowanie, wyszukiwanie i porównania zależne od języka
Ta sama sekwencja znaków może być porównywana inaczej w zależności od kolacji. Reguły dla języka polskiego nie są tożsame z regułami dla języka tureckiego, niemieckiego czy japońskiego. Różnice dotyczą kolejności sortowania, traktowania akcentów, znaków równoważnych oraz par małych i wielkich liter. Dlatego kolację należy dobierać do oczekiwanego zachowania aplikacji, a nie wyłącznie do języka interfejsu systemu Windows. Aplikacja może mieć polski interfejs, lecz przechowywać dane użytkowników z wielu krajów i wymagać reguł odpowiednich dla całego zbioru danych.
Kolacja wpływa na operatory takie jak =, LIKE, ORDER BY, GROUP BY i JOIN. W kolacji niewrażliwej na wielkość liter wartości abc i ABC mogą być traktowane jako równe, natomiast w kolacji wrażliwej na wielkość liter będą różne. Analogicznie kolacja niewrażliwa na akcent może uznać wybrane warianty znaków za równoważne podczas wyszukiwania. Jeśli aplikacja wymaga jednoznacznego porządku technicznego, na przykład dla identyfikatorów, można użyć kolacji binarnej, takiej jak wariant BIN2, zamiast reguł językowych.
Przy użyciu COLLATE w zapytaniu można jawnie narzucić reguły porównania, lecz takie rozwiązanie powinno być stosowane celowo. Kolacja zastosowana do wyrażenia może zmienić plan wykonania i utrudnić wykorzystanie indeksu na kolumnie. W przypadku tabel tymczasowych dodatkowym źródłem problemów jest kolacja bazy tempdb, która może różnić się od kolacji bazy aplikacyjnej. Wtedy porównanie kolumny tekstowej z tabeli tymczasowej z kolumną tabeli stałej może wymagać ujednolicenia kolacji po jednej ze stron.
Kontrola migracji i testów dla wielojęzycznych danych
Przed wdrożeniem SQL Server w środowisku wielojęzycznym należy zinwentaryzować kolacje instancji, baz, tabel i kolumn tekstowych. Przydatne są zapytania odczytujące właściwość collation_name z widoków katalogowych, między innymi sys.databases, sys.columns i sys.types. Trzeba również sprawdzić definicje procedur, widoków, funkcji oraz zapytań generowanych przez aplikację. Sama zmiana kolacji bazy nie zmienia automatycznie kolacji istniejących kolumn, dlatego konwersja wymaga osobnej analizy schematu i danych.
Testy powinny obejmować pełne wartości używane w systemie, a nie tylko alfabet łaciński. Należy sprawdzić zapis i odczyt znaków takich jak ą, ę, ł, ß, litery cyryliczne, znaki CJK oraz symbole zapisujące się poza podstawową płaszczyzną Unicode. Kolacje z sufiksem _SC obsługują pary zastępcze Unicode jako pojedyncze znaki w operacjach, które uwzględniają znaki uzupełniające. Warto zweryfikować działanie LEN, SUBSTRING, sortowania, unikatowych indeksów i wyszukiwania po migracji.
Diagnostyka obejmuje także sterownik, kodowanie połączenia i parametry przekazywane przez aplikację. Błąd może powstać na granicy klient–serwer, podczas importu pliku CSV albo w narzędziu ETL, zanim dane trafią do SQL Server. Należy porównać wartości źródłowe z wartościami zapisanymi w tabeli oraz sprawdzić, czy zapytania używają parametrów Unicode i właściwych typów. Dopiero po takim teście można bezpiecznie ocenić, czy problem dotyczy kolacji, typu danych, konwersji kodowania, czy logiki wyszukiwania.