とりあえず改良 LEN 関数 (U_LEN)
使う場合は自己責任で。
-- ============================================= -- Author: bleis-tift -- Create date: 2009/5/17 -- Description: サロゲート文字を考慮した文字列長を取得します。 -- ============================================= CREATE FUNCTION U_LEN ( @str nvarchar(max) ) RETURNS int AS BEGIN /* * UTF-16ではUnicodeのスカラ値000uuuuuxxxxxxxxxxxxxxxxを、 * 110110wwwwxxxxxx 110111xxxxxxxxxxの2バイトで表す(wwwwはuuuuu-1)。 * この先頭のビット列110110を判定するために、 * 1111110000000000(十進数で64512)をマスクとし、ビットごとに論理積を取った際、 * 1101100000000000(十進数で55296)と等しくなればサロゲート文字とみなす。 */ DECLARE @MASK AS int; DECLARE @SURROGATE_PAT AS int; SET @MASK = 64512; SET @SURROGATE_PAT = 55296; DECLARE @result AS int; SET @result = 0; DECLARE @i AS int; DECLARE @len AS int; SET @i = 1; SET @len = LEN(@str); DECLARE @is_surrogate AS bit; SET @is_surrogate = 0; WHILE @i <= @len BEGIN DECLARE @ch AS int; SET @ch = UNICODE(SUBSTRING(@str, @i, 1)); IF @is_surrogate = 1 SELECT @result = @result + 1 , @is_surrogate = 0 ; -- サロゲートペアのパターンに一致した段階では結果をインクリメントしない ELSE IF @ch & @MASK = @SURROGATE_PAT SET @is_surrogate = 1; ELSE SET @result = @result + 1; SET @i = @i + 1; END RETURN @result; END