32

val1テーブルのtable11 つの列val2から別のテーブルの1 つの列にすべての値をコピーしたいtable2。PostgreSQLでこのコマンドを試しました:

update table2
set val2 = (select val1 from table1)

しかし、私はこのエラーが発生しました:

ERROR:  more than one row returned by a subquery used as an expression

それを行う代替手段はありますか?

4

2 に答える 2

77

クエリUPDATEは次のようになります。

UPDATE table2 t2
SET    val2 = t1.val1
FROM   table1 t1
WHERE  t2.table2_id = t1.table2_id
AND    t2.val2 IS DISTINCT FROM t1.val1;  -- optional, see below

あなたが持っていた方法では、2 つのテーブルの個々の行の間にリンクはありませんでした。table1のすべての行に対して、すべての行がからフェッチされますtable2。この場所のサブクエリ式は単一の値のみを返すことが許可されているため、これは (コストのかかる方法で) 意味がなく、構文エラーも引き起こしました。

で 2 つのテーブルを結合することで、これを修正しましたtable2_id。それを実際に2つをリンクするものに置き換えます。

相関サブクエリを実行する代わりに、(句を使用して)UPDATE参加するように書き直しました。これは、通常、桁違いに高速であるためです。 また、で一致する行が見つからない場合に が無効になるのを防ぎます。代わりに、この形式のクエリでは、そのような行には何も起こりません。table1FROM
table2.val2table1

FROMプレーンSELECT(テーブル、サブクエリ、セットを返す関数など)のように、テーブル式をリストに追加できます。マニュアル:

from_list

テーブル式のリスト。他のテーブルの列をWHERE条件および更新式に表示できます。 これは、ステートメントのFROMで指定できるテーブルのリストに似ています。自己結合を意図しない限りSELECT、ターゲット テーブルを に表示してはならないことに注意してください(その場合は、 にエイリアスを付けて表示する必要があります)。from_listfrom_list

最後のWHERE句は、何も変更しない更新を防ぎます。これは、実際には常に良い考えです (ほぼ完全なコストですが、利益はありません。エキゾチックな例外が適用されます)。古い値と新しい値の両方が であることが保証されている場合は、次のようNOT NULLに単純化します。

AND   t2.val2 <> t1.val1
于 2012-11-20T12:55:11.240 に答える
0

update table1 set table1_column= table2.column from table2 table2 where table1_id= table2.id

  1. table1 にエイリアス名を使用しないでください。
  2. テーブルは table1、table2
于 2016-06-24T07:20:20.253 に答える