私のコードは次のとおりです:
SET @var = (SELECT var FROM dbo.varDB WHERE varName = @varName)
IF (@@ROWCOUNT > 0)
BEGIN
//carry out insert
END
これは常に割り当てを最後に実行するため、常に1 for @@ ROWCOUNTを返すと言っていいでしょうか?
もしそうなら、私ができるようにする最もエレガントな解決策は何ですか?
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
varname
がnot一意である場合、単一の値で何を行うのかわかりません。どれを引っ張りましたか?このシナリオを想像してください:
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;
行が存在しない場合、挿入は行われません。
変数を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
返された行の数を選択してテストできます。
SELECT @var = var FROM dbo.varDB WHERE varName = @varName
IF (@@ROWCOUNT > 0)
BEGIN
//carry out insert
END