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

5 ответов


это может быть проще, чем вы думаете ...

моя цель - автоматически вставить поле первичного ключа, когда вставка новой строки в таблицу.

просто установите значение по умолчанию столбца:

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. Работает с любой сеанс, параллельный или нет.

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

если вы хотите, чтобы новый tbl_id назад, чтобы сделать что-то с ним:

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

на currval возвращает последнее значение, сгенерированное для последовательности в течение текущей сессии. Поэтому, если другой сеанс генерирует новое значение для последовательности, вы все равно можете получить последнее значение, сгенерированное вашим сеансом, избегая ошибок.

но, чтобы получить последнее сгенерированное значение на любых сеансах, вы можете использовать следующее:

SELECT last_value FROM your_sequence_name;

будьте осторожны, если значение было использовано другим сеансом с незафиксированной (или прерванной) транзакцией и вы используете это значение как справки, вы можете получить сообщение об ошибке. Как правило, людям просто нужно currval или даже вернуть setval.


на самом деле nextval будет продвигать последовательность и возвращать новое значение, так что это будет ответ на ваш вопрос.

currval вернет значение, недавно полученное с nextval для указанной последовательности (это может произойти, если nextval не использовался в текущем сеансе).


эта проблема кажется прерывистой , для согласованности используйте CTE, чтобы получить вставленную последовательность для текущего сеанса

с вставленным как ( Вставить в notifn_main (notifn_dt, stat_id) Выбрать сейчас (), 22 Из notifn Возвращаемый id ) Выберите id из вставленного в tmp_id;


Я даю практический ответ на этот вопрос. Мой сервер базы данных используется моими программами и моим терминалом 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)

похоже, что вы можете видеть значения только в своем собственном сеансе. Это также повлияет на currval другого сеанса. Вероятно, это связано с многопоточностью сервера для изоляции другого сеанса. Счетчик (последовательный в psql) является общим объектом. На мой взгляд, это сеанс должен иметь возможность получить текущее значение счетчика, если счетчик правильно заблокирован, чтобы гарантировать, что только один поток (сеанс) может увеличить его (атомарная операция). Но я могу ошибаться здесь (не эксперт по написанию сервера баз данных).