12

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

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

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

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

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

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

4 に答える 4

10

それが 1 を返す理由は、正確に 1 つの値 (何らかの任意の値) を割り当てたためです。EXISTS@Siveが示唆するように、とにかく手動カウントを行う代わりに使用する必要があります。その理由は、 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

varnameが一意でない場合、単一の値で何をしようとしているのかわかりません。どっちが引いた?次のシナリオを想像してください。

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;

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

さらに、このテーブルからデータを挿入することを意図している場合は、事前チェックや行数などを単純に破棄して、次のように言ってください。

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

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

于 2012-04-30T14:06:30.840 に答える
6

変数をに設定できます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て値を割り当てることができます。selectset

SELECT @var = var FROM dbo.varDB WHERE varName = @varName
IF (@@ROWCOUNT > 0)
BEGIN
//carry out insert
END
于 2012-04-30T14:17:01.313 に答える
5

を使用して、このようなことを行うことができますEXISTSこれにより、 BEGINEND@varNameで囲まれたステートメントを実行する前に、指定された値に対して少なくとも1つのレコードが存在するかどうかがチェックされます。

スクリプト

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

MSDNドキュメントEXISTS(Transact-SQL)

コメントに基づいて、#1を更新します。

価値を知るための要件が​​わかりません。カウントを取得する場合は、COUNTを使用することをお勧めします。

DECLARE @recordsCount
SELECT @recordsCount = COUNT(var) FROM dbo.varDB WHERE varName = @varName

IF recordsCount > 0 
BEGIN
  // your statements
END

コメントに基づいて、更新#2:

結果セット自体をBEGINおよびEND内で使用する場合は、ステートメント内で結果セットがどのように使用されるかについての詳細が質問に必要です。さらなる入力に基づいて、IFステートメントさえ必要ないかもしれません。問題の明確な解決策を提供するために必要な詳細。

于 2012-04-30T14:01:25.943 に答える
4

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

SELECT @var = var FROM dbo.varDB WHERE varName = @varName
IF (@@ROWCOUNT > 0)
BEGIN
   //carry out insert
END
于 2012-04-30T14:05:32.943 に答える