Łatwo zapomnieć, że FORMAT()
T-SQL funkcja zapewnia formatowanie zgodne z ustawieniami lokalnymi. Uwzględnienie ustawień regionalnych oznacza, że ustawienia regionalne mogą wpływać na wyniki. Innymi słowy, dokładny wynik, jaki otrzymasz, będzie zależeć od ustawień regionalnych.
Domyślnie funkcja używa języka bieżącej sesji do określenia ustawień regionalnych. Można to jednak obejść, przekazując do funkcji argument „culture”. W ten sposób możesz dostarczać wyniki dla określonej lokalizacji bez konieczności zmiany języka bieżącej sesji.
Ten artykuł zawiera przykłady wpływu ustawień regionalnych na wyniki przy użyciu FORMAT()
funkcja w SQL Server.
Przykład 1 – Waluty
Oto krótki przykład pokazujący, jak język/kultura może wpływać na wyniki podczas formatowania liczb.
DECLARE @num decimal(6,2) = 1234.56; SELECT FORMAT(@num, 'C', 'en-us') 'en-us', FORMAT(@num, 'C', 'en-gb') 'en-gb', FORMAT(@num, 'C', 'th-th') 'th-th', FORMAT(@num, 'C', 'nl-nl') 'nl-nl', FORMAT(@num, 'C', 'ne-np') 'ne-np', FORMAT(@num, 'C', 'fa-ir') 'fa-ir';
Wyniki:
+-----------+-----------+-----------+------------+------------+--------------+ | en-us | en-gb | th-th | nl-nl | ne-np | fa-ir | |-----------+-----------+-----------+------------+------------+--------------| | $1,234.56 | £1,234.56 | ฿1,234.56 | € 1.234,56 | रु 1,234.56 | 1,234/56ريال | +-----------+-----------+-----------+------------+------------+--------------+
C
w tym przykładzie jest standardowym specyfikatorem formatu liczb. Ten pojedynczy znak oznacza, że wartość powinna być sformatowana w określony sposób (w tym przypadku jako waluta). Na szczęście SQL Server jest wystarczająco sprytny, aby wiedzieć, że nie wszystkie kultury używają tego samego formatu i automatycznie prezentuje inny format w zależności od kultury.
W powyższym przykładzie za każdym razem, gdy wywołuję FORMAT()
, przekazuję tę samą wartość i format ciągu. Jedyną różnicą jest wartość argumentu kulturowego. Powoduje to, że wyniki są różne w zależności od używanej kultury. Symbol waluty i jego pozycjonowanie zależy od kultury. Znak używany do separatorów dziesiętnych i separatorów grup jest również określany przez kulturę.
Przykład 2 – Wartości ujemne
Formatowanie może również zależeć od tego, czy wartość jest dodatnia, czy ujemna. Jeśli użyjemy wartości ujemnej, oto co się dzieje:
DECLARE @num decimal(3,2) = -1.23; SELECT FORMAT(@num, 'C', 'en-us') 'en-us', FORMAT(@num, 'C', 'en-gb') 'en-gb', FORMAT(@num, 'C', 'th-th') 'th-th', FORMAT(@num, 'C', 'nl-nl') 'nl-nl', FORMAT(@num, 'C', 'ne-np') 'ne-np', FORMAT(@num, 'C', 'fa-ir') 'fa-ir';
Wyniki:
+---------+---------+---------+---------+---------+-----------+ | en-us | en-gb | th-th | nl-nl | ne-np | fa-ir | |---------+---------+---------+---------+---------+-----------| | ($1.23) | -£1.23 | -฿1.23 | € -1,23 | -रु 1.23 | 1/23-ريال | +---------+---------+---------+---------+---------+-----------+
W niektórych kulturach znak minus pojawia się przed znakiem waluty, w innych pojawia się po nim. Ale w innych kulturach w ogóle nie ma znaku minusa – jest on zastępowany nawiasami, które otaczają cały wynik, w tym znak waluty.
Nie powinniśmy jednak zakładać, że te same reguły są stosowane we wszystkich ciągach formatu. Na przykład, jeśli sformatujemy go jako liczbę zamiast waluty, nie otrzymamy żadnych nawiasów:
DECLARE @num decimal(3,2) = -1.23; SELECT FORMAT(@num, 'N', 'en-us') 'en-us', FORMAT(@num, 'N', 'en-gb') 'en-gb', FORMAT(@num, 'N', 'th-th') 'th-th', FORMAT(@num, 'N', 'nl-nl') 'nl-nl', FORMAT(@num, 'N', 'ne-np') 'ne-np', FORMAT(@num, 'N', 'fa-ir') 'fa-ir';
Wyniki:
+---------+---------+---------+---------+---------+---------+ | en-us | en-gb | th-th | nl-nl | ne-np | fa-ir | |---------+---------+---------+---------+---------+---------| | -1.23 | -1.23 | -1.23 | -1,23 | -1.23 | 1/23- | +---------+---------+---------+---------+---------+---------+
Przykład 3 – Daty i godziny
Formatowanie liczb nie jest jedyną rzeczą, na którą wpływa kultura. Na przykład daty i godziny również będą sformatowane w różny sposób w zależności od kultury.
DECLARE @date datetime2(0) = '2019-06-15 13:45:30'; SELECT FORMAT(@date, 'G', 'en-us') 'en-us', FORMAT(@date, 'G', 'en-gb') 'en-gb', FORMAT(@date, 'G', 'th-th') 'th-th', FORMAT(@date, 'G', 'nl-nl') 'nl-nl', FORMAT(@date, 'G', 'ne-np') 'ne-np', FORMAT(@date, 'G', 'fa-ir') 'fa-ir';
Wyniki (przy użyciu wyjścia pionowego):
en-us | 6/15/2019 1:45:30 PM en-gb | 15/06/2019 13:45:30 th-th | 15/6/2562 13:45:30 nl-nl | 15-6-2019 13:45:30 ne-np | 6/15/2019 1:45:30 अपराह्न fa-ir | 25/03/1398 01:45:30 ب.ظ
W tym przykładzie zastosowano ogólny format daty/długiego czasu (uzyskiwany przy użyciu G
– jeden ze standardowych specyfikatorów formatu daty i czasu), a różnice między kulturami są oczywiste.
Ale możemy również zauważyć różnice, nawet przy użyciu formatu długiej daty:
DECLARE @date datetime2(0) = '2019-06-15 13:45:30'; SELECT FORMAT(@date, 'F', 'en-us') 'en-us', FORMAT(@date, 'F', 'en-gb') 'en-gb', FORMAT(@date, 'F', 'th-th') 'th-th', FORMAT(@date, 'F', 'nl-nl') 'nl-nl', FORMAT(@date, 'F', 'ne-np') 'ne-np', FORMAT(@date, 'F', 'fa-ir') 'fa-ir';
Wyniki (przy użyciu wyjścia pionowego):
en-us | Saturday, June 15, 2019 1:45:30 PM en-gb | 15 June 2019 13:45:30 th-th | 15 มิถุนายน 2562 13:45:30 nl-nl | zaterdag 15 juni 2019 13:45:30 ne-np | शनिवार, जून 15, 2019 1:45:30 अपराह्न fa-ir | شنبه, 25 خرداد 1398 01:45:30 ب.ظ
Przykład 4 – A co z ciągami formatu niestandardowego?
W poprzednich przykładach użyto standardowych ciągów formatujących, które w dużej mierze wykonują formatowanie za Ciebie. To jak skrócony sposób określania niestandardowego ciągu formatu. Z drugiej strony specyfikator formatu niestandardowego pozwala dokładnie określić, jakie znaki pojawiają się w danych wyjściowych i gdzie się znajdują. Jednak zazwyczaj oznacza to, że musisz użyć więcej specyfikatorów formatu w ciągu formatu.
Ale nawet jeśli używasz niestandardowych specyfikatorów formatu, dokładny wynik może również zależeć od ustawień regionalnych. Jeśli chcielibyśmy użyć niestandardowego ciągu formatu daty i godziny, aby naśladować poprzedni przykład, możemy zrobić coś takiego:
DECLARE @date datetime2(0) = '2019-06-15 13:45:30'; SELECT FORMAT(@date, 'dddd, dd MMMM yyyy hh:mm:ss tt', 'en-us') 'en-us', FORMAT(@date, 'dddd, dd MMMM yyyy hh:mm:ss tt', 'en-gb') 'en-gb', FORMAT(@date, 'dddd, dd MMMM yyyy hh:mm:ss tt', 'th-th') 'th-th', FORMAT(@date, 'dddd, dd MMMM yyyy hh:mm:ss tt', 'nl-nl') 'nl-nl', FORMAT(@date, 'dddd, dd MMMM yyyy hh:mm:ss tt', 'ne-np') 'ne-np', FORMAT(@date, 'dddd, dd MMMM yyyy hh:mm:ss tt', 'fa-ir') 'fa-ir';
Wyniki (przy użyciu wyjścia pionowego):
en-us | Saturday, 15 June 2019 01:45:30 PM en-gb | Saturday, 15 June 2019 01:45:30 PM th-th | เสาร์, 15 มิถุนายน 2562 01:45:30 PM nl-nl | zaterdag, 15 juni 2019 01:45:30 ne-np | शनिवार, 15 जून 2019 01:45:30 अपराह्न fa-ir | شنبه, 25 خرداد 1398 01:45:30 ب.ظ
Prawdopodobnie najbardziej oczywistą obserwacją jest to, że wynik jest formatowany przy użyciu języka określonego języka. Ale jeśli przyjrzymy się uważnie, zobaczymy, że ignoruje również oznaczenie AM/PM (tt
) dla nl-nl
kultura, prawdopodobnie dlatego, że ta kultura zwykle używa zegara 24-godzinnego. Widzimy też, że nawet nasze pozycjonowanie może być w niektórych przypadkach zignorowane (np. fa-ir
).
Jednak nie wszystko jest ignorowane, dlatego otrzymujemy kombinację naszych wyraźnych specyfikacji i tych określonych przez lokalizację.
Znajdowanie/zmiana bieżącego języka
Jak wspomniano, jeśli nie podasz argumentu „kultura”, język bieżącej sesji zostanie użyty do określenia lokalizacji.
Istnieje kilka sposobów na znalezienie języka bieżącej sesji.
Możesz także zmienić lokalizację bieżącego połączenia.
Alternatywnie możesz po prostu użyć SET LANGUAGE
oświadczenie, aby zmienić bieżący język zgodnie z wymaganiami.
Oto krótki przykład użycia SET LANGUAGE
aby pokazać, że twoje własne ustawienia języka mogą wpływać na wyniki formatowania tak samo, jak w przypadku użycia argumentu „kultura”, jak w poprzednich przykładach.
DECLARE @num decimal(3,2) = -1.23; SET LANGUAGE British; SELECT FORMAT(@num, 'C') Result; SET LANGUAGE US_English; SELECT FORMAT(@num, 'C') Result;
Wyniki:
+----------+ | Result | |----------| | -£1.23 | +----------+ +----------+ | Result | |----------| | ($1.23) | +----------+