★PostgreSQLカンファレンス2024 12月6日開催/チケット販売中★
他のバージョンの文書 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9.6 | 9.5 | 9.4 | 9.3 | 9.2 | 9.1 | 9.0 | 8.4 | 8.3 | 8.2 | 8.1 | 8.0 | 7.4 | 7.3 | 7.2

INSERT

INSERT — テーブルに新しい行を作成する

概要

[ WITH [ RECURSIVE ] with_query [, ...] ]
INSERT INTO table_name [ AS alias ] [ ( column_name [, ...] ) ]
    [ OVERRIDING { SYSTEM | USER } VALUE ]
    { DEFAULT VALUES | VALUES ( { expression | DEFAULT } [, ...] ) [, ...] | query }
    [ ON CONFLICT [ conflict_target ] conflict_action ]
    [ RETURNING { * | output_expression [ [ AS ] output_name ] } [, ...] ]


ここでconflict_targetは以下のいずれかです。

    ( { index_column_name | ( index_expression ) } [ COLLATE collation ] [ opclass ] [, ...] ) [ WHERE index_predicate ]
    ON CONSTRAINT constraint_name


またconflict_actionは以下のいずれかです。

    DO NOTHING
    DO UPDATE SET { column_name = { expression | DEFAULT } |
                    ( column_name [, ...] ) = [ ROW ] ( { expression | DEFAULT } [, ...] ) |
                    ( column_name [, ...] ) = ( sub-SELECT )
                  } [, ...]
              [ WHERE condition ]

説明

INSERTはテーブルに新しい行を挿入します。 値式を使用して行(複数可)を挿入すること、および、問い合わせの結果を使って0行以上の行を挿入することができます。

対象の列名はどのような順番でも指定できます。 列名リストが指定されなかった場合は、テーブル内の全ての列を宣言時の順番に並べたものがデフォルトとして使われます。 また、VALUES句やqueryN列のみが与えられた場合は、先頭のN列の名前が指定されたものとみなされます。 VALUES句やqueryで提供される値は、明示的または暗黙的な列リストと左から右への順で関連付けられます。

明示的または暗黙的な列リストにない各列にはデフォルト値(デフォルト値が宣言されていればその値、未宣言ならばNULL)が挿入されます。

各列の式が正しいデータ型でない場合は、自動的に型の変換が行われます。

一意インデックスのないテーブルへのINSERTは同時実行中の処理によりブロックされることはありません。 挿入される一意インデックスの値と一致する行をロックまたは修正する動作を同時実行中のセッションがしている場合には、一意インデックスのあるテーブルはブロックします。詳細は64.5で扱っています。 ON CONFLICTは一意制約または排他制約について、違反のエラーを発生させるのに代わる動作を指定するのに使うことができます。 (以下のON CONFLICT句を参照してください。)

RETURNING句を指定すると、INSERTは実際に挿入された(あるいはON CONFLICT DO UPDATE句によって更新された)各行に基づいて計算された値を返すようになります。 これは、通番のシーケンス番号など、デフォルトで与えられた値を取り出す時に主に便利です。 しかし、そのテーブルの列を使用した任意の式を指定することができます。 RETURNINGリストの構文はSELECTの出力リストと同一です。 挿入または更新に成功した行だけが返されます。 例えば、行がロックされていて、ON CONFLICT DO UPDATE ... WHERE句の conditionが満たされなかったために更新されなかった行は返されません。

テーブルに行を追加するには、そのテーブルに対してINSERT権限を持っている必要があります。 ON CONFLICT DO UPDATEがある場合は、テーブルのUPDATE権限も必要です。

列リストを指定する場合は、列挙された列に対するINSERT権限のみが必要です。 同様に、ON CONFLICT DO UPDATEが指定されている場合、更新対象として列挙されている列についてのみ、UPDATE権限が必要です。 しかし、ON CONFLICT DO UPDATEは、値がON CONFLICT DO UPDATE式あるいはconditionで読み取られるすべての列についてSELECT権限も必要です。

