Как создать последовательность, если она не существует - программирование
Подтвердить что ты не робот

Как создать последовательность, если она не существует

Я попытался использовать код из Проверить, существует ли последовательность в Postgres (plpgsql).

Чтобы создать последовательность, если она не существует. Запуск этого кода два раза вызывает исключение:

последовательность... уже существует.

Как создать последовательность только в том случае, если она не существует?

Если последовательность не существует, ни одно сообщение не должно быть записано и не должно возникать ошибки, поэтому я не могу использовать хранимую процедуру в другом ответе на этот вопрос, так как он записывает сообщение в файл журнала каждый раз, если последовательность существует.

do $$
begin

SET search_path = '';
IF not EXISTS (SELECT * FROM pg_class
             WHERE relkind = 'S'
               AND oid::regclass::text = 'firma1.' || quote_ident('myseq'))
  THEN

SET search_path = firma1,public;

create sequence myseq;

END IF;

SET search_path = firma1,public;

end$$;

select nextval('myseq')::int as nr;
4b9b3361

Ответ 1

Postgres 9.5 +

IF NOT EXISTS был добавлен в CREATE SEQUENCE в Postgres 9.5. Это простое решение:

CREATE SEQUENCE IF NOT EXISTS myschema.myseq;

Но рассмотрите детали устаревшего ответа в любом случае...
Знаете ли вы о столбцах serial, правильно?


Postgres 9.4 и старше

Имя последовательности конфликтует с именами объектов нескольких типов, а не только последовательностями. Руководство:

Имя последовательности должно отличаться от имени любого другого , таблица, индекс, представление или внешняя таблица в той же схеме.

Смелый акцент мой.
Итак, у вас есть три случая:

  • Имя не существует. → Создать последовательность.
  • Последовательность с тем же именем существует. → Не делай ничего? Любой выход? Любой журнал?
  • Существует другой конфликтный объект с тем же именем. → Сделайте что-нибудь? Любой выход? Любой журнал?

Вам нужно указать, что вы хотите сделать в любом из этих случаев. Оператор DO может выглядеть следующим образом:

DO
$do$
DECLARE
   _kind "char";
BEGIN
   SELECT relkind
   FROM   pg_class
   WHERE  oid = 'myschema.myseq'::regclass  -- sequence name, optionally schema-qualified
   INTO  _kind;

   IF NOT FOUND THEN       -- name is free
      CREATE SEQUENCE myschema.myseq;
   ELSIF _kind = 'S' THEN  -- sequence exists
      -- do nothing?
   ELSE                    -- object name exists for different kind
      -- do something!
   END IF;
END
$do$;

Типы объектов (relkind) в pg_class в соответствии с руководством:

r = обычная таблица
i = индекс
S = последовательность v = просмотр
m = материализованное представление
c = композитный тип
t = таблица TOAST
f = внешняя таблица

по теме:

Ответ 2

Я пошел другим путем: просто поймайте исключение:

DO
$$
BEGIN
        CREATE SEQUENCE myseq;
EXCEPTION WHEN duplicate_table THEN
        -- do nothing, it already there
END
$$ LANGUAGE plpgsql;

Хорошим преимуществом этого является то, что вам не нужно беспокоиться о том, какова ваша текущая схема.

Ответ 3

Если вам не нужно сохранять потенциально существующую последовательность, вы можете просто отбросить ее, а затем воссоздать ее:

DROP SEQUENCE IF EXISTS id_seq;
CREATE SEQUENCE id_seq;

Ответ 4

Postgres не имеет CREATE SEQUENCE IF NOT EXISTS, и если таблица имеет значение по умолчанию, используя последовательность, если вы просто отбрасываете последовательность, вы можете получить сообщение об ошибке:

ОШИБКА: невозможно удалить последовательность (имя_последовательности), потому что другие объекты зависят от нее Состояние SQL: 2BP01

Для меня это может помочь:

ALTER TABLE <tablename> ALTER COLUMN id DROP DEFAULT;
DROP SEQUENCE IF EXISTS <sequence_name>;
CREATE sequence <sequence_name>;

Ответ 5

Информация о последовательностях может быть получена из information_schema.sequences (ссылка)

Попробуйте что-то вроде этого (untested):

...
IF not EXISTS (SELECT * FROM information_schema.sequences
    WHERE sequence_schema = 'firma1' AND sequence_name = 'myseq') THEN
...

Ответ 6

У меня есть функция для очистки всех таблиц в приложении базы данных в любое время. Он строит динамически, но суть в том, что он удаляет все данные из каждой таблицы и сбрасывает последовательность. Это код для reset последовательности одной из таблиц:

perform relname from pg_statio_all_sequences where relname = 'privileges_id_seq';
if found then
  select setval ('privileges_id_seq',1, false) into i_result;
end if;

Надеюсь, что это поможет,

Loek

Я использую postgres 8.4, я вижу, что вы используете 9.2. Может быть разница в том, где хранится информация.