2017-06-29 25 views
0

這裏的情況的一個例子:爲什麼過濾後的視圖在過濾後的查詢中使用時無法轉換?

CREATE TABLE dbo.TestConversionTable 
(
    Value VARCHAR(MAX) 
) 

INSERT INTO dbo.TestConversionTable VALUES ('1') 
INSERT INTO dbo.TestConversionTable VALUES ('foo') 

CREATE VIEW dbo.TestConversion 
AS 
    SELECT CONVERT(BIGINT,Value) Value 
    FROM dbo.TestConversionTable 
    WHERE Value <> 'foo' 
GO 

SELECT * FROM dbo.TestConversion --this works 
SELECT * FROM dbo.TestConversion WHERE Value = 1 --Error converting data type varchar to bigint. 
SELECT * FROM dbo.TestConversion WHERE Value = '1' --Same thing, this doesn't work either. 

我希望這兩種方案的工作,因爲視圖已經過濾掉壞的數據。更奇怪的是,第二個查詢也不起作用。我只能在它們兩個上獲取估計的執行計劃(因爲我實際上無法無誤地運行查詢),並且它們是相同的。根據估計的計劃,在應用WHERE Value = 1之前,將首先過濾不良數據。

編輯:爲了測試查詢計劃,我將CONVERT改爲TRY_CONVERT。這些計劃的結果仍然是相同的,它看起來像在轉換之前發生的過濾器:

enter image description here

回答

1

我希望這兩種方案的工作,因爲視圖已經過濾掉不良數據

您使用的是視圖,視圖只是存儲定義..At運行的時候,你的查詢將擴展和這個相比肯定會失敗

SELECT CONVERT(BIGINT,Value) Value 

你也可以認爲,這where子句應該過濾掉壞的數據,但是這可能會或可能不會happen..this已經由保羅·白了說明: TSQL divide by zero encountered despite no columns containing 0

SQL是說明性語言;您編寫了一個邏輯描述所需結果的查詢,但是由優化器來制定物理計劃。這個物理計劃可能與查詢的書面形式沒有多大關係,因爲優化器不會簡單地對從查詢的文本形式派生的「步驟」進行重新排序,它可以應用300多種不同的轉換來找到有效的執行策略。

還有一個connect item raised,但也有不同意見,你在評論中看到的連接項目

也看到例如從連接項目是與你相似的下方,它也依賴於過濾掉壞數據

create table albert(a int NOT NULL, 
         b varchar(23) NOT NULL) 
    create table stina (a int NOT NULL) 
    go 
    insert albert (a, b) 
     values (1, '99'), 
       (2, 'Gurka'), 
       (3, '89') 
    insert stina (a) values(1), (3), (9), (12) 
    go 
    SELECT a.a, a.b + 100 
    FROM albert a 
    JOIN stina s ON s.a = a.a 

上述查詢失敗,下面誤差

此查詢失敗,「C onversion轉換爲varchar值「Gurka」到的數據類型爲int時失敗「,儘管此行絕不會出現在輸出

來到你的編輯和下方點

編輯:爲了測試查詢計劃,我將CONVERT改爲TRY_CONVERT。計劃的結果仍然相同,並且看起來像在轉換前發生過濾:

您提供的計劃是估計的計劃,而不是實際的計劃。看他們如何可以是不同的這樣的回答:Differences between estimated and actual execution plans

還檢查了這個答案由馬丁·史密斯更多的例子

https://stackoverflow.com/a/7192951/2975396

+0

見實際查詢計劃使用TRY_CONVERT編輯成我的問題。在轉換髮生之前,應先將無效記錄過濾掉。 – Lunyx

+0

現在看我的編輯,這個過濾可能會發生也可能不會發生 – TheGameiswar

+0

實際上,我的查詢計劃是實際的執行計劃,因爲您可以在過濾器上看到估計的vs實際行。不過,我只是再次檢查了這一點,我懷疑這可能是我使用的第三方分析器工具的問題,因爲SSMS中的計劃實際上顯示轉換髮生在謂詞的前半部分,而不是將謂詞顯示爲只檢查'<>'foo''。 – Lunyx