2009-06-22 15 views
9

Stawiliśmy czoła bardzo dziwnemu problemowi (naprawdę dziwnemu w przypadku tak dojrzałego produktu): jak uzyskać liczbę znaków w ciągu znaków Unicode za pomocą instrukcji Transact-SQL . Kluczowym problemem tego problemu jest to, że funkcja TSQL len() zwraca liczbę znaków, wykluczając końcowe znaki. Innym wariantem jest użycie długości danych (która zwraca liczbę bajtów) i podzielenie przez 2, więc zdobądź liczbę znaków Unicode. Ale znaki Unicode mogą być parami zastępczymi, więc to też nie zadziała.Jak uzyskać liczbę znaków w łańcuchu w języku Transact SQL, "w inny sposób"

Mamy 2 warianty rozwiązania: pierwszy to użycie len(replace()), a drugi to dodanie pojedynczego symbolu, a następnie odjęcie 1 od wyniku. Ale IMO oba warianty są raczej brzydkie.

declare @txt nvarchar(10) 
set @txt = 'stack ' 
select @txt as variable, 
len(@txt) as lenBehaviour, 
DATALENGTH(@txt)/2 as datalengthBehaviour, 
len(replace(@txt,' ','O')) as ReplaceBehaviour, 
len(@txt+'.')-1 as addAndMinusBehaviour 

Jakieś inne pomysły na zliczanie znaków w łańcuchu z końcowymi spacjami?

+1

Wow, nie miałem pojęcia, że ​​usunięte spacjami! Osobiście pójdę z addAndMinusBehaviour. –

+2

Osobiście nie widzę nic brzydkiego w twoim "addAndMinusBehaviour" - w rzeczywistości myślę, że jest to dość sprytne. – AakashM

+0

Znalazłem to jako opcję len (reverse (@txt)), które będzie działało dla spacji końcowych, ale oczywiście będzie się zrywało z wiodącymi spacjami. –

Odpowiedz

5

Nie mogę zostawić komentarza, więc będę musiał zostawić odpowiedź (lub zamknięcie).

Mój głos będzie dla addAndMinusBehaviour

Nie mam dobrą trzecią alternatywę, nie może jakieś niejasne zasadami odstępu, aby pobawić się w opcje/ustawienia/przyporządkowania Układanie ale nie wiem więcej szczegółów off czubek mojej głowy.

ale naprawdę addAndMinusBehaviour jest prawdopodobnie najłatwiejszy w implementacji, najszybszy do wykonania, a jeśli go udokumentujesz, również będzie można go łatwo konserwować.

+0

Głosuj, aby podać kilka punktów, aby móc komentować w przyszłości. (Nienawidziłem nie być w stanie komentować.) – Vaccano

3

Rozumiem, że DATALENGTH (@txt)/2 powinien zawsze podawać liczbę znaków. SQL Server przechowuje znaki Unicode w UCS-2, które nie obsługują par zastępczych.

http://msdn.microsoft.com/en-us/library/ms186939.aspx

http://en.wikipedia.org/wiki/UCS2

+0

Po krótkiej dyskusji z naszym kierownikiem zespołu stwierdziliśmy, że tekst UTF-16 może być przechowywany w podzbiorze znaków UCS-2. Pojedynczy symbol z surogatem UTF-16 zostanie przekształcony w 2 symbole UCS-2 i tym samym złamał poprawny wynik len(). Druga zła strona blokowania podzbioru UTF-16 UCS-2, którego nie można mieć pewności co do przyszłych wersji SQLServer. Nie mogę znaleźć informacji o dokładnie trybie Nvarchar w SQL2008, wygląda on podobnie do tego, który wskazałeś w 2005 roku. Ale jeśli chodzi o budowanie długoterminowego systemu wsparcia - nie możemy tego zablokować. BTW - dobry punkt o UCS-2, nigdy wcześniej tego nie zauważyłem. –

4
CREATE FUNCTION [dbo].[ufn_CountChar] (@pInput VARCHAR(1000), @pSearchChar CHAR(1)) 
RETURNS INT 
BEGIN 

RETURN (LEN(@pInput) - LEN(REPLACE(@pInput, @pSearchChar, ''))) 

END 
GO 
Powiązane problemy