2009-06-22 29 views
9

非常に奇妙な問題に直面しました(このような成熟した製品には本当に奇妙です): Transact-SQL文を使用してUnicode文字列の文字数を取得する方法。 len() TSQL関数が末尾の空白を除いて、文字数を返すというこの問題の重要な問題です。もう1つの方法は、datalength(バイト数を返す)を使用して2で割ることで、Unicode文字の数を取得します。しかし、Unicode文字は代理ペアになる可能性があるので、どちらも機能しません。文字列内の文字数を取得する方法

私たちは2種類のソリューションを持っています:最初にlen(replace())を使用し、2番目に単一シンボルを追加してから結果から1を引きます。しかし、IMOの両方の変種はかなり醜いです。末尾のスペースを持つ文字列で文字をカウントする方法を

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 

他のアイデア?

+1

うわー、私はそれが後続の空白を削除は思いもしませんでした!私は個人的にはaddAndMinusBehaviourを使うでしょう。 –

+2

個人的に私はあなたの 'addAndMinusBehaviour'について醜いことは何も見ません - 実際には、それはむしろ賢いと思います。 – AakashM

+0

私はこれをオプションのlen(reverse(@txt))として見いだしました。これは末尾のスペースでは動作しますが、先頭のスペースでは壊れてしまうことは明らかです。 –

答えて

5

私はコメントを残すことができないので、私は答え(またはシャットダウン)を残す必要があります。

私の投票は、私は、良い第3の選択肢を持っていないかもしれないいくつかのあいまいな空白のルールはオプション/ SET /照合順序の割り当てにそこをいじることではなく、オフの詳細を知らないaddAndMinusBehaviour

のためになる

私の頭の上。

ですが、実際にはaddAndMinusBehaviourは実装が最も簡単で、実行が速く、ドキュメント化しておくと、メンテナンスが容易です。

+0

今後のコメントができるよう、いくつかの点を挙げて投票してください。 (私もコメントすることができませんでした。) – Vaccano

3

DATALENGTH(@txt)/ 2は常に文字数を指定しなければならないと私は理解しています。 SQL Serverは、サロゲートペアをサポートしていないUCS-2にUnicode文字を格納します。

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

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

+0

私たちのチームリーダーとの短い議論の末、UTF-16テキストをUCS-2 charsサブセットに格納できると考えました。 サロゲートを含むUTF-16シングルシンボルは、UCS-2の2つのシンボルに変換され、正しいlen()結果が破られます。 UTF-16 UCS-2サブセットのロックのもう1つの側面は、SQLServerの将来のバージョンについてはわからないことです。私は正確にSQL2008のnvarcharストアモードに関する情報を見つけることはできませんが、あなたが指摘した2005年のものと似ているようです。しかし、私たちが長期的にサポートしているシステムを構築するには、それをロックすることはできません。 BTW - UCS-2についての良い点は、これまで気付かなかったことです。 –

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

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

END 
GO