2013-09-04 4 views
0

Есть ли способ вставить новую запись в таблицу, которая не имеет идентификатора автоматического инкремента, без специального ввода идентификатора. Я просто хочу, чтобы ID был lastId + 1.Вставить в postgres SQL

INSERT INTO lists VALUES (id,'KO','SPH', '5') // новый идентификатор

+5

Таким образом, вы хотите, чтобы поведение было как последовательность («auto-increment»), без использования последовательности. Почему нет? Эти вещи существуют для решения проблем, которые в противном случае вы легко могли бы использовать с параллельными вставками. – deceze

+0

Я просто хочу вставить новую запись, не меняя структуру БД ... – Jacob

+0

Если это исключительный случай, хорошо ... Если это нормальный modus operandi, возможно, вам следует изменить структуру базы данных. – deceze

ответ

5

Не делай этого! EVER! Даже не думайте об этом!

Это НЕПРАВИЛЬНО решение может казаться (не) работать для вас:

INSERT INTO lists VALUES ((SELECT max(id)+1 FROM lists),'KO','SPH', '5'); 

НО, если кто-то попытается вставить в то же время, как вы, вы оба получите то же id, что приведет к недействительному результату. Вы действительно должны использовать sequence или какой-нибудь более надежный механизм (вспомогательная таблица распространена, когда вы не можете иметь отверстия в последовательности, но у нее есть некоторые недостатки [она будет заблокирована]). Вы даже можете использовать serial тип данных, чтобы сделать его проще (он создает последовательность внизу):

CREATE TABLE lists(id serial, col2 text, col3 text, ...); 
-- If you don't specify "id", it will autogenerate for you: 
INSERT INTO lists(col2, col3, ...) VALUES('KO','SPH', ...); 
-- You can also specify using DEFAULT (the same as above): 
INSERT INTO lists(id, col2, col3, ...) VALUES(DEFAULT, 'KO','SPH', ...); 

Если вы действительно, действительно, действительно, не может создавать и использовать последовательность, вы можете сделать, как указано выше, но вам придется обработать исключение (при условии, id поле PK или Великобритании, а также с помощью зафиксированной транзакции чтения), что-то подобное (в PL/PgSQL):

DECLARE 
    inserted bool = false; 
BEGIN 
    WHILE NOT inserted LOOP; 
     BEGIN 
      INSERT INTO lists 
      VALUES ((SELECT coalesce(max(id),0)+1 FROM lists),'KO','SPH', '5'); 
      inserted = true; 
     EXCEPTION 
      WHEN unique_violation THEN 
       NULL; -- do nothing, just try again 
     END; 
    END LOOP; 
END; 

но опять же, я настоятельно рекомендую вам чтобы избежать этого: используйте последовательность и будьте счастливы ... = D

Кроме того, я знаю, что это пример, но используйте список явных столбцов в разделе INSERT INTO.

+0

Что произойдет, если нет данных, и вы делаете max (id) + 1? – maazza

+0

@maazza: тогда 'max' вернет' NULL' (и 'NULL + 1' возвращает' NULL'), вы можете легко справиться с 'COALESCE', я обновлю ответ, чтобы сделать это – MatheusOl

+0

Чтобы быть справедливым , предупреждение довольно мелодраматическое. При условии наличия ключевого ограничения для атрибута id, худшее, что произойдет, это то, что одна из вставок завершится с ошибкой. – beldaz

0

Попробуйте это:

INSERT INTO lists VALUES 
(
    (select coalesce(count(*),0) from lists) + 1, 
    'KO','SPH', '5' 
) 

В качестве альтернативы:

INSERT INTO lists VALUES 
(
    (select coalesce(max(id),0) from lists) + 1, 
    'KO','SPH', '5' 
) 

Если вы хотите не указать ID ваше поле должно быть Autoincrement.

Если вы используете в качестве идентификатора GUID (последовательности) необходимо указать поле, но значение рассчитывается СУБД

+1

Эта вставка приведет к неправильным результатам при одновременном запуске. Последовательность является единственным способом генерации такого идентификатора. –

+0

'select coalesce (count (*), 0) из списков)' это не произвело последний ключ – Jacob

+1

@Jacob: Если вы говорите последний ID + 1, я думаю, что у вас есть идентификатор целого числа, вы можете изменить, insted COUNT use MAX –