查看this answer有類似問題的人。對不起,如果這是一個長長的囉嗦:
SQL Server似乎通過映射不可代表的字符(沒有合適的替代字符)到問號來將Unicode變爲ASCII。要複製它,請嘗試打開Character Map Windows程序(應該安裝在大多數機器上),選擇Arial作爲字體並找到U + 034f「組合Grapheme連接器」。選擇這個角色,複製到剪貼板,然後粘貼下面的單引號之間:
declare @t nvarchar(10)
set @t = '͏'
select rtrim(ltrim(@t)) -- we can try and trim it, but by this stage it's already a '?'
你會得到一個問號了,因爲它不知道如何當它施放它代表了這個非ASCII字符到varchar
。爲了強制它接受它爲雙字節字符(nvarchar
),您需要改爲使用N''
,如前所述。上述引號前添加N
問號消失(但原來不可見字符在輸出保存 - 和ltrim
,並如下面所示rtrim
將無法將其刪除):
declare @t nvarchar(10),
@s varchar(10) -- note: single-byte string
set @t = rtrim(ltrim(N'͏')) -- trimming doesn't work here either
set @s = @t
select @s -- still outputs a question mark
進口數據絕對可以做到這個,我以前見過,像上面顯示的那些人物特別難以診斷,因爲你看不到他們!您需要創建某種清理流程來刪除這些不打印郵件(以及其他任何垃圾郵件),並確保您在任何地方都使用nvarchar
,否則最終會出現此問題。更糟的是,那些虛幻的問號將成爲真正的問號,你將無法與合法問號區分開來。
要查看字符代碼你處理,你可以投爲varbinary如下:
declare @t nvarchar(10)
set @t = N'͏test?'
select cast(@t as varbinary) -- returns 0x4F0374006500730074003F00
-- Returns:
-- 0x4F03 7400 6500 7300 7400 3F00
-- badchar t e s t ?
我們擺脫它:
declare @t nvarchar(10)
set @t = N'͏test?'
select cast(@t as varbinary) -- bad char
set @t = replace(@t COLLATE Latin1_General_100_BIN2, nchar(0x034f), N'');
select cast(@t as varbinary) -- gone!
注意,我不得不調換字節順序從0x4f03
到0x034f
(同樣的原因「t」在輸出中出現爲0x7400
,而不是0x0074
)。有關我們使用二進制排序規則的一些說明,請參閱this answer。
這是一種混亂,因爲你不知道什麼是骯髒的人物,他們可能是成千上萬的可能性之一。一種選擇是使用like
甚至unicode()
function迭代字符串,並放棄不在可接受字符列表中的字符串中的字符,但這可能會很慢。這可能是因爲你的大部分壞字符都在字符串的開始或結尾,如果這是你認爲可以做出的假設,那麼這可能會加速這個過程。
根據我上面向您展示的內容,如果您需要導入大量數據,您可能需要在SQL Server外部或作爲SSIS導入的一部分構建其他進程。如果您不確定這是否是最好的方法,那麼最好在一個新問題中回答。
我希望有幫助。
如果您執行Ltrim(@temp)會怎麼樣? – Harry
注意:如果出於某種原因想要保持字符串不變,您應該設置@temp = N'mystring'(顯式聲明該字符串是unicode,即使您的變量是NVARCHAR,也應該這樣做')而不是你目前正在做的事情。 – ZLK
看起來像一個字符集不匹配。 – Namphibian