Способ ссылки на идентификатор в транзакции с несколькими вставками? (Postgres)

8

Предполагая, что таблица "entity.eid" имеет автоинкремент, я хочу иметь возможность ссылаться на значение автоинкремента, назначенное позже в той же транзакции. То, как я это делал, - это выполнение нескольких транзакций, которые я считаю неоптимальными.

START TRANSACTION;
INSERT INTO entity ...;
INSERT INTO t2 (eid, ...) VALUES (?NEW EID REF HERE?, ...), (...), (...);
COMMIT;
Тони
источник

Ответы:

11

Есть разные способы сделать это.

Самый простой способ - использовать lastval()функцию, которая будет возвращать значение, сгенерированное «последней» последовательностью nextval.

START TRANSACTION;
INSERT INTO entity ...;
INSERT INTO t2 (eid, ...) VALUES (lastval(), ...), (...), (...);
COMMIT;

Если вы знаете имя последовательности для entityтаблицы, вы также можете использовать currvalфункцию:

START TRANSACTION;
INSERT INTO entity ...;
INSERT INTO t2 (eid, ...) VALUES (currval('entity_eid_seq'), ...), (...), (...);
COMMIT;

Это можно записать в более общем виде, используя pg_get_serial_sequence()функцию, избегая жесткого кодирования имени последовательности:

START TRANSACTION;
INSERT INTO entity ...;
INSERT INTO t2 (eid, ...) VALUES (currval(pg_get_serial_sequence('entity', 'eid')), ...), (...);
COMMIT;

Для получения более подробной информации, пожалуйста, обратитесь к руководству: http://www.postgresql.org/docs/current/static/functions-sequence.html

a_horse_with_no_name
источник
7

Вы не указываете свою версию Postgresql, но если вы используете 8.4+, вы можете использовать RETURNINGпредложение для возврата идентификатора (или любого столбца), который только что был вставлен.

Документы: http://www.postgresql.org/docs/current/static/sql-insert.html.

Пример:

INSERT INTO t2 (eid, ...) VALUES (...) RETURNING eid;

Если вы используете Postgresql версии 9.1+, вы также можете использовать WITHпредложения (aka Common Table Expressions) для вставки в одно предложение, а затем ссылаться на значения из RETURNINGпредложения, чтобы выполнить больше действий (предложения WITH могут объединяться в цепочку).

Документы по WITHстатье: http://www.postgresql.org/docs/current/static/queries-with.html

BMA
источник
4

Стоит отметить, что SERIAL в Postgres - это просто INT с SEQUENCE в качестве значения по умолчанию, вы можете легко запросить секвенсор самостоятельно в транзакции, а не вставлять в таблицу, позволяя выполнить значение по умолчанию.

xenoterracide
источник