2012-04-18 16 views
2

これはSQL Server 2008 R2にあります。varchar値 'N'をデータ型intに変換するときに変換に失敗しました

私はこの1つで私の髪を引っ張っています。密接に従ってください。

私はこれを実行すると、私は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

両方のクエリを「結合」しようとするとどうなりますか? – Lamak

+0

'fPhoneExists'関数はどのように見えますか? – Magnus

+1

ハ。わかった。 42.本当にすべてに答えます。 –

答えて

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

こんにちはAaron、関数のコードは次のとおりです: 'FUNCTION [dbo]。 \t \t SET GoodNumber = 0(のPhoneNumberがのPhoneNumber = 0またはのPhoneNumber = '' NULLであるか)IF 戻るBIT WITH EXECUTE CALLER AS AS \t DECLARE GoodNumberをBEGIN [fPhoneExists](のPhoneNumber VARCHAR)が \tビット。 \t ELSE \t \t SET GoodNumber = 1; リターン(GoodNumber); END;変数が '@'になる前に、私はここにそれを投稿させませんでした。私はまた、読みやすいようにこの記事の書式を設定する方法を知らない。ごめんなさい。 – Amarundo

+0

質問に関数を追加し、コードサンプルとして書式を設定してください。プレーンテキストのコメントとして読むことは非常に難しい(また、@記号はすべて取り除かれる)。質問を編集する場合は、コードを強調表示して '{} 'ボタンを押すことができます。 –

+0

また、単純化したコードではNEXTCALL2が表示されません。あなたの助けに感謝します。 – Amarundo

3

あなたdbo.fPhoneExists機能は、Data Type Peecendenceのルールに従ってintにPhoneNumber VARCHAR値をキャストPhoneNumber = 0式の暗黙のキャストが含まれています。文字列の値が数値でない場合、このキャストは失敗します。論理演算子の短絡が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の内容を最適化しないので、これがあります。

関連する問題