RETURNING句を使用するには、RETURNINGで使用するすべての列に対するSELECT権限が必要です。 queryを使用して問い合わせ結果を元に行を挿入する場合は当然ながら、その問い合わせ内で使われる全てのテーブルまたは列に対してSELECT権限を持っている必要があります。

パラメータ

挿入

この節では新しい行を挿入するときにのみ使われるパラメータについて説明します。 ON CONFLICT句においてのみ使われるパラメータについては、別に説明します。

with_query

WITH句により、INSERT問い合わせ内で名前により参照することができる1つ以上の副問い合わせを指定することができます。 詳しくは7.8SELECTを参照してください。

querySELECT文)でもまた、WITH句を含めることができます。 こうした場合、with_queryの集合との両方をquery内で参照することができます。 しかし、第二の問い合わせがより近くにネストされているため優先します。

table_name

既存のテーブルの名前です(スキーマ修飾名も可)。

alias

table_nameの代替名です。 aliasを指定すると、テーブルの実際の名前が完全に隠されます。 これは、excludedという名前のテーブルをON CONFLICT DO UPDATEが対象にしている場合、これを指定しなければ、それが挿入で処理される行を表現する特別なテーブルの名前とみなされるため、特に有用となります。

column_name

table_nameで指名されたテーブル内の列名です。 必要なら列名を副フィールドの名前や配列の添え字で修飾することができます。 (複合型の列の一部のフィールドのみを挿入すると他のフィールドはNULLになります。) ON CONFLICT DO UPDATEで列を参照する場合、対象列の指定にテーブル名を含めてはいけません。 例えば、INSERT INTO table_name ... ON CONFLICT DO UPDATE SET table_name.col = 1は無効です(これはUPDATEの一般的な動作に従います)。

OVERRIDING SYSTEM VALUE

この句が指定されると、IDENTITY列について指定された値がシーケンスが生成したデフォルト値に優先します。

GENERATED ALWAYSと定義されているIDENTITY列に対しては、OVERRIDING SYSTEM VALUEOVERRIDING USER VALUEを指定せずに(DEFAULT以外の)明示的な値を挿入するのはエラーです。 (GENERATED BY DEFAULTと定義されているIDENTITY列に対しては、OVERRIDING SYSTEM VALUEが通常の振る舞いであり、指定したとしても何もしませんが、PostgreSQLは拡張として許容します。)

OVERRIDING USER VALUE

この句が指定されると、IDENTITY列について指定された値はすべて無視されて、シーケンスが生成したデフォルト値が適用されます。

この句は例えばテーブル間で値をコピーする時に有用です。 INSERT INTO tbl2 OVERRIDING USER VALUE SELECT * FROM tbl1とすると、tbl1の列でtbl2のIDENTITY列でないものがすべてコピーされる一方、tbl2のIDENTITY列の値は、tbl2に紐付けられたシーケンスによって生成されます。

DEFAULT VALUES

各列に対してDEFAULTが明示的に指定されたかのように、すべての列にそれぞれのデフォルト値が設定されます。 (OVERRIDINGはこの構文では使用できません。)

expression

対応する列に代入する式または値を指定します。

DEFAULT

対応する列にデフォルト値を設定します。 IDENTITY列には関連付けられた列により新しく生成された値が書き込まれます。 生成列に対して、これを指定することは許されていますが、単に生成式から列を計算するという普通の振る舞いを指定するだけです。

query

挿入する行を提供する問い合わせ(SELECT文)を指定します。 構文の説明についてはSELECT文を参照してください。

output_expression

各行が挿入または更新された後、INSERTにより計算され、返される式です。 この式にはtable_nameで指名されたテーブルの任意の列名を使用することができます。 挿入または更新された行のすべての列を返す場合は*と記載してください。

output_name

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

ON CONFLICT

