如何在SQL Server数据库中使用UTF-8排序规则?


83

我已经将数据库从mysql迁移到使用UTF8的原始mysql数据库SQL Server(政治)。

现在我读到/dba/7346/sql-server-2005-2008-utf-8-collat​​ion-charset SQL Server 2008不支持utf8,这是在开玩笑吗?

SQL Server承载多个数据库,大多数数据库都是拉丁编码的。由于迁移的数据库是用于Web发布的,因此我想保持utf8编码。我错过了什么吗?还是需要在应用程序级别进行编码/拒绝?


实际上,通过创建SQLCLR UDF使用UTF8并没有问题,您可以从Microsoft下载代码。检查此链接:technet.microsoft.com/en-us/library/ms160893
v=sql.90)

1
值得一提的是,Java,JavaScript,DotNet和Windows都在内部使用UTF-16,因此,如果要以任何一种方式对您的网站进行编码,那么您会将转换保存为UTF16。
2016年

1
如果有帮助,您可以假装SQL Server在内部将文本存储为UTF-8。检索时,驱动程序会将其转换回UTF-16。您还可以假装SQL Server将文本存储为UCS-32。内部存储格式是无关的实现细节。重要的是数据库将Unicode字符数据返回为UTF-16(与您的编程环境匹配)。
伊恩·博伊德

Answers:


25

没有!这可不是说笑。

在这里看看:http : //msdn.microsoft.com/en-us/library/ms186939.aspx

字符数据类型为固定长度nchar或可变长度nvarchar Unicode数据,并使用UNICODE UCS-2字符集。

也是这里:http : //en.wikipedia.org/wiki/UTF-16

较早的UCS-2(2字节通用字符集)是一种类似的字符编码,在1996年7月被Unicode标准的2.0版中的UTF-16取代。


好。mssql-client可以转换为外部UTF8-world吗?
Teson 2012年

mssql-client可以是一切。Java,.NET,C,PHP等...客户端的含义是什么?
edze 2012年

1
客户端:phps下的sqlsrv扩展。罗伯特在这里输入清楚的文字: social.msdn.microsoft.com/Forums/en/sqldriverforphp/thread/…,将评估并发布结果。
Teson 2012年

2
再次嗨,您好,抱歉延迟,但感谢您的代表,在连接字符串中使用sqlsrv_connect(,array(“ characterSet” =>“ UTF-8”)..可以正常工作。PDO退出了,对吗?
Teson

29

UTF-8不是字符集,而是一种编码。UTF-8的字符集是Unicode。如果要存储Unicode文本,请使用nvarchar数据类型。

如果数据库将使用UTF-8来存储文本,那么您仍然不会将文本作为编码的UTF-8数据输出,而是将其作为解码的文本输出。

您可以轻松地将UTF-8编码的文本存储在数据库中,但是随后您就不会将其存储为文本,而是将其存储为二进制数据(varbinary)。


感谢您的输入。有更多的学习方法,例如stackoverflow.com/questions/3951722/…–
Teson

我无法解决这个问题。“ UTF8的字符集是Unicode”?utf8的范围不比unicode宽。保存Dauðalogn以Unicode VS UTF8给出不同的结果:(EF BB BF)44 61 75 C3 61 B0 6C 6F 67 6E VS \ u0044 \ u0061 \ u0075 \ u00f0 \ u0061 \ u006c \ u006f \ u0067 \ u006e
泰森

2
@ user247245:UTF-8是编码,而Unicode是字符集。UTF-8是保存Unicode的一种方法。用来表示Unicode的是字符串文字中使用的转义码,通常这不是将Unicode表示为文件的方式。UTF-32是最直接从Uncode转换为文件格式的文件,其中每个字符代码均保存为32位数字。
Guffa 2015年

您能否解释一下为什么上面示例中的第三个字母在UTF8中表示为C3 B0,而在Unicode中则简单表示为F0。谢谢你的帮助。
Teson

4
@ user247245:8到11位之间的字符代码按110xxxxx 10xxxxxxUTF-8(其中x表示数据位)进行编码,因此,字符代码F000011110000如11位)被编码为11000011 1011000000011从第一个字节和110000第二个字节中的字符代码输入))是C3 B0
Guffa 2015年

