@Rukis

Как в PostgreSQL сделать поле с автоматическим инкриментом по условию?

Когда то уже спрашивал на тостере подобное для mysql: Mysql как сделать поле альтернативной нумерации?

В чем суть, есть таблица с записями, у каждой записи есть id и category и нужно иметь порядковую нумерацию отдельную для каждой категории. То есть, третье поле alt_id в которое должен записываться порядковый номер записи в категории. (чтобы порядок этой нумерации не сбивался при удалении записей, и чтобы можно было всегда получить одним запросом одну запись и ее порядковый номер в категории. Категории у записей не меняются)

Этого можно было бы добиться, например делая перед каждой вставкой запрос
select max(alt_id) from table where category = 'blabla';

увеличивать значение на единицу и писать в таблицу. Но, во первых, после этого запроса может успеть выполнится другой запрос на вставку и счетчик будет неверным, во вторых хотелось бы гарантировать увеличение счетчика на уровне БД.

Для mysql мне предложили использовать триггер. Хотелось бы узнать предоставляет ли PostgreSQL какие нибудь еще возможности для решения этой задачи и какой вариант для него был бы лучшим?
  • Вопрос задан
  • 1017 просмотров
Пригласить эксперта
Ответы на вопрос 2
tsklab
@tsklab
Здесь отвечаю на вопросы.
Но, во первых, после этого запроса может успеть выполнится другой запрос на вставку и счетчик будет неверным
Для этого есть блокировка.
Уточнение: решение прикладной задачи по нумерации.
Ответ написан
@zwerg44
Думаю, для этой задачи, я бы не хранил порядковый номер в отдельной колонке, а рассчитывал бы на лету через оконную функцию.

Как-нибудь так:
WITH tmp AS (
  SELECT
    id,
    name,
    category,
    ROW_NUMBER () OVER (
      PARTITION BY category 
      ORDER BY name, id
    ) AS alt_id
  FROM tablename
)
SELECT *
FROM tmp t
WHERE t.id = 123


Или создал бы VIEW или MATERIALIZED VIEW для подобного селекта.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

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