2013-04-23 51 views
1

我們有一個奇怪的問題。我們正在升級JDE並且數據庫模式正在改變 - 一些char列正在改變爲nchar類型。但是,我們發現一些搜索不再有效,並且我們發現這在我們的SQL Server 2008數據庫中是一致的:SQL Server char和nchar列以不同的方式搜索

在我測試的數據庫中,ItemNumber列是char(25)並且具有不同的長度內容。

SELECT * FROM TableName WHERE ItemNumber LIKE '%S' 

返回一堆行。但是,如果我們將列更改爲nchar(25),那麼查詢現在僅返回那些以「S」結尾的ItemNumber值爲的行的長度爲25個字符,因此現在似乎尾隨空格(可能是正確的) - 如果將通配符值更改爲「%S」,則會查找以「S」結尾的24個字符的項目編號。

顯然,這對我們來說是一個相當大的問題,因爲* S搜索不再適用於JDE,因爲底層數據庫調用現在需要修改每個nchar列。這是一個已知的問題,還是一個我們需要改變的地方?

其他信息 我們沒有在使用的列類型的任何控制,也不是我們可以改變所產生的潛在的SQL,因爲這是我們的ERP系統及其升級的一部分。我們已經與甲骨文公司打過電話了,但據我所知,他們沒有看到這一點,也不能複製它(但我們不知道他們在什麼情況下試圖做到這一點),加上它的事實發生在我們其他的數據庫/服務器上,這讓我懷疑它是不是一個晦澀難懂的設置。

+4

爲什麼使用char或nchar代替varchar或nvarchar?爲什麼 - 如果你已經將它更改爲Unicode - 你是不是正確地爲你的字符串加上前綴('WHERE ItemNumber LIKE N'%S';')? – 2013-04-23 13:57:44

+2

我不會使用char或nchar,除非該字段被重用爲特定的長度(如2位數的statecodes)。否則,當需要使用varchar或nvarchar類型避免它們時,您將需要修剪哪些內容會浪費處理能力。這是一個設計更改,您不需要編碼更改。 – HLGEM 2013-04-23 14:09:38

+0

請參閱上面我更新的附加信息 - 我們無法控制所使用的數據類型(事實上,我同意你的觀點並從未理解爲什麼將它們設置爲char)。再一次,就像你一樣,我在搜索時想到了N個前綴,但是: - a)這沒有什麼區別,b)我不認爲這個解決方案對我們有幫助,無論如何,因爲我們不能改變(AFAIK )基礎SQL生成。 – 2013-04-23 14:20:19

回答

6

從爲LIKE (Transact-SQL)的文檔:

當您使用LIKE Unicode數據(的nchar或nvarchar數據類型),尾隨空白是顯著;但是,對於非Unicode數據,尾隨空格並不重要。

我複製你的問題如下表:

DECLARE @t TABLE(x NCHAR(25)); 
INSERT @t SELECT N'nanaS'; 
SELECT x FROM @t WHERE x LIKE N'%S'; 

結果:

(0 row(s) affected) 

但是如果你使用NVARCHAR代替,不會出現此問題:

DECLARE @t TABLE(x NVARCHAR(25)); 
INSERT @t SELECT N'nanaS'; 
SELECT x FROM @t WHERE x LIKE N'%S'; 

結果:

x 
----- 
nanaS 

但是原來的表沒有產生,即使轉換爲NVARCHARWHERE子句中所期望的結果:

DECLARE @t TABLE(x NCHAR(25)); 
INSERT @t SELECT N'nanaS'; 
SELECT x FROM @t WHERE CONVERT(NVARCHAR(25),x) LIKE N'%S'; 

結果:

(0 row(s) affected) 

所以一個潛在的解決方法是首先使用正確的數據類型(並且始終以Unicode字符串前綴N'properly'。如果您無法使數據類型正確,則可以使用Aushin發佈的RTRIM()解決方法,但也要記住HLGEM的註釋。

+0

爲了清楚起見,我認爲當文檔引用'NVARCHAR'類型的尾部空格時,它指的是顯式尾隨空格(即'Test'末尾的空格),而不是由於該類型(因爲它是可變長度的)。所以我不認爲行爲與文件相矛盾,儘管文件不是很清楚。這在[this fiddle](http://sqlfiddle.com/#!3/62d69/1)中得到了證明,其中第3行在NVARCHAR列中有'A',並且不像'%A' 。 – GarethD 2013-04-23 14:22:59

+0

啊,這很有趣 - 我一直在尋找這樣的信息,但我一直在努力尋找任何提及它的東西。簡直不敢相信我只想檢查LIKE手冊頁。我*完全贊同你的觀點,即列應該是一個nvarchar,但是我們對數據庫表設置有* no *控制。我不能相信這不會發生在其他人身上 - 通過我猜測這些東西的外觀,我不能把它關掉。 – 2013-04-23 14:24:00

+1

@MadHalfling它可能發生在其他人身上,他們只是停止使用NCHAR。並不是每個人都會遇到糟糕的設計。 :-) – 2013-04-23 14:34:20

3

編輯:我下面的解釋是基於你的問題的誤讀。雖然RTRIM會工作,但我沒有意識到你沒有使用nvarchar,但char。亞倫和戈登提供了更好的見解。

SELECT * FROM TableName WHERE RTRIM(ItemNumber) LIKE N'%S' 

這是因爲對於一個nvarchar(25), 'S' 的最後一個字符是S.

對於NCHAR(25), 'S' 實際上是 'S' + 24空間。所以你的最後一個字符 是一個空格。

+0

請使用N前綴'LIKE N'%S'' – 2013-04-23 13:58:15

+0

謝謝你的提醒。 – Aushin 2013-04-23 13:59:19

+0

尾隨空格在LIKE的LHS上並不重要。例如'select 1 where'X'+ SPACE(24)like'%X'' returns'1' – 2013-04-23 14:00:47

相關問題