在嘗試回答Stack Overflow上的另一個SQL Server問題時,遇到了一些無法正常工作的情況。我正在使用SQL Server 2008R2,但這可能並不重要。在查詢派生表時在SQL Server中拋出異常
我有一個簡單的假設表,有一些日期存儲爲VARCHAR數據類型。我知道使用DATE數據類型存儲日期信息是明顯而實際的,但本示例故意使用VARCHAR來演示我遇到的問題。該日期是無效的原因並不重要 - 它可能是壞的消毒,畸形更新查詢,用你的想象力,等
-- setup
CREATE TABLE #temp (DateString VARCHAR(10));
INSERT #temp (DateString) VALUES ('01/01/2013');
INSERT #temp (DateString) VALUES ('02/14/2013');
INSERT #temp (DateString) VALUES ('03/31/2013');
INSERT #temp (DateString) VALUES ('05/27/2013');
INSERT #temp (DateString) VALUES ('06/31/201'); -- known invalid date, maybe the data wasn't sanitized, etc.
INSERT #temp (DateString) VALUES ('07/04/2013');
我想選擇假期的7月1日之前的數量,2013年我懷疑日期可能無效,所以我必須爲此規劃以避免例外。之前,我甚至寫這些下面的查詢,我知道他們會失敗:
-- fails: cast exception, obviously
SELECT COUNT(*) AS [CountHolidays]
FROM #temp
WHERE CAST(DateString AS DATE)<'20130701';
-- fails: ISDATE() is not gauranteed to be evaluated first, less obvious, pointed out by another user.
SELECT COUNT(*) AS [CountHolidays]
FROM #temp
WHERE ISDATE(DateString) = 1 AND CAST(DateString AS DATE)<'20130701';
該查詢按預期工作和將是我最後的選擇:
-- works
SELECT COUNT(*) AS [CountHolidays]
FROM #temp
WHERE CONVERT(DATE,CASE WHEN ISDATE(DateString)=1 THEN datestring ELSE NULL END) < '20130701';
之前,我寫我的最後的查詢,雖然,我試過這是第一次,我期望它能夠工作,但它也引發了一個拋出的例外。爲什麼此查詢具體失敗?
-- Why does this query fail specifically?
-- I expected my derived inner query to filter invalid dates out first, but it does not. I get the same cast exception.
SELECT COUNT(*) AS [CountHolidays]
FROM (
-- the derived table returns expected data when executed independently.
SELECT DateString
FROM #temp
WHERE ISDATE(DateString) = 1
) AS T
WHERE CAST(DateString AS DATE)<'20130701';
這可能是MS SQL Server查詢優化器中的錯誤。如果您查看執行計劃,您會看到首先轉換所有字符串:CONVERT(date,[tempdb]。[dbo]。[#temp]。[DateString],0)<'2013-07-01' – alex
請參閱http://connect.microsoft.com/SQLServer/feedback/details/537419/sql-server-should-not-raise-illogical-errors –