web-dev-qa-db-ja.com

currvalはまだこのセッションで定義されていませんが、マルチセッションシーケンスを取得する方法は?

私の目的は、テーブルに新しい行を挿入するときに主キーフィールドを自動的に挿入することです。

PostgreSQLでセッションからセッションへのシーケンスを取得する方法は?

 doubleemploi@hanbei:/home/yves$ psql -d test
 Mot de passe : 
 psql (8.4.13)
 Saisissez « help » pour l''aide.

 test=> create sequence test001 start 10;
 CREATE SEQUENCE
 test=> select currval('test001');
 ERREUR:  la valeur courante (currval) de la séquence « test00 » n''est pas encore définie dans cette session
 --- current value not yet defined this session (???)
 test=> select setval('test001', 10);
 setval 
 --------
      10
 (1 ligne)

 test=> select currval('test00');
  currval 
 ---------
       10
 (1 ligne)

 test=> \q
 test@hanbei:/home/yves$ psql -d test
 Mot de passe : 
 psql (8.4.13)
 Saisissez « help » pour l''aide.

 test=> select currval('test001');
 ERREUR:  la valeur courante (currval) de la séquence « test00 » n''est pas encore définie dans cette session
26
MUY Belgium

これはあなたが思っているより簡単かもしれません...

私の目的は、テーブルに新しい行を挿入するときに主キーフィールドを自動的に挿入することです。

列のデフォルト値を設定するだけです:

ALTER TABLE tbl ALTER COLUMN tbl_id SET DEFAULT nextval('my_seq'::regclass);

またはもっと簡単に、 serial で始まるテーブルを作成します。

CREATE TABLE tbl(
  tbl_id serial PRIMARY KEY
 ,col1 txt
  -- more columns
);

専用のシーケンスを作成し、tbl_idのデフォルトを自動的に設定します。

こちらです tbl_idは、INSERTで言及されていない場合、添付されたシーケンスから次の値を自動的に割り当てられます。 anyセッション、同時または非同時で動作します。

INSERT INTO tbl(col1) VALUES ('foo');

新しいtbl_id戻って何かをする:

INSERT INTO tbl(col1) VALUES ('foo') RETURNING tbl_id;
15

currvalは、現在のセッション内のシーケンスに対して生成された最後の値を返します。したがって、別のセッションがシーケンスの新しい値を生成した場合でも、エラーを回避して、YOURセッションによって生成された最後の値を取得できます。

ただし、セッションで最後に生成された値を取得するには、上記を使用できます。

SELECT last_value FROM your_sequence_name;

値がコミットされていない(または中止された)トランザクションで他のセッションで使用され、この値を参照として使用すると、エラーが発生する可能性があることに注意してください。通常、人々はcurrvalまたはsetvalの戻りさえ必要とします。

85
MatheusOl

この問題に対する実際的な答えを提供します。データベースサーバーは、プログラムとpsqlターミナルで使用されます。そのため、複数のセッションがあります。現在、私は私のpsqlターミナルにいます:

fooserver=> select currval('fusion_id_seq');
ERROR:  currval of sequence "fusion_id_seq" is not yet defined in this session
fooserver=> select nextval('fusion_id_seq');
 nextval 
---------
  320032
(1 row)

fooserver=> select currval('fusion_id_seq');
 currval 
---------
  320032
(1 row)

自分のセッションでのみ値を表示できるようです。これは、別のセッションの実行にも影響します。これはおそらく、異なるセッションを分離するためのサーバーのマルチスレッド化に関連しています。カウンター(psqlのシリアル)は共有オブジェクトです。私の意見では、このセッションは、カウンターが適切にロックされ、単一のスレッド(セッション)のみがそれをインクリメントできる(アトミック操作)限り、カウンターの現在の値を取得できるはずです。しかし、ここで間違っている可能性があります(データベースサーバーライターの専門家ではありません)。

6
Kemin Zhou

実際にはnextvalはシーケンスを進めて新しい値を返すので、それがあなたの質問に対する答えになります。

currvalは、指定されたシーケンスのnextvalで最後に取得された値を返します(ただし、現在のセッションでnextvalが使用されていない場合は失敗する可能性があります)。

2
Jalal

この問題は断続的に発生しているようです。一貫性を保つために、CTEを使用して現在のセッションの挿入シーケンスを取得してください

WITH挿入AS(INSERT INTO notifn_main(notifn_dt、stat_id)SELECT now()、22 FROM notifn RETURNING id)挿入INTO tmp_idからIDを選択します。

1
Sandeep naik