2015-09-30 26 views
1

我的同事和我在SQL-Server中遇到了一個奇怪的行爲。爲什麼一個案例中的一個場景的內容決定是否應該修剪其他內容?

考慮下面的代碼:

select a = 
    case when 1=1 then 
     'a ' 
    else 
     'b ' 
    end + 'c' 

人們會應該合理假設以上代碼生成字符串「爲C」。它確實如此。

但是,如果我延長else的常數(「B「)與額外的空間,一些奇怪的事情發生了:

select a = 
    case when 1=1 then 
     'a ' 
    else 
     'b ' 
    end + 'c' 

現在的結果是‘交流’,從空間‘’具有消失了。反過來也是如此:

select a = 
    case when 1=0 then 
     'a ' 
    else 
     'b ' 
    end + 'c' 

這將產生'bc'。所以當常量不被返回的時間比被返回的常量長時,被返回的常量被修剪。

而且它只是一個正確的修剪,因爲下面的代碼將產生「交流」:

select a = 
    case when 1=1 then 
     ' a ' 
    else 
     'b ' 
    end + 'c' 

是有此行爲的原因是什麼?我認爲它可能與清理字符串尾部空白有關,但爲什麼只有當常量不被返回時纔會發生?

在SQL Server 2014 Express Edition上觀察到上述行爲。

更新:

正如評論所說,這種行爲不會出現要在SQL Server的標準安裝可重複2014年

+1

我無法重現問題 –

+0

SQL-Server的版本和發行版可以在SQLFiddle上重現嗎? – MatBailie

+0

好奇,也許它與我的查詢執行設置有關。目前,我只設置了「SET ARITHABORT」標誌並且沒有ANSI標誌。我正在使用SQL Server 2014.而且我無法在SQLFiddle上重現該行爲。這一定與我們的設置有關。我不知道是什麼設置導致它。 – Svip

回答

3

它看起來像你的會話具有SET ANSI_PADDING OFF,這將削減尾隨空格varchar。嘗試使用SET ANSI_PADDING ON(推薦設置)運行。

SET ANSI_PADDING OFF; 

--trims trailing spaces 
SELECT a = 
    CASE WHEN 1=1 THEN 
     'a ' 
    ELSE 
     'b ' 
    END + 'c'; 

--does not trim trailing spaces 
SET ANSI_PADDING ON; 

SELECT a = 
    CASE WHEN 1=1 THEN 
     'a ' 
    ELSE 
     'b ' 
    END + 'c'; 

編輯:

SQL Server ANSI_PADDING documentation,設定應只適用於列存儲,而不是表達的結果。我詢問了這種行爲,並且SQL Server MVP Erland Sommarskog使用古老的SQL Server版本進行了一些迴歸測試,並將此行爲確定爲SQL 7中引入的一個錯誤。它在SQL 2000中得到糾正,但僅在ANSI_PADDING ON; ANSI_PADDING OFF繼續行事至今。

我強烈建議您將代碼更改爲不依賴無證和錯誤的行爲。此錯誤可能會在未來的SQL Server版本或補丁中修復並破壞您的代碼。如果您的應用程序需要刪除尾部空格,請明確使用RTRIM函數。

+0

是的。這似乎是正確的答案。謝謝。我們可能想考慮重新啓用這個標誌。 – Svip

+0

雖然你的答案很有用,但它仍然不能解釋爲什麼沒有啓動ANSI_PADDING就會出現這種情況。無論你如何看待它,這似乎都是一種特別奇怪的行爲。 Sybase不這樣做,所以它不能成爲向後兼容性問題。 – Svip

+0

@Svip,自從我與Sybase合作已近20年了。你是否說Sybase與'ANSI_PADDING OFF'有不同的表現?請注意,客戶端API可能會在連接時設置會話設置。現代API默認打開這個選項。 –

相關問題