последовательность первичного ключа не существует

У меня есть база данных postgresql, и после перехода на более новую версию и импорта моих старых данных у меня возникла проблема с первичным ключом:

org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint   
"browser_link_pkey"  Detail: Key (id)=(173) already exists.

Итак, я хотел сбросить свою последовательность, но запустил:

select nextval('browser_link_id_seq')

Также не работает с:

column „browser_link_id_seq“ does not exist
SQL Status:42703

Это SQL для создания таблицы

CREATE TABLE browser_link (
    id bigint NOT NULL,
....
);
ALTER TABLE ONLY browser_link
ADD CONSTRAINT browser_link_pkey PRIMARY KEY (id);

Я попытался выбрать последовательную последовательность, но похоже, что ее нет:

postgres=# \connect historify
You are now connected to database "historify" as user "postgres".
historify=# select pg_get_serial_sequence('browser_link', 'id');
 pg_get_serial_sequence
------------------------

(1 row)

Я использую postgresql 9.5.3. Кроме того, до тех пор, пока не возникла ошибка, столбец id увеличивался, как и ожидалось, поэтому каким-то образом он работает.

Теперь два моих вопроса:

  1. почему работает автоинкремент?
  2. как сбросить счетчик автоинкремента?

person sveri    schedule 01.07.2016    source источник
comment
Вам нужны одинарные кавычки в select nextval('browser_link_id_seq') Двойные кавычки предназначены для идентификаторов. (имя последовательности в вызове функции может выглядеть как идентификатор, но на самом деле это строковый литерал)   -  person joop    schedule 01.07.2016
comment
Я обновил вопрос, попробовал и то, и другое, ни то, ни другое не работает.   -  person sveri    schedule 01.07.2016
comment
У вас было более одной ошибки. Другая ошибка заключается в том, что последовательность не связана со столбцом id. Вы должны изменить столбец, добавив последовательность как значение / выражение по умолчанию.   -  person joop    schedule 01.07.2016
comment
Я все еще не понимаю, что, если последовательность (какая именно?) Не связана с столбцом, то как уже происходит автоинкремент столбца? Я никогда не создавал последовательность явно? Я предполагаю, что ограничение primary key действительно создает последовательность.   -  person sveri    schedule 01.07.2016


Ответы (1)


Серийные номера в Postgres - это целые числа со значением по умолчанию , предоставленным последовательностью. В следующем фрагменте таблица «один» и таблица «два» в точности эквивалентны:

CREATE TABLE one
( id bigserial NOT NULL PRIMARY KEY
  , name varchar
);

CREATE TABLE two
( id bigint NOT NULL PRIMARY KEY
  , name varchar
);
CREATE SEQUENCE "two_id_seq"
  INCREMENT 1
  MINVALUE 1
  MAXVALUE 9223372036854775807
  START 1
  CACHE 1;

ALTER SEQUENCE "two_id_seq"
        OWNED BY two.id
        ;
ALTER TABLE two
        ALTER COLUMN id SET default nextval('two_id_seq')
        ;

\d one
\d two

Как видите, синтаксис serial для таблицы one намного компактнее (на самом деле это сокращенная запись для 4 операторов, необходимых для таблицы two)

Итак, в вашей проблемной таблице вы можете либо перестроить таблицу, используя bigserial вместо bigint в качестве типа данных, либо «прикрепить» существующий серийный номер к существующему столбцу id с помощью синтаксиса ALTER table ... ALTER COLUMN ....


Вы можете установить для последовательности новое значение с помощью 'setval (' name ', val); `example:

INSERT INTO two(id, name) VALUES ( 13, 'thirteen' );
select nextval('two_id_seq');
SELECT setval ('two_id_seq', (select max(id) FROM two));
select * from two;
select nextval('two_id_seq');

Результат:

INSERT 0 1
 nextval 
---------
       1
(1 row)

 setval 
--------
     13
(1 row)

 id |   name   
----+----------
 13 | thirteen
(1 row)

 nextval 
---------
      14
(1 row)
person joop    schedule 01.07.2016
comment
Спасибо, я сделаю это и воссоздаю таблицу. До сих пор не понимаю, почему это работает уже без последовательности. - person sveri; 01.07.2016