最終バージョン
...OPからのいくつかの詳細情報の後。このデモを検討してください:
-- DROP TABLE foo; DROP TABLE bar;
CREATE TEMP TABLE bar (
id serial PRIMARY KEY -- using a serial column!
,z integer NOT NULL
);
CREATE TEMP TABLE foo (
id serial PRIMARY KEY -- using a serial column!
,x integer NOT NULL
,y integer NOT NULL
,bar_id integer UNIQUE NOT NULL REFERENCES bar(id)
);
値を挿入-bar
最初に。
それは非常に役に立ちます このような質問でテストデータを提供した場合!
INSERT INTO bar (id,z) VALUES
(100, 7)
,(101,16)
,(102,21);
INSERT INTO foo (id, x, y, bar_id) VALUES
(1, 3,4,100)
,(2, 9,6,101)
,(3,18,0,102);
シーケンスを現在の値に設定しないと、重複するキー違反が発生します:
SELECT setval('foo_id_seq', 3);
SELECT setval('bar_id_seq', 102);
チェック:
-- SELECT nextval('foo_id_seq')
-- SELECT nextval('bar_id_seq')
-- SELECT * from bar;
-- SELECT * from foo;
クエリ:
WITH a AS (
SELECT f.x, f.y, bar_id, b.z
FROM foo f
JOIN bar b ON b.id = f.bar_id
WHERE x > 3
),b AS (
INSERT INTO bar (z)
SELECT z
FROM a
RETURNING z, id AS bar_id
)
INSERT INTO foo (x, y, bar_id)
SELECT a.x, a.y, b.bar_id
FROM a
JOIN b USING (z);
これにより、前回の更新で説明されていることが実行されます。
クエリはz
を想定しています はUNIQUE
。 z
の場合 ユニークではなく、より複雑になります。ウィンドウ関数row_number()
を使用したすぐに解決できるソリューションについては、この関連する回答のクエリ2を参照してください。 この場合。
また、 1:1の関係を置き換えることを検討してください foo
の間 およびbar
単一の統合されたテーブルで。
データ変更CTE
詳細情報の後の2番目の回答。
foo
に行を追加する場合 および バーコード> PostgreSQL 9.1 以降、1つのクエリでデータ変更CTEを使用できます :
WITH x AS (
INSERT INTO bar (col1, col2)
SELECT f.col1, f.col2
FROM foo f
WHERE f.id BETWEEN 12 AND 23 -- some filter
RETURNING col1, col2, bar_id -- assuming bar_id is a serial column
)
INSERT INTO foo (col1, col2, bar_id)
SELECT col1, col2, bar_id
FROM x;
foo
から値を描画します 、 bar
に挿入します 、自動生成された bar_id
と一緒に返送してもらいます それを挿入します foo
に 。他のデータも使用できます。
これがsqlfiddleで遊ぶための実用的なデモです。
基本
説明の前に基本的な情報を含む元の回答。
基本的な形式は次のとおりです。
INSERT INTO foo (...)
SELECT ... FROM foo WHERE ...
括弧は必要ありません。どのテーブルでも同じことができます
INSERT INTO foo (...)
SELECT ... FROM bar WHERE ...
そして、SELECTで挿入したテーブルに参加できます:
INSERT INTO foo (...)
SELECT f.col1, f.col2, .. , b.bar_id
FROM foo f
JOIN bar b USING (foo_id); -- present in foo and bar
これは、他のSELECTと同じように、挿入先のテーブルを含めることができる単なるSELECTです。行は最初に読み取られ、次に挿入されます。