UPDATE

名前

UPDATE -- テーブルの行を更新する

概要

UPDATE [ ONLY ] table [ [ AS ] alias ]
    SET { column = { expression | DEFAULT } |
          ( column [, ...] ) = ( { expression | DEFAULT } [, ...] ) } [, ...]
    [ FROM fromlist ]
    [ WHERE condition ]
    [ RETURNING * | output_expression [ AS output_name ] [, ...] ]

説明

UPDATEは、条件を満たす全ての行の指定した列の値を変更します。 SET句には、変更する列のみを指定する必要があります。 SET句にて明示的に指定されなかった列の値は変更されません。

デフォルトでは、UPDATEは指定したテーブルとその副テーブルの行を更新します。 指定されたテーブルのみを更新したい場合はONLY句を使用してください。

データベース内の他のテーブルの情報を使用してテーブルを変更するには、2つの方法があります。 1つは副問い合わせを使用する方法、もう1つはFROM句で追加するテーブルを指定する方法です。 どちらの方法が適切であるかは状況次第です。

省略可能なRETURNING句により、UPDATEは実際に更新された各行に基づいて計算された値を返すようになります。 そのテーブルの列、FROMで指定された他のテーブルの列、あるいは、その両方を使用した式を計算することができます。 テーブル列の新しい(更新された後の)値が使用されます。 RETURNINGリストの構文はSELECTの出力リストと同一です。

テーブルを変更するにはUPDATE権限が必要です。 さらに、expressionsconditionで読み込むテーブルに対するSELECT権限も必要になります。

パラメータ

table

更新対象のテーブルの名前です(スキーマ修飾名でも可)。

alias

対象テーブルの代替名です。 別名が指定されると、テーブルの実際の名前は完全に隠蔽されます。 たとえば、UPDATE foo AS fでは、UPDATE文の残りの部分ではfooではなくfとしてこのテーブルを参照しなければなりません。

column

table内の列名です。 必要に応じて、列名を副フィールド名や配列の指示子で修飾することも可能です。 対象列の指定にはテーブル名を含めないでください。 たとえば、UPDATE tab SET tab.col = 1は無効です。

expression

列に代入する式です。 この式では、テーブル内の対象列やその他の列の変更前の値を使用することができます。

DEFAULT

列にデフォルト値を設定します (デフォルト式が割り当てられていない場合はNULLになります)。

fromlist

WHERE条件や更新用の式において、他のテーブルの列を指定するために使用するテーブル式の集合です。 これはSELECT文のFROMで指定するテーブルのリストに似ています。 自己結合を行う場合を除き、fromlistに更新対象のテーブルを含める必要はありません (自己結合を行う場合は、fromlist内で更新対象のテーブルとその別名を指定しておく必要があります)。

condition

boolean型の値を返す式です。 この式がtrueを返す行のみが更新されます。

output_expression

各行を更新した後に計算され、UPDATEによって返される式です。 この式には、tableまたはFROMで指定したテーブル(複数可)の任意の列名を使用することができます。 すべての列を返す場合は*と記載してください。

output_name

返される列で使用される名前です。

出力

正常に処理が終わると、UPDATEコマンドは以下の形式のコマンドタグを返します。

UPDATE count

countは更新された行数を意味します。 countが0の場合はconditionに一致する行がなかったことを意味します (これはエラーとはみなされません)。

UPDATEコマンドがRETURNING句を持つ場合、その結果は、RETURNINGリストで定義した列と値を持ち、そのコマンドで更新された行全体に対して計算を行うSELECT文の結果と似たものになるでしょう。

注釈

FROM句が存在する場合、基本的に、対象テーブルとfromlistで指定されたテーブルが結合され、この結合の出力行が対象テーブルの更新操作の結果となります。 FROM句を使用する場合、更新対象テーブルの1行に対して、結合結果が複数行にならないように注意してください。 言い換えると、対象テーブルの個々の行は、他テーブルの複数の行と結合すべきではありません。 結合結果が複数行になった場合、対象行の更新には結合結果のいずれか1行のみが使用されますが、どの行が使用されるかは簡単には予測できません。

このような問題があるため、他テーブルの参照は副問い合わせ内のみに留めておいた方がより安全です(ただし、結合よりも可読性や実行速度は低下します)。

filmsテーブルのkind列にあるDramaという単語をDramaticに変更します。

UPDATE films SET kind = 'Dramatic' WHERE kind = 'Drama';

weatherテーブルの特定の行に対し、気温という項目を調整し、降水量をデフォルト値に戻します。

UPDATE weather SET temp_lo = temp_lo+1, temp_hi = temp_lo+15, prcp = DEFAULT
  WHERE city = 'San Francisco' AND date = '2003-07-03';

同じ操作を行い、更新された項目を返します。

UPDATE weather SET temp_lo = temp_lo+1, temp_hi = temp_lo+15, prcp = DEFAULT
  WHERE city = 'San Francisco' AND date = '2003-07-03'
  RETURNING temp_lo, temp_hi, prcp;

別の列リスト構文を使用して同様の更新を行います。

UPDATE weather SET (temp_lo, temp_hi, prcp) = (temp_lo+1, temp_lo+15, DEFAULT)
  WHERE city = 'San Francisco' AND date = '2003-07-03';

FROM句構文を使用して、アクメ社を顧客とするセールスマンのセールスカウントを1増加させます。

UPDATE employees SET sales_count = sales_count + 1 FROM accounts
  WHERE accounts.name = 'Acme Corporation'
  AND employees.id = accounts.sales_person;

WHERE句で副問い合わせを使用して、同じ操作を行います。

UPDATE employees SET sales_count = sales_count + 1 WHERE id =
  (SELECT sales_person FROM accounts WHERE name = 'Acme Corporation');

新しい商品とその在庫数を挿入します。 既にその商品が存在している場合は、代わりに既存商品の在庫数を更新します。 トランザクション全体が失敗することがないようにこの操作を行うには、セーブポイントを使用してください。

BEGIN;
-- 何かしらの他の操作を行います。
SAVEPOINT sp1;
INSERT INTO wines VALUES('Chateau Lafite 2003', '24');
-- 上記のコマンドが一意キー違反により失敗したとします。
-- この場合、次のコマンドを実行します。
ROLLBACK TO sp1;
UPDATE wines SET stock = stock + 24 WHERE winename = 'Chateau Lafite 2003';
-- 他の操作を続けた後、最後に次を実行します。
COMMIT;

互換性

このコマンドは標準SQLに準拠しています。 ただしFROM句およびRETURNING句はPostgreSQLの拡張です。

標準に従うと、列リスト構文は、副選択のような単一の行値式から代入される列のリストを許可しなければなりません。

UPDATE accounts SET (contact_last_name, contact_first_name) =
    (SELECT last_name, first_name FROM salesmen
     WHERE salesmen.id = accounts.sales_id);

これは現時点ではサポートされていません。ソースは独立した式でなければなりません。

他のデータベースシステムには、FROMオプション内で、対象テーブルが再度指定されることを前提として動作するものもあります。 これはPostgreSQLにおけるFROMの解釈方法とは異なります。 FROM拡張機能を使用するアプリケーションを移植する時は注意してください。