3

次の SQL クエリを想像してください。

UPDATE MYTABLE
SET COL2 = (SELECT COL2 + 1 FROM (SELECT MAX(COL2) FROM MYTABLE) AS X)
WHERE ID IN (1,2,3,4,5)

アップデート実行前のMAX(COL2)が1であるとします。

私の意図は、ID=1 COL2 が 'max(COL2) + 1' (つまり 2) に更新される更新では、その後の更新では 'MAX(COL2) + 1' が再評価されるため、ID が=2、COL2=3、ID=3、COL2=4 など...

実際には、すべての行 (ID=1、2、3、4、5) で COL2 の値が 2 になります。

更新ごとに MAX(COL2) +1 の値を「再評価」するスマートな方法はありますか? これを行うとパフォーマンスの問題が発生する可能性があることは認識していますが、それでも興味があります! より良い代替手段 (複数の更新ステートメントを含まない) はありますか?

ところで:上記のクエリ(ネストされた内部テーブル)に使用される構文について疑問がある場合は、ここを参照してください:SQL:ネストされたFROM句のUPDATEステートメントでターゲットテーブルを使用する

4

5 に答える 5

11
UPDATE mytable, (
  SELECT @loop := MAX(col1)
  FROM
    mytable
  ) o
SET col1 = (@loop := @loop + 1)

ここで遭遇したものは と呼ばれquery stabilityます。

クエリ自体、または次のクエリによって行われた変更を確認することはできません。

UPDATE mytable
SET col1 = col2 + 1
WHERE col1 > col2 

決して終わらないでしょう。

于 2009-02-17T12:14:52.840 に答える
2

これが私が行う方法です:

SELECT MAX(col2) FROM mytable INTO @max;

UPDATE mytable
SET col2 = @max:=@max+1
WHERE id IN (1,2,3,4,5)
ORDER BY id;

これを MySQL 5.1.30 でテストしたところ、動作しました。

変数を最初に設定したのは、@max@Quassnoi がデカルト積でそれを行うトリックが不要で読みにくいことがわかったからです。

MySQL はステートメントでサポートORDER BYされていることに注意してUPDATEください (これは標準 SQL ではありません)。値が必要な順序で更新されるようにするには、これを行う必要があります。それ以外の場合、MySQL は特定の順序を保証しません。

于 2009-02-17T14:34:23.053 に答える
0
declare @loop int
select @loop = 1

UPDATE MYTABLE
SET COL1 = @loop,
    @loop = @loop+1
WHERE ID IN (1,2,3,4,5)
于 2009-02-17T12:07:31.190 に答える
0

各挿入で MAX(COL1) +1 の値を「再評価」するスマートな方法はありますか?

行を1つずつ更新しない限り:(

これはMSSQLで機能しますが、MySQLについては知りませんが、アイデアが得られるかもしれません:

DECLARE @Counter int

SELECT @Counter = MAX(COL2) FROM MYTABLE

UPDATE MYTABLE
SET @Counter = @Counter + 1,
    COL1 = @Counter
WHERE ID IN (1,2,3,4,5)

編集: SET ステートメントは MSSQL で次のように簡略化できると思います。

SET @Counter = COL1 = @Counter + 1
于 2009-02-17T12:10:07.533 に答える
-1

挿入ごとに再評価する必要があります。おそらくCOL2の最大値は変化していません。MAX(COL 1 )を選択しないでよろしいですか? あなたの質問をもう一度読んで、挿入と更新という用語を混同し(現在は修正されています)、ループに陥りました。


一度に多くのレコードを更新しようとしていますが、それぞれを個別に更新しているかのように動作させます。これは意図したとおりには機能しません。

各レコード WHERE ID IN (1,2,3,4,5) をループして個別に更新するストアド プロシージャを作成できます。または、5 行しか実行していないので、ステートメントを 5 回コピーして貼り付け、WHERE 句をWHERE ID = 1(および後続の行で 2、3、4、5) に変更してみませんか。

于 2009-02-17T12:05:08.933 に答える