Witaj na Zine.net online Zaloguj się | Rejestracja | Pomoc

[PL] Kolacje w różnych wariantach

Dzisiaj spędziłem kilka chwil analizując problem, jaki pojawił się w jednym z wątków na portalu WSS.pl. Cała rzecz rozbijała się o użycie funkcji DATABASEPROPERTYEX, która jako wynik zwraca wartość typu sql_variant. I tu był cały szkopuł. Skąd biorą się informacje o właściwościach baz danych? Może z bazy master? A jaką kolację (nieoficjalne spolszczenie angielskiego "collation") ma baza master? Oczywiście, kolację serwera (wybieramy ją podczas instalacji). A zatem, jeśli mamy kolację Polish_CI_AS na serwerze, to wartość typu sql_variant zwracana przez DATABASEPROPERTYEX zakonotuje sobie kolację Polish_CI_AS właśnie (taki już urok typu sql_variant – gdy wrzucamy doń tekst, zapamiętuje się też jego kolacja). Jak to sprawdzić? Oto mały test:

USE master;
GO
IF EXISTS (SELECT * FROM sys.databases WHERE name = N'test')
DROP DATABASE test;
GO
CREATE DATABASE test;
GO
USE test;
GO
SELECT
SQL_VARIANT_PROPERTY(DATABASEPROPERTYEX(DB_NAME(), 'Collation'), 'Collation') AS KolacjaZapamietana,
CASE
WHEN N'Polish_CI_AS' = DATABASEPROPERTYEX(DB_NAME(), 'Collation') THEN 1
ELSE 0
END AS TestRownosci;
GO

Serwer ma kolację Polish_CI_AS. Test równości pokazuje, że kolacja bazy bieżącej to Polish_CI_AS. Funkcja SQL_VARIANT_PROPERTY pokazuje, że sql_variant zapamiętał kolację tę samą. Nic dziwnego, skoro tylką jedną kolacją operujemy :-)

A teraz trochę trudniej:

USE master;
GO
IF EXISTS (SELECT * FROM sys.databases WHERE name = N'test')
DROP DATABASE test;
GO
CREATE DATABASE test COLLATE Polish_BIN;
GO
USE test;
GO
SELECT
SQL_VARIANT_PROPERTY(DATABASEPROPERTYEX(DB_NAME(), 'Collation'), 'Collation') AS KolacjaZapamietana,
CASE
WHEN N'Polish_BIN' = DATABASEPROPERTYEX(DB_NAME(), 'Collation') THEN 1
ELSE 0
END AS TestRownosci;
GO

Tym razem kolacja bazy jest inna niż kolacja serwera. I co się dzieje? Test równości mówi, że kolacja bazy wcale nie jest Polish_BIN (choć jest właśnie taka bez wątpienia!). I co się okazuje. Ano okazuje się, że sql_variant zwracany przez funkcję DATABASEPROPERTYEX zapamiętał... Polish_CI_AS, czyli kolację serwera!

I teraz pytanie, czy wiedząc, że jest tak, jak powyżej napisałem, możemy domyśleć się, jak to się dzieje, że powyższe testy równości dają takie wyniki, jakie dają? Tak!!! Odpowiedzią są dwa rozdziały Books Online (BOL):

http://msdn.microsoft.com/en-us/library/ms190309.aspx - Data Type Precedence

http://msdn.microsoft.com/en-us/library/ms181071.aspxUsing sql_variant Data

Z pierwszego z powyższych rozdziałów dowiadujemy się, że sql_variant jest prawie najwyżej w hierarchii typów SQL Servera. A to oznacza, że w przypadku porównywania wartości typu sql_variant do wartości typu nvarchar (jak to ma miejsce powyżej) ta druga wartość rzutowana jest na sql_variant i dopiero następuje porównanie. A porównanie dwóch wartości typu sql_variant to już nie bułka z masłem dla SQL Servera, o czym można przeczytać w drugim z podanych przeze mnie powyżej rozdziałów BOL (warto spojrzeć, ile parametrów jest tam porównywanych, jeśli wartości pochodzą od typów tekstowych!).

Chciałoby się powiedzieć, czytajcie dokumentację (RTFM) :-) A ja bym powiedział raczej – uwaga na to, co zwraca funkcja (jakiego typu dane). Bo przecież proste rzutowanie na nvarchar załatwia sprawę problemów z sql_variant w przypadku użycia funkcji DATABASEPROPERTYEX, co pokazał Marek Adamczuk we wspomnianym wątku na WSS.pl.

Osobne podziękowania dla Maćka Pileckiego, z którym dyskusja ożywiła mój umysł i zachęciła mnie do ponownego przyjrzenia się problemowi. Problemowi, który okazuje się niekoniecznie trudny, a jednak pokazuje, jak bardzo trzeba uważać operując funkcjami (zawsze trzeba znać typ zwracany) oraz że nie powinniśmy ufać niejawnym konwersjom.

Zdecydowanie polecam też wszystkim obejrzenie nagrania sesji Marka Adamczuka o kolacjach z wczorajszego spotkania Virtual Study Group 70-432. Nagranie powinno niebawem ukazać się na portalu VirtualStudy.pl. Kolacje są tematem niełatwym i można się w nich pogubić dość skutecznie.

Opublikowane 17 listopada 2009 23:19 przez brejk

Komentarze:

# re: [PL] Kolacje w różnych wariantach

18 listopada 2009 10:29 by Tomek

Hmmm ... tytuł zapowiadał coś bardziej smakowitego ... przynajmniej dla człowieka nie zajmującego się na codzień SQL ... jednak spolszczenia są zmorą :).

# re: [PL] Kolacje w różnych wariantach

18 listopada 2009 10:48 by brejk

@Tomek: Dzięki tytułowi złowiłem nawet speca od AD ;-) A spolszczenie urocze, nieprawdaż? ;-)

# re: [PL] Kolacje w różnych wariantach

18 listopada 2009 15:35 by marekpow

Gdy użyłem pierwszy raz tego spolszczenia omal nie zostałem zlinczowany przez kolegów ;-)

# re: [PL] Kolacje w różnych wariantach

18 listopada 2009 19:38 by Bysza

Nie lepiej "przekąska"? ;)

# re: [PL] Kolacje w różnych wariantach

18 listopada 2009 20:05 by brejk

@marekpow: Ja tylko papuguję po Marku Adamczuku ;-) Grunt, że wszyscy wiedzą, o co chodzi :D

# re: [PL] Kolacje w różnych wariantach

18 listopada 2009 20:56 by marekpow

@brejk: autorytet Marka mnie uratował, gdy pokazałem "Kolację przy świecach" :)

Komentarze anonimowe wyłączone

About brejk

MVP, MCT, SQL Server geek