PostgreSQL функционируют для последнего вставленного идентификатора

В PostgreSQL, как я вставлял последний идентификатор в таблицу?

В MS SQL там является SCOPE_IDENTITY ().

Не советуйте мне использовать что-то вроде этого:

select max(id) from table
297
задан jkdev 3 July 2018 в 22:33
поделиться

4 ответа

( tl;dr : перейдите к варианту 3: INSERT с RETURNING)

Напомним, что в postgresql нет понятия "id" для таблиц, только последовательности (которые обычно, но не обязательно используются как значения по умолчанию для суррогатных первичных ключей, с псевдо-типом SERIAL).

Если вас интересует получение id только что вставленного ряда, есть несколько способов:


Вариант 1: CURRVAL(<имя последовательности>);.

Например:

  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 разработано так, что различные сессии не будут вмешиваться, поэтому нет риска возникновения условий гонки (если другая сессия вставит другой ряд между моим INSERT и моим SELECT, я все равно получу правильное значение).

Однако у них есть тонкая потенциальная проблема. Если в базе данных есть какой-то TRIGGER (или RULE), который при вставке в таблицу persons делает дополнительные вставки в другие таблицы... тогда LASTVAL, вероятно, даст нам неправильное значение. Проблема может возникнуть даже с CURRVAL, если дополнительные вставки делаются в ту же таблицу persons (это случается гораздо реже, но риск все равно существует).


Вариант 3: INSERT с RETURNING

INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John') RETURNING id;

Это самый чистый, эффективный и безопасный способ получения id. У него нет ни одного из рисков предыдущего.

Недостатки? Почти нет: возможно, вам придется изменить способ вызова оператора INSERT (в худшем случае, возможно, ваш API или уровень БД не ожидает, что INSERT вернет значение); это не стандартный SQL (кого это волнует); он доступен с Postgresql 8.2 (Dec 2006...)


Заключение: Если есть возможность, выбирайте вариант 3. В других случаях предпочтите 1.

Примечание: все эти методы бесполезны, если вы хотите получить последний вставленный id глобально (не обязательно по вашей сессии). Для этого вы должны прибегнуть к SELECT max(id) FROM table (конечно, это не позволит прочитать незафиксированные вставки из других транзакций).

И наоборот, вы должны никогда не использовать SELECT max(id) FROM table вместо одного из 3 вариантов выше, чтобы получить id, только что созданный вашим INSERT оператором, потому что (помимо производительности) это небезопасно для одновременной работы: между вашим INSERT и вашим SELECT другая сессия могла вставить другую запись.

556
ответ дан 23 November 2019 в 01:31
поделиться

Смотрите пункт RETURNING оператора INSERT. По сути, INSERT удваивает запрос и возвращает вам значение, которое было вставлено.

73
ответ дан 23 November 2019 в 01:31
поделиться

См. Пример ниже

CREATE TABLE users (
    -- make the "id" column a primary key; this also creates
    -- a UNIQUE constraint and a b+-tree index on the column
    id    SERIAL PRIMARY KEY,
    name  TEXT,
    age   INT4
);

INSERT INTO users (name, age) VALUES ('Mozart', 20);

Затем для получения последнего вставленного идентификатора используйте это для таблицы "пользователь" имя столбца seq "id"

SELECT currval(pg_get_serial_sequence('users', 'id'));
8
ответ дан 23 November 2019 в 01:31
поделиться
SELECT CURRVAL(pg_get_serial_sequence('my_tbl_name','id_col_name'))

Конечно, вам нужно указать имя таблицы и имя столбца.

Это будет для текущего сеанса / соединения. http://www.postgresql.org/docs/8.3/static/functions-sequence.html

7
ответ дан 23 November 2019 в 01:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: