77

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

これが私の手順です:

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

  1. 請求書テーブルから請求書 ID のリストを取得し、Cursor に格納します
  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 を保存し、次の update ステートメントの set 句で再度使用するにはどうすればよいですか? カーソル変数または int 型の別のローカル変数を作成する必要がありますか?

4

5 に答える 5

109

私はちょうど同じ問題を抱えていました...

declare @userId uniqueidentifier
set @userId = (select top 1 UserId from aspnet_Users)

またはさらに短い:

declare @userId uniqueidentifier
SELECT TOP 1 @userId = UserId FROM aspnet_Users
于 2011-01-27T13:50:19.653 に答える
50
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

編集:
この質問は、私が予想していたよりもはるかに多くの牽引力を得ています。回答でカーソルを使用することを推奨しているのではなく、質問に基づいて値を割り当てる方法を示していることに注意してください。

于 2009-04-30T16:16:48.930 に答える
20

これを試して

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変数として宣言します。

また、これは、カーソルを処理するときだけでなく、変数への任意のタイプの選択に対して行う方法であることに注意する必要があります。

于 2009-04-30T16:13:39.407 に答える
15

変数を安全に割り当てるには、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 番目のバージョンを使用しているときに、select が結果をまったく返さない場合はどうなりますか?

あなたが信じているかもしれないこととは反対に、変数の値はnullではありません-それは以前の値を保持します!

これは、前述のように、SQL が投稿ごとに 1 回変数に値を割り当てるためです。つまり、結果に投稿が含まれていない場合、変数に対して何も実行されません。したがって、変数にはステートメントを実行する前の値が保持されます。

SET-SELECT ステートメントでは、値は になりますnull

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

于 2013-10-29T15:16:56.187 に答える