データ変更CTEを使用する :
WITH ins1 AS (
INSERT INTO sample(firstname, lastname)
VALUES ('fai55', 'shaggk')
-- ON CONFLICT DO NOTHING -- optional addition in Postgres 9.5+
RETURNING id AS sample_id
)
, ins2 AS (
INSERT INTO sample1 (sample_id, adddetails)
SELECT sample_id, 'ss' FROM ins1
RETURNING user_id
)
INSERT INTO sample2 (user_id, value)
SELECT user_id, 'ss2' FROM ins2;
各INSERT
前のものに依存します。 SELECT
VALUES
の代わりに 前のINSERT
から行が返されない場合は、補助テーブルに何も挿入されないようにします 。 (Postgres 9.5以降では、ON CONFLICT
を追加できます。 。)
この方法では、少し短くて高速です。
通常、完全なデータ行を1か所に提供する方が便利です。 :
WITH data(firstname, lastname, adddetails, value) AS (
VALUES -- provide data here
('fai55', 'shaggk', 'ss', 'ss2') -- see below
, ('fai56', 'XXaggk', 'xx', 'xx2') -- works for multiple input rows
-- more?
)
, ins1 AS (
INSERT INTO sample (firstname, lastname)
SELECT firstname, lastname -- DISTINCT? see below
FROM data
-- ON CONFLICT DO NOTHING -- UNIQUE constraint? see below
RETURNING firstname, lastname, id AS sample_id
)
, ins2 AS (
INSERT INTO sample1 (sample_id, adddetails)
SELECT ins1.sample_id, d.adddetails
FROM data d
JOIN ins1 USING (firstname, lastname)
RETURNING sample_id, user_id
)
INSERT INTO sample2 (user_id, value)
SELECT ins2.user_id, d.value
FROM data d
JOIN ins1 USING (firstname, lastname)
JOIN ins2 USING (sample_id);
db<>ここでフィドル
スタンドアロンのVALUES
で明示的な型キャストが必要になる場合があります 式-VALUES
とは対照的 INSERT
に付加された式 ここで、データ型はターゲットテーブルから派生します。参照:
- 複数の行を更新するときにNULLタイプをキャストする
複数の行に同じ(firstname, lastname)
を付けることができる場合 、最初のINSERT
の重複を折りたたむ必要がある場合があります :
...
INSERT INTO sample (firstname, lastname)
SELECT DISTINCT firstname, lastname FROM data
...
CTE data
の代わりに、(一時的な)テーブルをデータソースとして使用できます。 。
これを(firstname, lastname)
のUNIQUE制約と組み合わせるのはおそらく理にかなっています。 テーブルとON CONFLICT
クエリの句。
関連:
- PostgreSQLでONCONFLICTを使用してRETURNINGを使用するにはどうすればよいですか?
- 関数内のSELECTまたはINSERTは競合状態になりやすいですか?