【PostgreSQL】insertと同時にデフォルト値(シーケンス)を取得する。

まず環境づくり

CREATE SEQUENCE USER_SEQ; 

CREATE TABLE USER_INFO( 
  SEQ INTEGER DEFAULT NEXTVAL('USER_SEQ') PRIMARY KEY
  , NAME CHARACTER VARYING (80)
); 

CREATE TABLE USER_INFO_DETAIL( 
  SEQ INTEGER PRIMARY KEY
  , BIRTH_DAY CHARACTER VARYING (8)
);

文字であらわすとこんな感じ。

  • 主テーブル(USER_INFO)と副テーブル(USER_INFO_DETAIL)の2テーブルが存在する。
  • 両テーブルは主キー(SEQ)で紐づける想定。
  • 主キーはシーケンスで管理しており、主テーブルのデフォルト値として設定されている。

こんなシチュエーション。

要望としてはこんな感じ。

  • 折角デフォルト値が生成されてるんだから、主テーブルのインサートのためにnextvalを取りたくない。
  • 主テーブルにデータを挿入した時に副テーブルにもデータを挿入したいので主キーの値が欲しい。

こんな時はRETURNING句が有効活用できるよう。

http://www.postgresql.jp/document/8.2/html/sql-insert.html

(ドキュメントを漁ったところ、8.2から使える様子?)

INSERT 
INTO USER_INFO(NAME) 
VALUES ('山田 太郎') RETURNING SEQ;

こんなSQLを投げると、データ投入後のSEQの値を返却してくれる。 f:id:negiblog:20160612235444j:plain そうそう、こういうのを探してた。

後は取得したSEQの値をロジックで好きに触って副テーブルに挿入するだけ!

【おまけ】 一本のSQLで同時に更新することも不可能ではない。

WITH UPDATED AS (
INSERT
INTO USER_INFO(NAME)
VALUES ('山田 太郎') RETURNING SEQ
)
INSERT
INTO USER_INFO_DETAIL
VALUES ((SELECT SEQ FROM UPDATED), '20000101');