オプションのON CONFLICT句では、一意制約や排他制約の違反について、エラーを発生させる代替となる動作を指定します。 挿入しようとされた各行について、挿入の処理が進められるか、あるいは、conflict_targetにより指定された競合制約またはインデックスに違反した場合の代替のconflict_actionが実行されるか、のいずれかです。 ON CONFLICT DO NOTHINGは代替の動作として、単に行の挿入をしなくなるだけです。 ON CONFLICT DO UPDATEは代替の動作として、挿入されようとしていた行と競合する既存の行を更新します。

conflict_target一意インデックスの推定を実行することができます。 推定を実行するとき、それは1つ以上のindex_column_name列、またはindex_expression式、あるいはその両方、およびオプションでindex_predicateから構成されます。 table_nameの一意インデックスでconflict_targetで指定された列と式を(順序は関係なく)正確に含むものは、すべて競合解決インデックスとして推定されます(選ばれます)。 index_predicateが指定されている場合は、推定のさらなる条件として、それは競合解決インデックスを満たさなければなりません。 これは、部分インデックスでない一意インデックス(述語のない一意インデックス)は、それが他のすべての条件を満たすのであれば推定される(従ってON CONFLICTで使用される)ことを意味することに注意して下さい。 推定に失敗した時は、エラーが発生します。

ON CONFLICT DO UPDATEINSERTまたはUPDATEの原子的な結果を保証します。 無関係のエラーが発生しなければ、多数の同時実行がある状況においてさえも、それら2つの結果のうちの1つになります。 これはUPSERT、つまりUPDATE or INSERTとしても知られています。

conflict_target

ON CONFLICT競合解決インデックスを選ぶことで代替の動作をするときの競合を指定します。 一意インデックスの推定を実行するか、あるいは制約を明示的に指定するかのいずれかです。 ON CONFLICT DO NOTHINGではconflict_targetを指定するのはオプションです。 省略すると、利用可能なすべての制約(および一意インデックス)との競合が処理されます。 ON CONFLICT DO UPDATEではconflict_targetを指定しなければなりません

conflict_action

conflict_actionではON CONFLICTの代替の動作を指定します。 これはDO NOTHINGあるいはDO UPDATE句のいずれかをとることができ、後者では競合が発生した場合に実行されるUPDATEの動作の正確な詳細を記述します。 ON CONFLICT DO UPDATESET句とWHEREは既存の行にテーブルの名前(または別名)を使ってアクセスでき、また挿入されようとしていた行には、特別なexcludedテーブルを使ってアクセスできます。 excludedの列を読み取るときには、対象テーブルの対応する列のSELECT権限が必要です。

すべての行レベルのBEFORE INSERTトリガーの結果がexcludedの値に反映されることに注意して下さい。 これらの結果として、行が挿入から除外されることになったかもしれないからです。

index_column_name

table_nameの列の名前です。 競合解決インデックスを推定するのに使われます。 CREATE INDEXの形式に従います。 index_column_nameSELECTが必要です。

index_expression

index_column_nameと似ていますが、インデックスの定義に現れるtable_nameの列の式(単純な列ではない)の推定に使われます。 CREATE INDEXの形式に従います。 index_expressionに現れるすべての列のSELECT権限が必要です。

collation

これを指定すると、推定時に、対応するindex_column_nameあるいはindex_expressionをマッチさせるときに、特定の照合順序を指定することになります。 普通は照合順序は制約違反が発生するかどうかに関係しないので、通常は省略されます。 CREATE INDEXの形式に従います。

opclass

これを指定すると、推定時に、対応するindex_column_nameあるいはindex_expressionをマッチさせるときに、特定の演算子クラスを指定することになります。 等価の意味は、いずれにせよ、型の演算子クラスをまたがって同等であることが多いですし、また定義された一意インデックスは等価を適切に定義していると信頼すれば十分なので、通常はこれは省略されます。 CREATE INDEXの形式に従います。

index_predicate

