2012-04-18 121 views
2

這是在SQL Server 2008 R2中。將varchar值「N」轉換爲數據類型時轉換失敗int

我正在用這個拉我的頭髮。請密切關注。

當我跑,我得到27行返回:

select * 
from dbo.[12STD_NO_VISIT] 
where (
     (dbo.fPhoneExists(PhoneNumber1) = 1 
     AND (NextCall1 BETWEEN GETDATE() AND DATEADD(hh, 1, GETDATE()))) 
    ) 

當我跑,我得到21行返回(注意改變PhoneNumber2和NextCall2):

select * 
from dbo.[12STD_NO_VISIT] 
where (
      (dbo.fPhoneExists(PhoneNumber2) = 1 
      AND (NextCall2 BETWEEN GETDATE() AND DATEADD(hh, 1, GETDATE()))) 
    ) 

但是,當我運行此, '或門' 的2個條件,我得到一個錯誤:

Conversion failed when converting the varchar value 'N' to data type int

select * 
from dbo.[12STD_NO_VISIT] 
where (
      (dbo.fPhoneExists(PhoneNumber1) = 1 
      AND (NextCall1 BETWEEN GETDATE() AND DATEADD(hh, 1, GETDATE()))) 
     OR 
      (dbo.fPhoneExists(PhoneNumber2) = 1 
      AND (NextCall2 BETWEEN GETDATE() AND DATEADD(hh, 1, GETDATE()))) 
    ) 

但它不只是給我的錯誤。它首先檢索42行,顯示分秒(結果標籤),然後顯示錯誤(消息標籤)。

我無法弄清楚這一點。任何幫助非常感謝。

謝謝!

FUNCTION [dbo].[fPhoneExists](@PhoneNumber varchar) 
RETURNS BIT 
WITH EXECUTE AS CALLER 
AS 
BEGIN 
DECLARE @GoodNumber bit 
IF (@PhoneNumber is NULL or @PhoneNumber = 0 or @PhoneNumber = '') 
    SET @GoodNumber = 0; 
ELSE 
    SET @GoodNumber = 1; 
    Return(@GoodNumber); 
END 
+0

如果你嘗試'UNION'這兩個查詢會發生什麼? – Lamak 2012-04-18 18:03:11

+0

'fPhoneExists'函數看起來像什麼? – Magnus 2012-04-18 18:03:55

+1

哈。我現在明白了。 42.確實回答一切。 – 2012-04-18 18:15:08

回答

4

什麼是PhoneNumber1PhoneNumber2數據類型? dbo.fPhoneExists的定義是什麼?我懷疑問題出在哪裏 - 或者正如Lynn所建議的那樣,查詢可能比您向我們展示的要多(查詢要麼整體成功,要麼失敗,不會產生42行,然後出現錯誤)。

現在我們所看到的功能,這裏是一個重新寫:

ALTER FUNCTION [dbo].[fPhoneExists] 
(
    @PhoneNumber VARCHAR -- varchar(what)? This should match definition of column 
) 
RETURNS BIT 
WITH EXECUTE AS CALLER 
AS 
BEGIN 
    RETURN (SELECT CASE WHEN COALESCE(@PhoneNumber, '') IN ('0', '') THEN 0 ELSE 1 END); 
END 
GO 

沒有理由存儲在一個變量臨時邏輯,也注意到你正在返回變量在ELSE條件。

+0

嗨亞倫,這裏是函數的代碼:'FUNCTION [dbo]。[fPhoneExists](******中國VARCHAR) RETURNS BIT WITH EXECUTE AS CALLER AS BEGIN \t DECLARE GoodNumber位 \t IF(******中國是NULL或******中國= 0或******中國= '') \t \t SET GoodNumber = 0; \t ELSE \t \t SET GoodNumber = 1; Return(GoodNumber); END;在變量出現'@'之前,只有它不讓我在這裏發佈。爲了便於閱讀,我也不知道如何格式化此帖。抱歉。 – Amarundo 2012-04-18 18:20:41

+0

請將該函數添加到問題中,並將其格式化爲代碼示例。作爲純文本評論很難閱讀(所有@符號也被刪除)。如果您編輯問題,您可以突出顯示該代碼並點擊「{}」按鈕。 – 2012-04-18 18:22:16

+0

另外,在您的簡化代碼中,我看不到NEXTCALL2。非常感謝你的幫助。 – Amarundo 2012-04-18 18:22:40

3

您的dbo.fPhoneExists函數在PhoneNumber = 0表達式中包含隱式轉換,根據Data Type Peecendence的規則將VARCHAR值轉換爲int。如果字符串中的值不是數字,則此投射將失敗。您也陷入了假設布爾運算符短路在SQL中得到保證的謬論,這根本不正確。 SQL是一種聲明性語言,並且是order of evaluation of boolean operators is not guaranteed

1

你會得到更好的性能,通過與CASE替換函數替換fnPhoneExists

select * 
from dbo.[12STD_NO_VISIT] 
where (
      (case when ISNULL(PhoneNumber1,'') not in ('0','') then 1 else 0 end=1 
      AND (NextCall1 BETWEEN GETDATE() AND DATEADD(hh, 1, GETDATE()))) 
     OR 
      (case when ISNULL(PhoneNumber2,'') not in ('0','') then 1 else 0 end=1 
      AND (NextCall2 BETWEEN GETDATE() AND DATEADD(hh, 1, GETDATE()))) 
    ) 

這是因爲優化器將不能優化fnPhoneExists的內容。

相關問題