Currval еще не был определен этот сеанс, как получить многосеансовые последовательности?
Моя цель - автоматически вводить поле первичного ключа при вставке новой строки в таблицу.
Как получить последовательность, идущую от сеанса к сеансу в PostgreSQL?
[email protected]:/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
[email protected]:/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
Ответы
Ответ 1
Это может быть проще, чем вы думаете...
Моя цель - автоматически вводить поле первичного ключа, когда вставка новой строки в таблицу.
Просто установите значение по умолчанию для столбца:
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;
Ответ 2
currval
вернет последнее значение, сгенерированное для последовательности в текущем сеансе. Поэтому, если другой сеанс генерирует новое значение для последовательности, вы все равно можете получить последнее значение, сгенерированное вашим сеансом, избегая ошибок.
Но чтобы получить последнее сгенерированное значение на любых сеансах, вы можете использовать приведенное выше:
SELECT last_value FROM your_sequence_name;
Будьте осторожны, если это значение использовалось другим сеансом с помощью необоснованной (или прерванной) транзакции, и вы используете это значение в качестве ссылки, вы можете получить сообщение об ошибке. Обычно людям просто нужен currval
или даже возврат setval
.
Ответ 3
Фактически nextval будет продвигать последовательность и возвращать новое значение, так что это будет ответом на ваш вопрос.
currval вернет последнее значение, полученное последним, для указанной последовательности (это может быть неудачно, если в текущем сеансе не было nextval).
Ответ 4
Эта проблема, кажется, прерывистая, для согласованности используйте CTE для вставки последовательности для текущего сеанса
С вставленным AS ( INSERT INTO notifn_main (notifn_dt, stat_id) SELECT now(), 22 FROM notifn RETURNING id) SELECT id из вставленного INTO tmp_id;
Ответ 5
Я дам практический ответ на этот вопрос.
Мой сервер базы данных используется моими программами и моим терминалом 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 другого сеанса. Вероятно, это связано с многопоточным сервером, чтобы изолировать другой сеанс. Счетчик (serial in psql) является общим объектом. На мой взгляд, этот сеанс должен иметь возможность получить текущее значение счетчика, пока счетчик должным образом заблокирован, чтобы гарантировать, что только один поток (сеанс) может увеличивать его (атомная операция). Но я могу ошибаться здесь (не эксперт по созданию сервера баз данных).