2013-01-14 66 views
0

我的內容已導入我們的SQL Server 2008數據庫(使用排序規則SQL_Latin1_General_CP1_CI_AS),該列表受到在nvarchar(128)列中受UNICODE NULLS污染的數據的影響。SQL Server在nvarchar字符串中選擇unicode空字符

其影響是當他們嘗試導出PDF報告中的內容和其他此類操作時,它爆炸了我們的Java庫。

我想查找和修改各種表和列中的值。我的一些員工告訴我,這些違規值看起來像'u s e r n a m e'而不是'username'

在試圖找到這些問題的UNICODE空值,我已經運行的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的。他們與拉丁UTF8字符堅如磐石。

回答

0

您可以使用CAST(name AS varbinary(128))來查看十六進制值並檢查它。

您可以使用條件name LIKE '%'+CHAR(0)+'%'找到'空字符',但是,有效的Unicode字符串也可以包含零,因此這可能不是您需要執行的操作。

您確定問題不在您的圖書館或PDF生成器中嗎?它看起來像數據庫中有unicode字符串,但應用程序正在將它們解釋爲ASCII字符串。

+0

Vladv--這將返回所有在表中的行:從用戶 其中名稱LIKE '%' + CHAR(0)+ '%' 選擇ID,名稱 – mrTexasFreedom

0

試圖尋找使用VARBINARY轉化可導致假陽性空Unicode字符序列,例如下面的unicode在UTF16 LE:

20 00 00 A0 

的字符串是一個空格,接着Unicode字符A0。兩者都是有效的非空字符。但是,如果你這樣做:

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

你會得到一個空間結束和下一個字符開始之間的誤報。

這是我寫的一個函數。請注意,它在大文本方面表現不佳,我正在努力改進。 CLR過程可能會更好。試試這個:

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 
0

給出原始帖子超過9個月大,這是,我相信,海報已經太晚了。但是,per the documentation,ncharnvarchar數據類型 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)
  • 改變消費者以正確使用雙字節字符。