[解決済み】最後に挿入されたIDを取得するPostgreSQL関数
質問
PostgreSQLで、あるテーブルに最後に挿入されたidを取得するにはどうすればよいですか?
MS SQL では、SCOPE_IDENTITY() があります。
このようなものを使うようにアドバイスしないでください。
select max(id) from table
解決方法は?
(
tl;dr
オプション3:RETURNINGを使用したINSERT )
Postgresqlでは、テーブルにquot;id"という概念はなく、単に シーケンス (これは通常、代理の主キーのデフォルト値として使われますが、必ずしもそうとは限りません。 シリアル 擬似型)。
新しく挿入された行のIDを取得することに興味がある場合、いくつかの方法があります。
オプション1:
CURRVAL(<sequence name>);
.
例えば
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
SELECT currval('persons_id_seq');
シーケンスの名前を知っていなければなりませんが、それは本当に任意のものです。この例では、テーブル
persons
には
id
カラムを作成します。
SERIAL
という擬似型があります。これに頼らず、よりすっきりさせるためには、代わりに
pg_get_serial_sequence
:
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
SELECT currval(pg_get_serial_sequence('persons','id'));
警告
currval()
の後にしか機能しません。
INSERT
(を実行した)。
nextval()
),
同じセッションで
.
オプション 2:
LASTVAL();
これは先ほどと似ていますが、シーケンス名を指定する必要がないのが特徴です。これは、最も新しく変更されたシーケンスを探します(常にセッション内にあります。)
両方
CURRVAL
と
LASTVAL
は完全にコンカレントセーフです。PGにおけるシーケンスの動作は、異なるセッションが干渉しないように設計されており、競合状態に陥る危険性はありません。
しかし
には、微妙に潜在的な問題があります。もし、データベースが何らかの
トリガー
(またはRULE)に挿入すると
persons
テーブルで、他のテーブルへの追加挿入が行われる...すると
LASTVAL
は、おそらく間違った値を与えるでしょう。この問題は
CURRVAL
への追加挿入が行われる場合、同じ
persons
テーブルを作成する必要があります(これはあまり一般的ではありませんが、リスクは依然として存在します)。
オプション 3:
INSERT
と
RETURNING
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John') RETURNING id;
これは、idを取得するための最もクリーンで効率的かつ安全な方法です。以前のようなリスクは一切ありません。
欠点は?INSERT文を呼び出す方法を修正する必要があるかもしれない(最悪の場合、おそらくあなたのAPIやDB層はINSERTが値を返すことを期待していない)、標準SQLではない(誰が気にする)、Postgresql 8.2 (Dec 2006...) から利用できる。
結論 可能であれば、オプション3を選択する。それ以外の場合は、1がいい。
注意:これらの方法は、もしあなたが
最後に挿入されたidがグローバルに
(必ずしもセッションごとでなくとも)。そのためには
SELECT max(id) FROM table
(もちろん、これは他のトランザクションからのコミットされていない挿入を読み取ることはできません)。
逆に
決して
使用
SELECT max(id) FROM table
の代わりに、上記の3つのオプションのいずれかを使用することです。
INSERT
ステートメントを使用する場合、(パフォーマンスとは別に)これはコンカレントセーフではないためです:あなたの
INSERT
と
SELECT
別のセッションで別のレコードが挿入されている可能性があります。
関連
-
[解決済み] psql: FATAL: データベース "<user>" が存在しない
-
[解決済み] PostgreSQLの場合。PostgreSQLのテーブルを表示する
-
[解決済み] PostgreSQLの "DESCRIBE TABLE"
-
[解決済み] PostgreSQL コマンドラインユーティリティ: psql を終了する方法
-
[解決済み] 各GROUP BYグループの最初の行を選択しますか?
-
[解決済み] PostgreSQLで重複して更新された場合の挿入?
-
[解決済み] コマンドライン引数でPostgreSQLの.sqlファイルを実行する
-
[解決済み] PostgreSQLデータベースへのSQLダンプのインポート
-
[解決済み] PostgreSQL で "use database_name" コマンドを使用する。
-
[解決済み】Mac OS XでPostgreSQLサーバーを起動するには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] ポストグレス \コピー構文
-
[解決済み] Rails 4でPostgreSQLサーバーのデフォルトのユーザー名/パスワードは何ですか?
-
[解決済み] Psql はサーバーに接続できませんでした。そのようなファイルまたはディレクトリがありません、5432エラー?
-
[解決済み] postgresqlのポートの混乱 5433 or 5432?
-
[解決済み] libpqのソースはどこで手に入りますか?
-
[解決済み】PostgreSQLで読み取り専用ユーザーを作成する方法は?
-
[解決済み】コマンドラインを使ってpostgresのバックアップファイルをリストアする?
-
[解決済み】最後に挿入されたIDを取得するPostgreSQL関数
-
[解決済み】PostgreSQLでタイムゾーンがある場合とない場合のタイムスタンプの違いについて
-
[解決済み】PostgreSQLでUPSERT(MERGE、INSERT ... ON DUPLICATE UPDATE)する方法とは?