質問

選択したフィールド値をクエリから変数に保存し、更新ステートメントで使用するにはどうすればよいですか

ここに私の手順があります:

次のことを行うSQL Server 2005 T-SQLストアドプロシージャを書いています。

  1. 請求書IDのリストを請求書テーブルから取得し、カーソルに保存します
  2. カーソルから請求書IDを取得-> tmp_key変数
  3. foreach tmp_keyは、顧客テーブルから請求書クライアントのプライマリ連絡先IDを見つけます
  4. クライアントの連絡先キーをプライマリ連絡先IDで更新します
  5. カーソルを閉じる

ここに私のコードがあります:

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 になります。

参照:変数を割り当てる際のSETとSELECT

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top