質問
選択したフィールド値をクエリから変数に保存し、更新ステートメントで使用するにはどうすればよいですか
ここに私の手順があります:
次のことを行うSQL Server 2005 T-SQLストアドプロシージャを書いています。
- 請求書IDのリストを請求書テーブルから取得し、カーソルに保存します
- カーソルから請求書IDを取得-> tmp_key変数
- foreach tmp_keyは、顧客テーブルから請求書クライアントのプライマリ連絡先IDを見つけます
- クライアントの連絡先キーをプライマリ連絡先IDで更新します
- カーソルを閉じる
ここに私のコードがあります:
DECLARE @tmp_key int
DECLARE @get_invckey cursor
set @get_invckey = CURSOR FOR
select invckey from tarinvoice where confirmtocntctkey is null and tranno like '%115876'
OPEN @get_invckey
FETCH NEXT FROM @get_invckey into @tmp_key
WHILE (@@FETCH_STATUS = 0)
BEGIN
SELECT c.PrimaryCntctKey as PrimaryContactKey
from tarcustomer c, tarinvoice i
where i.custkey = c.custkey and i.invckey = @tmp_key
UPDATE tarinvoice set confirmtocntctkey = PrimaryContactKey where invckey = @tmp_key
FETCH NEXT FROM @get_invckey INTO @tmp_key
END
CLOSE @get_invckey
DEALLOCATE @get_invckey
PrimaryContactKeyを保存し、次の更新ステートメントのset句で再度使用するにはどうすればよいですか?カーソル変数を作成しますか、それともint型の別のローカル変数を作成しますか?
解決
DECLARE @tmp_key int
DECLARE @get_invckey cursor
SET @get_invckey = CURSOR FOR
SELECT invckey FROM tarinvoice WHERE confirmtocntctkey IS NULL AND tranno LIKE '%115876'
OPEN @get_invckey
FETCH NEXT FROM @get_invckey INTO @tmp_key
DECLARE @PrimaryContactKey int --or whatever datatype it is
WHILE (@@FETCH_STATUS = 0)
BEGIN
SELECT @PrimaryContactKey=c.PrimaryCntctKey
FROM tarcustomer c, tarinvoice i
WHERE i.custkey = c.custkey AND i.invckey = @tmp_key
UPDATE tarinvoice SET confirmtocntctkey = @PrimaryContactKey WHERE invckey = @tmp_key
FETCH NEXT FROM @get_invckey INTO @tmp_key
END
CLOSE @get_invckey
DEALLOCATE @get_invckey
編集:
この質問は、私が予想していたよりもはるかに多くの関心を集めています。私は答えでカーソルを使用することを推奨しているのではなく、質問に基づいて値を割り当てる方法を示していることに注意してください。
他のヒント
同じ問題が発生しました...
declare @userId uniqueidentifier
set @userId = (select top 1 UserId from aspnet_Users)
またはさらに短い:
declare @userId uniqueidentifier
SELECT TOP 1 @userId = UserId FROM aspnet_Users
これを試して
SELECT @PrimaryContactKey = c.PrimaryCntctKey
FROM tarcustomer c, tarinvoice i
WHERE i.custkey = c.custkey
AND i.invckey = @tmp_key
UPDATE tarinvoice SET confirmtocntctkey = @PrimaryContactKey
WHERE invckey = @tmp_key
FETCH NEXT FROM @get_invckey INTO @tmp_key
この変数は、ループの外側で標準のTSQL変数として宣言します。
これは、カーソルを扱うときだけでなく、変数への任意のタイプの選択に対してこれを行う方法でもあることに注意してください。
なぜカーソルが必要なのですか? コードのセグメント全体をこれに置き換えることができます。これにより、多数の行で非常に高速に実行されます。
UPDATE tarinvoice set confirmtocntctkey = PrimaryCntctKey
FROM tarinvoice INNER JOIN tarcustomer ON tarinvoice.custkey = tarcustomer.custkey
WHERE confirmtocntctkey is null and tranno like '%115876'
変数を安全に割り当てるには、SET-SELECTステートメントを使用する必要があります。
SET @PrimaryContactKey = (SELECT c.PrimaryCntctKey
FROM tarcustomer c, tarinvoice i
WHERE i.custkey = c.custkey
AND i.invckey = @tmp_key)
開始括弧と終了括弧の両方があることを確認してください!
SET-SELECTバージョンが変数を設定する最も安全な方法である理由は2つあります。
1。 SELECTはいくつかの投稿を返します
次の選択の結果、複数の投稿があった場合はどうなりますか?
SELECT @PrimaryContactKey = c.PrimaryCntctKey
FROM tarcustomer c, tarinvoice i
WHERE i.custkey = c.custkey
AND i.invckey = @tmp_key
@PrimaryContactKey
には、結果の最後の投稿からの値が割り当てられます。
実際、 @PrimaryContactKey
には結果の投稿ごとに1つの値が割り当てられるため、結果としてSELECTコマンドが処理していた最後の投稿の値が含まれます。
「最後」の投稿はどれですかクラスター化インデックスによって決定されます。クラスター化インデックスが使用されていない場合、または主キーがクラスター化されている場合は、「最後の」投稿は最後に追加された投稿になります。この動作は、最悪の場合、テーブルのインデックスが変更されるたびに変更される可能性があります。
SET-SELECTステートメントを使用すると、変数は null
に設定されます。
2。 SELECTは投稿を返しません
選択した結果がまったく返されない場合、2番目のバージョンのコードを使用するとどうなりますか?
変数の値がnullにならないと思われる場合とは逆に、以前の値を保持します
これは、上記のように、SQLが変数に値を割り当てるためです。投稿ごとに1回-結果に投稿が含まれていない場合、変数で何もしません。そのため、変数は、ステートメントを実行する前の値のままです。
SET-SELECTステートメントを使用すると、値は null
になります。