web-dev-qa-db-ja.com

ORDER BYを使用した更新

UPDATEORDER BYと「関連付ける」必要があります。カーソルを使用しようとしていますが、エラーが発生します。

cursor "cursupd" doesn't specify a line,
SQL state: 24000

コード:

BEGIN;
    DECLARE cursUpd CURSOR FOR SELECT * FROM "table" WHERE "field" = 5760 AND "sequence" >= 0 AND "sequence" < 9 ORDER BY "sequence" DESC;
    UPDATE "table" SET "sequence" = "sequence" + 2 WHERE CURRENT OF cursUpd;
    CLOSE cursUpd;
COMMIT;

それを正しく行う方法は?

アップデート1

カーソルなしで、私がこのようにすると:

UPDATE "CableLinePoint" AS "t"
SET "sequence" = t."sequence" + 2
from (
    select max("sequence") "sequence", "id"
    from "CableLinePoint"
    where
        "CableLine" = 5760
    group by "id"
    ORDER BY "sequence" DESC
) "s"
where "t"."id" = "s"."id" and "t"."sequence" = "s"."sequence"

固有のエラーが発生します。したがって、最初からではなく、最後から更新する必要があります。

アップデート2

テーブル:

id|CableLine|sequence
10|    2    |    1
11|    2    |    2
12|    2    |    3
13|    2    |    4
14|    2    |    5

フィールド「シーケンス」を更新(増加)する必要があります。 「シーケンス」には「インデックス」タイプがあるため、実行できません。

UPDATE "table" SET "sequence" = "sequence" + 1 WHERE "CableLine" = 2

id = 10を含む行の「シーケンス」が1だけ増加すると、"sequence" = 2を含む別の行がすでに存在するというエラーが表示されます。

13
dedoki

UPDATE with _ORDER BY_

タイトルで出された質問に関して:SQL UPDATEコマンドには_ORDER BY_がありません。 Postgresは任意の順序で行を更新します。ただし、制約を各行の後、各ステートメントの後、またはトランザクションの最後にチェックするかどうかを決定する(制限された)オプションがあります。 DEFERRABLE制約を使用すると、intermediate状態の重複キー違反を回避できます。

私はこの質問の下で私たちが解決したことを引用しています:

ただし、制限があります。外部キー制約では、ターゲット列にnon-deferrable制約が必要です。

参照される列は、参照されるテーブルの遅延できない一意キーまたは主キー制約の列である必要があります。

Workaround

質問の更新後に更新されました。
通常の操作で_"sequence"_が負になることはないと仮定すると、次のような固有のエラーを回避できます。

_UPDATE tbl SET "sequence" = ("sequence" + 1) * -1
WHERE  "CableLine" = 2;

UPDATE tbl SET "sequence" = "sequence" * -1
WHERE  "CableLine" = 2
AND    "sequence" < 0;
_

遅延できない制約(デフォルト)では、これを機能させるために2つの個別のコマンドを実行する必要があります。同時実行の問題を回避するために、コマンドをすばやく連続して実行します。このソリューションは明らかに重い同時負荷には適していません。

余談:
テーブルエイリアスの場合、ワードASをスキップしても問題ありませんが、列エイリアスの場合は同じようにしないことをお勧めします。

許可されていても、SQLキーワードを識別子として使用しないことをお勧めします。

問題を回避する

大規模な場合、または同時負荷の高いデータベースの場合、行の相対的な順序付けに serial 列を使用する方が賢明です。ビューまたはクエリでウィンドウ関数row_number()を使用すると、1から始まり、ギャップのない数値を生成できます。この関連する回答を検討してください:

10

UPDATE with ORDER BY

UPDATE thetable 
  SET columntoupdate=yourvalue 
 FROM (SELECT rowid, 'thevalue' AS yourvalue 
         FROM thetable 
        ORDER BY rowid
      ) AS t1 
WHERE thetable.rowid=t1.rowid;

UPDATEの順序はまだランダムです(私は推測します)が、UPDATEコマンドに提供された値はthetable.rowid=t1.rowid条件と一致します。だから私がやっていることは、最初にメモリ内の「更新された」テーブルを選択し、上のコードではt1という名前を付け、次に物理テーブルをt1と同じように見せます。また、更新の順序は関係ありません。

真に順序付けられたUPDATEについては、誰にとっても有用であるとは思えません。

13
alexkovelsky
Update with Order By
Declare 
v number;
cursor c1 is 
    Select col2 from table1 order by col2;
    begin
    v:=0;
     for c in c1
     loop
    update table1 
    set col1 =v+1
    where col2 = c.col2;
    end loop;
    commit;
    END;

これは私のために働きました:

[ここでステートメントを更新] OPTION(MAXDOP 1)-レコードが更新される順序を利用する熱心なスプールの使用を行サイズが引き起こすのを防ぎます。

私はクラスター化されたintインデックスを順次(必要に応じて生成)で使用し、最近まで問題がありませんでした。それでも、クエリプランオプティマイザーが(逆に)遅延スプールを使用することを決定した小さな行セットでのみ問題がありました。

理論的には、新しいオプションを使用してスプールの使用を禁止することもできますが、maxdopの方が簡単です。

計算が分離されているため(シングルユーザー)、私は独特の状況にあります。別の状況では、競合を回避するためにmaxdop制限を使用する代わりの方法が必要になる場合があります。

0
cmore

Postgresqlのtable_id_seqを1から並べ替えて、IDで並べ替える問題が発生したのと同じように、誰かがここに来た場合。私が試した解決策は、@ Syd Nazam Ul Hasan(上記)および https://Gist.github.com/JoshCheek/e19f83f271dc16d7825e2e4079538ba8 から部分的に取られました。

CREATE OR REPLACE FUNCTION update_sequence()
RETURNS SETOF varchar AS $$
DECLARE
  curs CURSOR FOR SELECT * FROM table ORDER BY id ASC;
  row  RECORD;
  v INTEGER := 0;
BEGIN
  open curs;
  LOOP
    FETCH FROM curs INTO row;
    update table 
    set id = v+1
    where id = row.id;
    v = v+1;
    EXIT WHEN NOT FOUND;
    return next row.id;
  END LOOP;
END; $$ LANGUAGE plpgsql;

SELECT update_sequence();
0
ssi-anik

レイジーウェイ、(別名最速または最良の方法ではありません)

CREATE OR REPLACE FUNCTION row_number(table_name text, update_column text, start_value integer, offset_value integer, order_by_column text, order_by_descending boolean)
  RETURNS void AS
$BODY$
DECLARE
    total_value integer;
    my_id text;
    command text;
BEGIN
total_value = start_value;
    command = 'SELECT ' || order_by_column || ' FROM ' || table_name || ' ORDER BY '  || order_by_column;

    if (order_by_descending) THEN
        command = command || ' desc';
    END IF;

    FOR  my_id in  EXECUTE command LOOP
        command = 'UPDATE ' || table_name || ' SET  ' || update_column || ' = ' || total_value || ' WHERE ' || order_by_column || ' = ' ||  my_id|| ';';

        EXECUTE command;
        total_value = total_value + offset_value;
    END LOOP;
END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE
  COST 100;

SELECT row_number( 'regispro_spatial_2010.ags_states_spatial'、 'order_id'、10,1、 'ogc_fid'、true)

0
user3605589