部分一意インデックスの推定を可能にします。 述語を満たすすべてのインデックス(実際に部分インデックスである必要はありません)は推定可能になります。 CREATE INDEXの形式に従います。 index_predicateに現れるすべての列についてSELECT権限が必要です。

constraint_name

競合解決の制約を制約やインデックスの推定によるのではなく、明示的に名前で指定します。

condition

boolean型の値を返す式です。 この式がtrueを返す行のみが更新されます。 ただし、ON CONFLICT DO UPDATEの動作が行われるときは、すべての行がロックされます。 conditionは最後に評価される、競合が更新対象候補として特定された後であることに注意して下さい。

排他制約はON CONFLICT DO UPDATEの競合解決としてはサポートされないことに注意して下さい。 すべての場合について、NOT DEFERRABLEである制約と一意インデックスのみが競合解決としてサポートされます。

ON CONFLICT DO UPDATE句のあるINSERT決定論的な文です。 これは、そのコマンドが既存のどの行に対しても、2回以上影響を与えることが許されない、ということを意味します。 これに反する状況が発生した時は、カーディナリティ違反のエラーが発生します。 挿入されようとする行は、競合解決インデックスあるいは制約により制限される属性の観点で、複製されてはなりません。

パーティションテーブルに適用されたINSERTON CONFLICT DO UPDATE句に対しては、その行を新しいパーティションに移動する必要のあるような競合する行のパーティションキーを更新することは現在サポートされていないことに注意してください。

ヒント

ON CONFLICT ON CONSTRAINT constraint_nameを使って制約を直接指定するより、一意インデックスの推定を使う方が望ましいことが多いです。 背景にあるインデックスが、他のほぼ同等のインデックスと重なり合う形で置換されるとき、推定は正しく動作し続けます。 例えば、置換されるインデックスを削除する前にCREATE UNIQUE INDEX ... CONCURRENTLYを使う場合です。

出力

正常に終了すると、INSERTは以下のようなコマンドタグを返します。

INSERT oid count

countは挿入または更新された行数です。 oidは常に0です(countが正確に1であり、対象のテーブルがWITH OIDSと宣言されていた場合、挿入された行にOIDが、そうでなければ0が割り当てられていましたが、WITH OIDSでテーブルを作成することは今はもうサポートされていません)。

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

注釈

指定したテーブルがパーティションテーブルの場合、各行は適切なパーティションに回され、そちらに挿入されます。 指定したテーブルがパーティションの場合、挿入行にパーティションの制約に違反するものがあれば、エラーが発生します。

MERGEを使用すると、単一の文内でINSERTUPDATEDELETEを混在させることができます。 MERGEを参照してください。

filmsテーブルに1行を挿入します。

INSERT INTO films VALUES
    ('UA502', 'Bananas', 105, '1971-07-13', 'Comedy', '82 minutes');

次の例では、len列を省略しています。 したがって、ここにはデフォルト値が入ります。

INSERT INTO films (code, title, did, date_prod, kind)
    VALUES ('T_601', 'Yojimbo', 106, '1961-06-16', 'Drama');

次の例では、日付列に対して値を指定する代わりにDEFAULTを使用します。

INSERT INTO films VALUES
    ('UA502', 'Bananas', 105, DEFAULT, 'Comedy', '82 minutes');
INSERT INTO films (code, title, did, date_prod, kind)
    VALUES ('T_601', 'Yojimbo', 106, DEFAULT, 'Drama');

全てデフォルト値からなる行を挿入します。

INSERT INTO films DEFAULT VALUES;

複数行のVALUES構文を使用して複数行を挿入します。

INSERT INTO films (code, title, did, date_prod, kind) VALUES
    ('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'),
    ('HG120', 'The Dinner Game', 140, DEFAULT, 'Comedy');

次の例では、filmsテーブルと同じ列レイアウトを持つtmp_filmsテーブルからfilmsテーブルへいくつか行を挿入します。

INSERT INTO films SELECT * FROM tmp_films WHERE date_prod < '2004-05-07';

