我的内容已导入我们的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字符固定。
答案 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 documentation,nchar
和nvarchar
数据类型是 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)