2

これはSQLServer2008R2にあります。

これで髪を引っ張っています。よく従ってください。

これを実行すると、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つの条件を「OR」すると、エラーが発生します。

varchar値'N'をデータ型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
4

3 に答える 3

4

PhoneNumber1とのデータ型は何PhoneNumber2ですか?の定義は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条件でのみ変数を返すことに注意してください。

于 2012-04-18T18:05:22.330 に答える
3

dbo.fPhoneExists関数には、データ型PeecendencePhoneNumber = 0規則に従って、 VARCHAR値をintにキャストする式に暗黙のキャストが含まれています。文字列の値が数値でない場合、このキャストは失敗します。また、SQLでブール演算子の短絡が保証されていると仮定するという誤謬に陥っていますが、これは単に真実ではありません。SQLは宣言型言語であり、ブール演算子の評価の順序は保証されていませんPhoneNumber

于 2012-04-18T18:37:56.747 に答える
1

fnPhoneExists関数をCASE:に置き換えると、パフォーマンスが向上します。

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のコンテンツを最適化しないためです。

于 2012-04-18T19:13:14.453 に答える