SQL Server在nvarchar字符串中选择unicode null字符

时间:2013-01-14 23:01:22

标签: sql sql-server unicode null

我的内容已导入我们的SQL Server 2008数据库(使用排序规则SQL_Latin1_General_CP1_CI_AS),该数据库已被nvarchar(128)列中的UNICODE NULLS污染。

影响是当它们试图导出PDF报告和其他此类操作中的内容时,它会炸毁我们的java库。

我正在尝试查找和修改各种表和列中的值。我们的一些工作人员告诉我,违规值看起来像'u s e r n a m e'而不是'username'

在尝试查找这些违规的UNICODE NULLS时,我运行了以下SQL:

SELECT name 
FROM users
WHERE name LIKE '%[^ -~]%' COLLATE Latin1_General_BIN

返回的是以下集合:

M
M
M
N
S
S
S
S
ÿþA

我认为这些单字母值可能会跟随UNICODE NULLS,但我不确定。最后一个肯定也看起来很可疑。

是否有某种方法可以使用CONVERT和十六进制值 - 0x00来查找nvarchar字符串中的UNICODE NULLS?

编辑#1:

select name, CAST(RIGHT(name,1) AS varbinary(128)) AS RIGHTER_1,
from users
where id=1

returns:

B   0x4200

所以,那封信' B'有点好笑。这里确实有UNICODE NULLS,并且这些库没有被设计来处理UNICODE。他们用LATIN UTF8字符固定。

3 个答案:

答案 0 :(得分:0)

您可以使用CAST(name AS varbinary(128))将值视为十六进制并进行检查。

你可以使用条件name LIKE '%'+CHAR(0)+'%'找到'空字符',但是,有效的unicode字符串也可能包含零,所以这可能不是你需要做的。

您确定问题不在您的图书馆或PDF生成器中吗?看起来您在数据库中有unicode字符串,但应用程序将它们解释为ASCII字符串。

答案 1 :(得分:0)

尝试使用varbinary转换查找空的unicode字符序列可能会导致误报,例如UTF16 LE中的以下unicode:

20 00 00 A0

字符串是一个空格,后跟一个unicode字符A0。两者都是有效的非空字符。但是如果你这样做了:

where charindex (0x0000, cast(UnicodeText as varbinary (max))) > 0

你会在空格的结尾和下一个角色的开头之间得到误报。

这是我写的一个功能。请注意,它对大文本的表现不佳,我正在努力改进。可能CLR proc会更好地工作。试试这个:

    create function dbo.FindNullUnicode
(
    @Input nvarchar(max)
    ,@StartPosition bigint = 1
)
returns bigint
as
begin
    if @StartPosition < 1
        set @StartPosition = 1;

    declare @pos bigint = @StartPosition;
    declare @len bigint = len(@Input);
    declare @singlechar nchar(1);

    while (@pos <= @len)
    begin
        if unicode(SUBSTRING(@input,@pos,1)) = 0 
            return @pos;

        set @pos +=1;
    end;
    return 0;
end

答案 2 :(得分:0)

认为原帖超过9个月,我相信这对于海报来说太迟了。但是,per the documentationncharnvarchar数据类型 Unicode。它们被定义为:

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

UCS-2表示列中的每个字符占用2个字节。如果数据是单字节字符,则高位字节将为0x00,自然而且每隔一个八位字节为0x00。

最初的问题是消费者几乎肯定期待ASCII或UTF-8数据而不是UCS-2 / UTF-16。这些列很可能已声明为char / varchar而不是nchar / nvarchar。正确的解决方案是执行以下操作之一:

  • 更改表格,使列成为正确的数据类型
  • 使用convert()函数更改查询以转换列,因此:convert(varchar(4000),my_nvarchar_column)
  • 更改消费者以正确使用双字节字符。