Всем привет! Понадобилось мне сделать автоинкремент поля и нагуглил я SERIAL. Только вот беда, значение поля увеличивается не на единицу, а на двойку. Т.е. вместо 1;2;3 я получаю 1;3;5. Как быть?
Могу словами описать, ибо код лениво - надо же отлаживать, время и т.д. Скажу только что в одном проекте я это использовал и вполне себе успешно.
В общем есть некая таблица с нужными нам данными, пусть скажем users_tbl вида:
id INTEGER PRIMARY KEY
username VARCHAR(64) UNIQUE
И есть таблица где хранятся номера, скажем numbers_tbl вида:
id INTEGER,
tablename VARCHAR(64),
CONSTRAINT uni_num (id, tablename) UNIQUE
при добавлении записи в таблицу users_tbl должен сработать триггер, который:
1. Получит из таблицы numbers_tbl запись с наименьшим id для таблицы users_tbl
2. Если такая запись есть, возьмёт из этой записи id и использует его при вставке данных в таблицу users_tbl, после чего удалить данную запись из numbers_tbl (разумеется, эти две операции нужно выполнять в транзакции, думаю понятно почему)
3. Если такой записи нет, выполнит запрос для users_tbl с целью получения максимального id в этой таблице, после чего добавит к нему 1 и использует этот id для вставки данных в users_tbl (опять-таки эти два запроса нужно выполнять в транзакци).
при удалении записи из таблицы users_tbl опять должен сработать триггер, который:
Сохранит значение id в таблицу numbers_tbl для последующего использования.
Как-то так в общем.
Для того, чтобы при большом количестве вставок ничего не тормозило, имеет смысл завести ещё одну таблицу, хранящую максимальные значения id для всех таблиц, которые обрабатываются схожим образом. Значения также заносить туда триггером.
Разумеется, если вставок делается в единицу времени много, всё-таки такой механизм будет давать серьёзный ущерб в производительности. Но в этом случае нужно выбирать: либо стройные ряды значений id без пропусков строго через единицу, либо быстродействие - решать вам.
SERIAL не гарантирует вам
SERIAL не гарантирует вам увеличение на единицу и вообще последовательное увеличение номера, тип лишь гарантирует уникальность значения (да и то не всегда). Читайте:
http://postgresql.ru.net/manual/datatype-numeric.html#DATATYPE-SERIAL
Если хотите строгую последовательность - юзайте триггеры и таблицы удалённых номеров.
А можно пример?
А можно пример?
Могу словами описать, ибо код
Могу словами описать, ибо код лениво - надо же отлаживать, время и т.д. Скажу только что в одном проекте я это использовал и вполне себе успешно.
В общем есть некая таблица с нужными нам данными, пусть скажем users_tbl вида:
id INTEGER PRIMARY KEY
username VARCHAR(64) UNIQUE
И есть таблица где хранятся номера, скажем numbers_tbl вида:
id INTEGER,
tablename VARCHAR(64),
CONSTRAINT uni_num (id, tablename) UNIQUE
при добавлении записи в таблицу users_tbl должен сработать триггер, который:
1. Получит из таблицы numbers_tbl запись с наименьшим id для таблицы users_tbl
2. Если такая запись есть, возьмёт из этой записи id и использует его при вставке данных в таблицу users_tbl, после чего удалить данную запись из numbers_tbl (разумеется, эти две операции нужно выполнять в транзакции, думаю понятно почему)
3. Если такой записи нет, выполнит запрос для users_tbl с целью получения максимального id в этой таблице, после чего добавит к нему 1 и использует этот id для вставки данных в users_tbl (опять-таки эти два запроса нужно выполнять в транзакци).
при удалении записи из таблицы users_tbl опять должен сработать триггер, который:
Сохранит значение id в таблицу numbers_tbl для последующего использования.
Как-то так в общем.
Для того, чтобы при большом количестве вставок ничего не тормозило, имеет смысл завести ещё одну таблицу, хранящую максимальные значения id для всех таблиц, которые обрабатываются схожим образом. Значения также заносить туда триггером.
Разумеется, если вставок делается в единицу времени много, всё-таки такой механизм будет давать серьёзный ущерб в производительности. Но в этом случае нужно выбирать: либо стройные ряды значений id без пропусков строго через единицу, либо быстродействие - решать вам.
Я понял, спасибо.
Я понял, спасибо.