Caseステートメントでクエリを終了しますか?


8

2つの異なるテーブルの2つの日付を比較し、それらが等しい場合、クエリが終了するようにクエリを設定しようとしています。それらが等しくない場合、クエリは続行し、いくつかのものを挿入します。しかし、どうすれば自分のやりたいことができるのかわかりません。

SELECT TOP(1) @dateA=a.someDate
FROM a
ORDER BY DESC;
SELECT TOP(1) @dateB=b.someDate
FROM b
ORDER BY DESC;

CASE WHEN @dateA=@dateB THEN raiseerror('dates equal',20,-1) with log;

Insert statements;

任意の助けをいただければ幸いです。


SQLの他のいくつかのバリアントには、式と名前付きステートメントの両方がありCASEます-SQL ServerにはCASE式しかありません。
RDFozz 2018

3
あなたが実際に行う必要エラーを発生させるには?それとも、それは単に終了しようとしているのでしょうか?
ケビン

回答:


16

CASE 式(ステートメントではない)であり、そのようなフローの制御には使用できません。コマンドを呼び出したり、複数の列/値を返したり、単独でコマンドとして使用したりすることはできません。

IF日付が等しいときにエラーを発生させるために使用できるように思えますが、それ以外の場合は挿入を実行します。

IF @dateA = @dateB 
BEGIN
  raiseerror('dates equal',20,-1) with log;
END
ELSE -- maybe you don't need a batch-aborting, logging error level
BEGIN
  INSERT ...
END

他の方法で行うこともできます。日付が等しくない場合のみ挿入を実行し、そうでない場合はエラーを発生させます。

IF @dateA <> @dateB
BEGIN
  INSERT ...
END
ELSE
BEGIN
  raiserror ...
END

あなたがエラーを使用することを考えている場合のみ、挿入を実行しているから抜け出すの目的のために、そしてあなただけからすべてを削除することができELSEたときに挿入を実行する唯一の方法であるため、ダウン@dateAして@dateBいると等しくありません

IF @dateA <> @dateB
BEGIN
  INSERT ...
END

行(「レコード」と比較)や列(「フィールド」と比較)のようなものについて知識を深めるようにスケールを戻しましたが、式全体とステートメントの違いは、まさにこの理由から非常に重要です。「CASE式のダーティーシークレット」を参照してください。


1つのnitpickを除いて、ほとんどの場合良い答えです。 '<>'演算子を使用しても、NULL値ではうまく機能しません。日付値の1つがNULLの場合、「等しくない」演算子は予期しない結果を返します。これを試してください "SELECT CASE WHEN(1 <> NULL)THEN '!=' ELSE '==' END"
user5151179

1
@ user5151179アーロンは違いを知っていると思います。また、質問のOPが、2つの日付が等しい場合に何をしたいか、等しくない場合に何をしたいかを確認します。彼は、どちらか一方または両方がそうであるときに彼らが何をしたいのかについてはまったく言及していませんNULL。その場合、Aaronが提供する2つのバージョンが異なる動作をすることは、依然として良い観察です。
ypercubeᵀᴹ

6

IF代わりにCASE

 IF @dateA=@dateB 
    raiseerror('dates equal',20,-1) with log;
 ELSE
    BEGIN
        Insert statements;
    END

もちろん、これは実際にエラーを発生させたいことを前提としています。他のオプションは次のとおりです。

 IF @dateA<>@dateB 
    BEGIN
        Insert statements;
    END

さて、注意してくださいBEGINEND。それらは重要になるでしょう。IF声明(とELSE)だけで以下のコマンドの権利に影響を与えます。複数のコマンドが必要な場合は、BEGINとENDが必要です。


2

他の回答は、CASEはステートメントではなくであり、それ自体はステートメントRAISEERRORまたはその他)を包含することはできないと指摘しています。条件が多くない場合、特に条件が1つだけの場合、IFステートメントは、前述したように、実行しようとしていることに最適な選択です。

それでも、シナリオによっては、CASE式を引き続き使用できますが、これまで示したとおりではありません。特に、一致する結果として同じアクションのセットが必要となるチェック対象の条件が多数ある場合(例:例外を発生させ、スクリプトを終了する)、CASEの結果を格納する割り当てステートメントでCASE式を使用し、次のようにします。格納された結果をIFでチェックし、必要に応じて次のように必要なアクションを実行します。

DECLARE @ErrorMessage varchar(1000);

SET @ErrorMessage =
  CASE WHEN @dateA = @dateB THEN
    'Dates equal'
  CASE WHEN ... /* some other condition */ THEN
    'Some other message'
  .
  .
  .
  ELSE
    ''  -- no message if nothing is wrong;
        -- you can also omit the ELSE branch entirely,
        -- which means the same as ELSE NULL
  END
;

IF @ErrorMessage <> ''
BEGIN
  RAISERROR (@ErrorMessage, 20, -1) WITH LOG;
END;

... /* continue the script */

この場合、必要なアクションは例外の発生ですが、例外とともに返されるメッセージは、最初にチェックされた条件に依存する必要があります。割り当てステートメントは、CASE式を使用して、@ErrorMessage変数に格納するメッセージを選択します。

また、エラーが発生するのは条件付きであることがわかります(変数に実際に表示するメッセージが含まれている場合のみ)。値が空の文字列またはnullの場合、スクリプトは中断されることなく続行されます。


0

変数が必要ですか?

declare @D1 table (dt date);
declare @D2 table (dt date);
insert into @D1 values ('2000-01-01'), ('2000-02-01');
insert into @D2 values ('2000-01-01'), ('2000-02-01');
if (select max(dt) from @D1) = (select max(dt) from @D2)
begin 
   select 'match'
end
else 
begin 
   select 'no match'
end
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.