次の例では、配列型の列に挿入します。


-- 三目並べ用の3×3マスのゲーム盤を作成します。
INSERT INTO tictactoe (game, board[1:3][1:3])
    VALUES (1, '{{" "," "," "},{" "," "," "},{" "," "," "}}');

--上の例の添え字は本当は必要ありません。
INSERT INTO tictactoe (game, board)
    VALUES (2, '{{X," "," "},{" ",O," "},{" ",X," "}}');

distributorsテーブルに一行を挿入し、そのDEFAULT句により生成されたシーケンス番号を返します。

INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets')
   RETURNING did;

Acme社の顧客を担当する営業担当者の売り上げ数を増やし、ログテーブルに更新行全体と更新時刻を記録します。

WITH upd AS (
  UPDATE employees SET sales_count = sales_count + 1 WHERE id =
    (SELECT sales_person FROM accounts WHERE name = 'Acme Corporation')
    RETURNING *
)
INSERT INTO employees_log SELECT *, current_timestamp FROM upd;

新しい販売店(distributors)を適切に挿入または更新します。 did列に現れる値を制限する一意インデックスが定義されているものとします。 元々挿入されようとしていた値を参照するために、特別なexcludedテーブルが使用されていることに注意して下さい。

INSERT INTO distributors (did, dname)
    VALUES (5, 'Gizmo Transglobal'), (6, 'Associated Computing, Inc')
    ON CONFLICT (did) DO UPDATE SET dname = EXCLUDED.dname;

販売店を挿入するか、あるいは挿入しようとした行について既存の除外行(before insertの行トリガを実行した後で制約列にマッチした行)がある場合は何もしません。 例ではdid列に現れる値を制限する一意インデックスがあるものとしています。

INSERT INTO distributors (did, dname) VALUES (7, 'Redline GmbH')
    ON CONFLICT (did) DO NOTHING;

新しい販売店を適切に挿入または更新します。 例ではdid列に現れる値を制限する一意インデックスがあるものとしています。 実際に更新される行を制限するためにWHERE句が使われています(ただし、更新されない既存の行もすべてロックされます)。


-- 特定の郵便番号については既存の販売店を更新しません
INSERT INTO distributors AS d (did, dname) VALUES (8, 'Anvil Distribution')
    ON CONFLICT (did) DO UPDATE
    SET dname = EXCLUDED.dname || ' (formerly ' || d.dname || ')'
    WHERE d.zipcode <> '21201';


-- 文中で制約を直接指定します(DO NOTHINGの動作をする競合解決のため
-- 関連するインデックスを指定します)
INSERT INTO distributors (did, dname) VALUES (9, 'Antwerp Design')
    ON CONFLICT ON CONSTRAINT distributors_pkey DO NOTHING;

可能であれば新しい販売店を挿入しますが、できないときはDO NOTHINGとします。 この例では、is_activeという論理値の列がtrueである行という条件で、did列に一意インデックスが定義されているものとしています。


-- この文は"WHERE is_active"という述語を使って、部分インデックスを
-- 推定できますが、単に"did"上の通常の一意制約を使うこともできます
INSERT INTO distributors (did, dname) VALUES (10, 'Conrad International')
    ON CONFLICT (did) WHERE is_active DO NOTHING;

互換性

INSERTは標準SQLに準拠します。 ただし、RETURNING句、INSERTWITHが可能であること、ON CONFLICTで代替の動作を指定できることはPostgreSQLの拡張です。 また、標準SQLでは、列名リストが省略された時に、VALUES句またはqueryで一部の列のみを指定することはできません。 ON CONFLICTよりも標準SQLにより準拠した文がお望みであれば、MERGEを参照してください。

標準SQLでは、必ず値を生成するIDENTITY列が存在する場合にのみOVERRIDING SYSTEM VALUEを指定できるとしています。 PostgreSQLではこの句はどのような場合でも指定でき、それが適用できないときには無視します。

query句の制限については、SELECTにて記述されています。