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

Я работаю над функцией, которая позволяет мне добавить индекс, если он не существует. Я сталкиваюсь с проблемой, что я не могу получить список индексов для сравнения. Любые мысли?

Это аналогичная проблема с созданием столбца, который разрешен с помощью этого кода: https://stackoverflow.com /а /12603892/368511

52 голоса | спросил GuidoS 28 FebruaryEurope/MoscowbThu, 28 Feb 2013 00:39:14 +0400000000amThu, 28 Feb 2013 00:39:14 +040013 2013, 00:39:14

2 ответа


81

Имена индексов в PostgreSQL

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

Если вам неинтересно имя индекса, вы можете указать Postgres авто-имя:

CREATE INDEX ON tbl1 (col1)

(почти) совпадает с

CREATE INDEX tbl1_col1_idx ON tbl1 USING btree (col1);

За исключением того, что Postgres избежит столкновения имен и автоматически выбирает следующее бесплатное имя:

tbl1_col1_idx 
tbl1_col1_idx2
tbl1_col1_idx3
...

Просто попробуй. Но, очевидно, вы бы not хотели создать несколько избыточных индексов. Поэтому было бы неплохо просто слепо создать новый.

Тест на существование

Postgres 9.3 и старше

Очень простой способ проверить - присвоить имя, присвоенное схеме, regclass :

SELECT 'myschema.myname'::regclass

Если он выдает исключение, имя бесплатное.
Или, чтобы проверить одно и то же, не вызывая исключения, используется в DO :

DO $$
BEGIN

IF NOT EXISTS (
    SELECT 1
    FROM   pg_class c
    JOIN   pg_namespace n ON n.oid = c.relnamespace
    WHERE  c.relname = 'my_name'
    AND    n.nspname = 'myschema' -- 'public' by default
    ) THEN

    CREATE INDEX my_name ON myschema.mytable (mycolumn);
END IF;

END$$;

Это не работает для CREATE INDEX CONCURRENTLY, так как этот вариант не может быть заключен во внешнюю транзакцию. См. комментарий от @Gregory ниже.

DO заявление был введен с Postgres 9.0. В более ранних версиях вам необходимо создать функцию , чтобы сделать то же самое .
Подробная информация о pg_class в руководстве .
Основы индексов в руководстве .

Postgres 9.4

Вы можете использовать новую функцию to_regclass(), чтобы проверить, не выбрасывая исключение:

DO $$
BEGIN

IF to_regclass('myschema.my_name') IS NULL THEN
    CREATE INDEX my_name ON myschema.mytable (mycolumn);
END IF;

END$$;

Возвращает NULL, если индекс (или другой объект) этого имени не существует. Подробности:

Postgres 9.5

Теперь доступно:

CREATE INDEX IF NOT EXISTS ...

То, что также работает для CREATE INDEX CONCURRENTLY.

Однако для документации :

  

Обратите внимание, что нет никакой гарантии, что существующий индекс - это что-то   как тот, который был бы создан.

Это обычная проверка имени объекта. Здесь применимы все варианты.

ответил Erwin Brandstetter 28 FebruaryEurope/MoscowbThu, 28 Feb 2013 02:22:44 +0400000000amThu, 28 Feb 2013 02:22:44 +040013 2013, 02:22:44
12

Он будет доступен в 9.5. Вот фактический git commit https://github.com/postgres/postgres/commit/08309aaf74ee879699165ec8a2d53e56f2d2e947

Обсуждение pg хакеров http://postgresql.nabble.com/CREATE-IF -на-EXISTS-ИНДЕКС-td5821173.html

ответил Sergey Mirvoda 9 AMpThu, 09 Apr 2015 10:22:57 +030022Thursday 2015, 10:22:57

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132