web-dev-qa-db-ja.com

IFステートメントおよびBEGIN..ENDブロック内で@@ ROWCOUNTを使用する方法

私のコードは次のとおりです:

SET @var = (SELECT var FROM dbo.varDB WHERE varName = @varName)

IF (@@ROWCOUNT > 0)
    BEGIN
        //carry out insert
    END

これは常に割り当てを最後に実行するため、常に1 for @@ ROWCOUNTを返すと言っていいでしょうか?

もしそうなら、私ができるようにする最もエレガントな解決策は何ですか?

  • クエリの結果を格納した変数を作成する
  • クエリが結果を返すかどうかをテストする
10
Simon Kiely

1を返すのは、1つの値(任意の値)を1つだけ割り当てたためです。とにかく、@ Siveが示唆するように、手動でカウントする代わりにEXISTSを使用する必要があります。その理由は、EXISTSのパフォーマンスはCOUNTを下回ることはなく、説明しているユースケースでは、実際のカウントが何であるかは問題ではないからです。カウントがゼロかゼロより大きいかを知りたいとします。

あなたが行った方法で変数にその値を割り当てることの問題は、一致する複数の行がある場合にどうなりますか?試してみよう:

DECLARE @foo TABLE([var] INT, varname SYSNAME);
INSERT @foo VALUES (1,N'bob'),(2,N'bob');
DECLARE @var INT;
SET @var = (SELECT [var] FROM @foo WHERE varname = N'bob

結果:

メッセージ512、レベル16、状態1、行4
サブクエリが複数の値を返しました。これは、サブクエリが=、!=、<、<=、>、> =の後に続く場合、またはサブクエリが式として使用される場合は許可されません。

今、varnameが一意である場合、私はこれを行います:

SELECT @var = [var] FROM dbo.varDB WHERE varName = @varName;
IF @var IS NOT NULL
BEGIN
    // carry out insert
END
ELSE
BEGIN
    PRINT 'Already existed! ' + RTRIM(@var);
END

varnamenot一意である場合、単一の値で何を行うのかわかりません。どれを引っ張りましたか?このシナリオを想像してください:

DECLARE @foo TABLE([var] INT, varname SYSNAME);
INSERT @foo VALUES (3,N'bob'),(2,N'adam'),(1,N'bob');
DECLARE @var INT;
SELECT @var = [var] FROM @foo WHERE varname = N'bob';
PRINT @var;

ウィル@varは1または3ですか?知るか?潜在的に多くの値の1つだけをキャプチャしている場合、なぜそれが問題になるのですか?あなたはその行で何かをするつもりですか?

さらに、このテーブルからデータを挿入するつもりなら、単純に事前チェック、行数などを捨てて、次のように言ってみてください。

INSERT dbo.SomeTable(column1 --,...other columns
  SELECT var --,...other columns
  FROM dbo.varDB
  WHERE varName = @varName;

行が存在しない場合、挿入は行われません。

9
Aaron Bertrand

変数をNULLに設定できます(念のため)。

クエリが行を返さない場合でも、@ varはNULLのままです。
1行を返す場合、@varには値があります
複数の行を返す場合は、例外があります。

SET @var = NULL

SET @var = (SELECT var FROM dbo.varDB WHERE varName = @varName)
IF @var IS NOT NULL
BEGIN
//carry out insert
END

更新

本当に使いたいなら@@ROWCOUNT代わりに、selectの代わりにsetを使用して値を割り当てることができます。

SELECT @var = var FROM dbo.varDB WHERE varName = @varName
IF (@@ROWCOUNT > 0)
BEGIN
//carry out insert
END
5
Mikael Eriksson

返された行の数を選択してテストできます。

SELECT @var = var FROM dbo.varDB WHERE varName = @varName
IF (@@ROWCOUNT > 0)
BEGIN
   //carry out insert
END