四、UTF-8出于国际化和平台独立性的考虑,越来越多的网站和应用程序开始采用UTF-8作为默认字符编码。通常编码转换的工作都是在前端编程语言中实现的。下面给出一下用T-SQL实现的UCS-2与UTF-8的互转函数,没有太多实际应用价值,仅仅是一个示例:(也没准会遇到需要在数据库层面对utf8字串进行编解码的情况,这两个函数就排上用场了。)CREATE FUNCTION dbo.ucs2_to_utf8(
@ucs2 varbinary(max)
)
RETURNS varbinary(max)
AS
/*
U-00000000 ... U-0000007F 0xxxxxxx 
U-00000080 ... U-000007FF 110xxxxx 10xxxxxx 
U-00000800 ... U-0000FFFF 1110xxxx 10xxxxxx 10xxxxxx 
*/
BEGIN
DECLARE
@output varbinary(max),
@i int,
@code int
SET @output = 0x
SET @i = 1
WHILE 1 = 1
BEGIN
SET @code = CAST(SUBSTRING(@ucs2,@i+1,1) + SUBSTRING(@ucs2,@i,1) AS int)
IF @code = 0
BREAK
IF @code >= 0x0800
SET @output = @output +
CAST(@code / 4096 + 224 AS binary(1)) +
CAST((@code % 4096) / 64 + 128 AS binary(1)) +
CAST((@code % 4096) % 64 + 128 AS binary(1))
ELSE IF @code >= 0x0080
SET @output = @output +
CAST(@code / 64 + 192 AS binary(1)) +
CAST(@code % 64 + 128 AS binary(1))
ELSE
SET @output = @output + CAST(@code AS binary(1))
SET @i = @i + 2
END
RETURN @output
END
GO
CREATE FUNCTION dbo.utf8_to_ucs2(
@utf8 varbinary(max)
)
RETURNS varbinary(max)
AS
BEGIN
DECLARE
@output varbinary(max),
@i int,
@next int,
@code int,
@tmp varbinary(1)
SET @output = 0x
SET @i = 1
SET @next = 0
WHILE 1 = 1
BEGIN
SET @tmp = SUBSTRING(@utf8,@i,1)
IF @tmp = 0x
BREAK
IF @tmp BETWEEN 0x01 AND 0x7F
SET @output = @output + @tmp + 0x00
ELSE IF @tmp BETWEEN 0xC0 AND 0xDF
BEGIN
SET @code = (CAST(@tmp AS int) & 0x1F) * 64
SET @next = 1
END
ELSE IF @tmp BETWEEN 0xE0 AND 0xEF
BEGIN
SET @code = (CAST(@tmp AS int) & 0x0F) * 4096
SET @next = 2
END
ELSE IF @tmp BETWEEN 0x80 AND 0xBF AND @next IN (1,2)
BEGIN
IF @next = 1
BEGIN
SET @code = @code + (CAST(@tmp AS int) & 0x3F)
SET @output = @output + CAST(NCHAR(@code) AS binary(2))
END
IF @next = 2
SET @code = @code + (CAST(@tmp AS int) & 0x3F) * 64
SET @next = @next - 1
END
ELSE
RETURN NULL
SET @i = @i + 1
END
RETURN @output
END
GO五、其它常见问题如上所述,在指定Chinese_PRC_CI_AS为默认排序规则的情况下,char/varchar使用cp936编码,也可以存储中文。但个人建议是,char/varchar只用以存储ASCII字符,对于包含大于127的非ASCII字符的字符串,统一用nchar/nvarchar存储。这样,不但可以支持多语言,不会造成其他语言的字符遗失,而且可以避免许多计算上的问题。例如:DECLARE @str varchar(100)
SET @str = '1234567一二三四五六七'
SELECT LEN(@str)               --14
SELECT LEFT(@str,10)           --1234567一二三
DECLARE @col varchar(10)
SET @col = LEFT(@str,10)
SELECT @col                    --1234567一
倘若在char/varchar中包含了中文字符,SQLServer的字符串函数(包括LEN、LEFT/RIGHT、SUBSTRING、STUFF、CHARINDEX/PATINDEX)会把一个中文字符(双字节)作为一个字符处理,而定义变量或列时指定的数据类型char/varchar却是以字节为单位,结果则如上例,截取了一个字串的10个字符,却无法放入一个varchar(10)的变量或列中,这种违反直觉的不一致会给系统带来一些讨厌的BUG。