24

看起来最终将在SQL Server 2019中支持此功能! SQL Server 2019-新增功能

从BOL:

UTF-8支持

完全支持广泛使用的UTF-8字符编码作为导入或导出编码,或作为文本数据的数据库级或列级排序规则。CHARVARCHAR数据类型中允许使用UTF-8 ,并且在创建对象的归类或将其归类为带UTF8后缀的归类时启用。

例如,LATIN1_GENERAL_100_CI_AS_SCLATIN1_GENERAL_100_CI_AS_SC_UTF8。正如SQL Server 2012中引入的那样,UTF-8仅适用于支持补充字符的Windows归类,NCHAR并且NVARCHAR仅允许UTF-16编码,并且保持不变。

根据使用的字符集,此功能可以节省大量存储空间。例如,将具有ASCII字符串的现有列数据类型从NCHAR(10)更改为CHAR(10)使用启用了UTF-8的排序规则,可以将存储需求减少近50%。减少的原因是NCHAR(10),存储需要22个字节,而CHAR(10)同一Unicode字符串则需要12个字节。

2019-05-14更新:

文档似乎现在已更新,并在“排序规则和Unicode支持”部分中解释了在MSSQL 2019中启动的选项。

2019-07-24更新:

Pedro Lopes-高级项目经理@ Microsoft的文章,介绍对Azure SQL数据库的UTF-8支持


4

请注意,如Microsoft SQL Server 2016,UTF-8是支持bcpBULK_INSERTOPENROWSET

附录2016-12-21:SQL Server 2016 SP1现在为所有版本的MS SQL(包括Standard和Express)启用Unicode压缩(以及大多数其他以前仅限企业使用的功能)。这与UTF-8支持不同,但是如果目标是减少西方字母的磁盘空间,则可以产生类似的好处。


但不是OPENQUERY?我想知道这是否就是为什么我在使用OPENQUERY从Oracle迁移CLOB数据时遇到问题。
Geoff Dawdy

4

两个UDF在T-SQL中处理UTF-8:

CREATE Function UcsToUtf8(@src nvarchar(MAX)) returns varchar(MAX) as
begin
    declare @res varchar(MAX)='', @pi char(8)='%[^'+char(0)+'-'+char(127)+']%', @i int, @j int
    select @i=patindex(@pi,@src collate Latin1_General_BIN)
    while @i>0
    begin
        select @j=unicode(substring(@src,@i,1))
        if @j<0x800     select @res=@res+left(@src,@i-1)+char((@j&1984)/64+192)+char((@j&63)+128)
        else            select @res=@res+left(@src,@i-1)+char((@j&61440)/4096+224)+char((@j&4032)/64+128)+char((@j&63)+128)
        select @src=substring(@src,@i+1,datalength(@src)-1), @i=patindex(@pi,@src collate Latin1_General_BIN)
    end
    select @res=@res+@src
    return @res
end

CREATE Function Utf8ToUcs(@src varchar(MAX)) returns nvarchar(MAX) as
begin
    declare @i int, @res nvarchar(MAX)=@src, @pi varchar(18)
    select @pi='%[à-ï][€-¿][€-¿]%',@i=patindex(@pi,@src collate Latin1_General_BIN)
    while @i>0 select @res=stuff(@res,@i,3,nchar(((ascii(substring(@src,@i,1))&31)*4096)+((ascii(substring(@src,@i+1,1))&63)*64)+(ascii(substring(@src,@i+2,1))&63))), @src=stuff(@src,@i,3,'.'), @i=patindex(@pi,@src collate Latin1_General_BIN)
    select @pi='%[Â-ß][€-¿]%',@i=patindex(@pi,@src collate Latin1_General_BIN)
    while @i>0 select @res=stuff(@res,@i,2,nchar(((ascii(substring(@src,@i,1))&31)*64)+(ascii(substring(@src,@i+1,1))&63))), @src=stuff(@src,@i,2,'.'),@i=patindex(@pi,@src collate Latin1_General_BIN)
    return @res
end
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.