Inną opcją jest obsługiwanie tego za pośrednictwem SQLCLR. Istnieje nawet metoda dostępna w .NET, która to robi: TextInfo.ToTitleCase (in System.Globalization
). W tej metodzie pierwsza litera każdego słowa będzie pisana dużymi literami, a pozostałe - małymi literami. W przeciwieństwie do innych propozycji tutaj, pomija także słowa pisane wielkimi literami, zakładając, że są to akronimy. Oczywiście, jeśli takie zachowanie jest pożądane, łatwo byłoby zaktualizować dowolną z sugestii T-SQL, aby to zrobić.
Jedną z zalet metody .NET jest to, że może ona zawierać duże litery, które są znakami uzupełniającymi. Na przykład: DESERET SMALL LETTER OW ma mapowanie wielkich liter DESERET CAPITAL LETTER OW (oba pokazują się jako pola po wklejeniu ich tutaj) , ale UPPER()
funkcja nie zmienia wersji małych liter na duże litery, nawet gdy domyślne sortowanie dla bieżącej bazy danych jest ustawione na Latin1_General_100_CI_AS_SC
. Wydaje się to spójne z dokumentacją MSDN, która nie zawiera tej listy, UPPER
oraz LOWER
w zestawieniu funkcji, które zachowują się inaczej podczas korzystania z _SC
Collation: Collation i Unicode: Supplementary Characters .
SELECT N'DESERET SMALL LETTER OW' AS [Label], NCHAR(0xD801)+NCHAR(0xDC35) AS [Thing]
UNION ALL
SELECT N'DESERET CAPITAL LETTER OW' AS [Label], NCHAR(0xD801)+NCHAR(0xDC0D) AS [Thing]
UNION ALL
SELECT N'SmallButShouldBeCapital' AS [Label], UPPER(NCHAR(0xD801)+NCHAR(0xDC35)) AS [Thing]
Zwraca (powiększony, aby można było zobaczyć postać dodatkową):
Możesz zobaczyć pełną (i bieżącą) listę znaków pisanych małymi literami i przechodzić na wielkie litery, korzystając z następującej funkcji wyszukiwania na Unicode.org (możesz zobaczyć dodatkowe znaki przewijając w dół, aż dojdziesz do „DESERET” lub po prostu naciśnij Control-Fi wyszukaj to słowo):
http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AChanges_When_Titlecased%3DYes%3A%5D
Chociaż szczerze mówiąc, nie jest to ogromna korzyść, ponieważ wątpliwe jest, aby ktokolwiek faktycznie używał któregokolwiek z Postaci Uzupełniających, które można umieścić w tytułach. Tak czy inaczej, oto kod SQLCLR:
using System.Data.SqlTypes;
using System.Globalization;
using Microsoft.SqlServer.Server;
public class TitleCasing
{
[return: SqlFacet(MaxSize = 4000)]
[Microsoft.SqlServer.Server.SqlFunction(IsDeterministic = true, IsPrecise = true)]
public static SqlString TitleCase([SqlFacet(MaxSize = 4000)] SqlString InputString)
{
TextInfo _TxtInf = new CultureInfo(InputString.LCID).TextInfo;
return new SqlString (_TxtInf.ToTitleCase(InputString.Value));
}
}
Oto sugestia @ MikaelEriksson - nieznacznie zmodyfikowana, aby obsługiwać NVARCHAR
dane, a także pomijać słowa pisane wielkimi literami (aby lepiej pasowały do zachowania metody .NET) - wraz z testem tej implementacji T-SQL i implementacja SQLCLR:
SET NOCOUNT ON;
DECLARE @a NVARCHAR(50);
SET @a = N'qWeRtY kEyBoArD TEST<>&''"X one&TWO '
+ NCHAR(0xD801)+NCHAR(0xDC28)
+ N'pPLe '
+ NCHAR(0x24D0) -- ⓐ Circled "a"
+ NCHAR(0xFF24) -- D Full-width "D"
+ N'D u'
+ NCHAR(0x0308) -- ̈ (combining diaeresis / umlaut)
+ N'vU'
+ NCHAR(0x0308) -- ̈ (combining diaeresis / umlaut)
+ N'lA';
SELECT @a AS [Original];
SELECT STUFF((
SELECT N' '
+ IIF(UPPER(T3.V) <> T3.V COLLATE Latin1_General_100_BIN2,
UPPER(LEFT(T3.V COLLATE Latin1_General_100_CI_AS_SC, 1))
+ LOWER(STUFF(T3.V COLLATE Latin1_General_100_CI_AS_SC, 1, 1, N'')),
T3.V)
FROM (SELECT CAST(REPLACE((SELECT @a AS N'*' FOR XML PATH('')), N' ', N'<X/>')
AS XML).query('.')) AS T1(X)
CROSS APPLY T1.X.nodes('text()') AS T2(X)
CROSS APPLY (SELECT T2.X.value('.', 'NVARCHAR(70)')) AS T3(V)
FOR XML PATH(''), TYPE
).value('text()[1]', 'NVARCHAR(70)') COLLATE Latin1_General_100_CI_AS_SC, 1, 1, N'')
AS [Capitalize first letter only];
SELECT dbo.TitleCase(@a) AS [ToTitleCase];
Inną różnicą w zachowaniu jest to, że ta konkretna implementacja T-SQL dzieli się tylko na spacje, podczas gdy ToTitleCase()
metoda uważa , że większość liter niebędących literami stanowi separatory słów (stąd różnica w obsłudze części „one & TWO”).
Obie implementacje poprawnie obsługują łączenie sekwencji. Każda z akcentowanych liter w „üvÜlA” składa się z litery podstawowej i łączącej diaeresis / umlaut (dwie kropki nad każdą literą) i w obu testach są one poprawnie konwertowane na drugi przypadek.
Wreszcie, jedną nieoczekiwaną wadą wersji SQLCLR jest to, że przy opracowywaniu różnych testów znalazłem błąd w kodzie .NET związany z obsługą listów w kółku (który został teraz zgłoszony w Microsoft Connect - AKTUALIZACJA: Connect został przeniósł się do /dev/null
- dosłownie - więc może być konieczne ponowne przesłanie tego, jeśli problem nadal występuje). Biblioteka .NET traktuje litery w kółko jako separatory słów, dlatego nie zamienia „ⓐDD” w „Ⓐdd” tak, jak powinno.
FYI
Wstępnie wykonana funkcja SQLCLR enkapsulująca TextInfo.ToTitleCase
powyższą metodę jest teraz dostępna w bezpłatnej wersji SQL # (którą napisałem) jako String_ToTitleCase i String_ToTitleCase4k .
😺