Nomes de índice no PostgreSQL
- Os nomes de índice são exclusivos em um único esquema de banco de dados.
- Os nomes de índice não podem ser iguais a qualquer outro índice, tabela (estrangeira), exibição (materializada), sequência ou tipo de composto definido pelo usuário no mesmo esquema.
- Duas tabelas no mesmo esquema não podem ter um índice com o mesmo nome. (Segue logicamente.)
Se você não se importa com o nome do índice, faça com que o Postgres o nomeie automaticamente:
CREATE INDEX ON tbl1 (col1);
é (quase) o mesmo que:
CREATE INDEX tbl1_col1_idx ON tbl1 USING btree (col1);
Exceto que o Postgres evitará colisões de nomes e escolherá automaticamente o próximo nome gratuito:
tbl1_col1_idx
tbl1_col1_idx2
tbl1_col1_idx3
...
Apenas tente. Mas, obviamente, você não gostaria de criar vários índices redundantes. Portanto, não seria uma boa ideia criar apenas uma nova cegamente.
Teste de existência
Postgres 9.3 ou anterior
Uma maneira muito simples de testar é converter o nome qualificado pelo esquema para regclass
:
SELECT 'myschema.myname'::regclass;
Se lançar uma exceção, o nome estará livre.
Ou, para testar o mesmo sem gerar uma exceção, usado em uma DO
instrução:
DO
$$
BEGIN
IF NOT EXISTS (
SELECT
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname = 'mytable_mycolumn_idx'
AND n.nspname = 'myschema'
) THEN
CREATE INDEX mytable_mycolumn_idx ON myschema.mytable (mycolumn);
END IF;
END
$$;
Isso não funciona CREATE INDEX CONCURRENTLY
, pois essa variante não pode ser quebrada em uma transação externa. Veja o comentário de @Gregory abaixo.
A DO
declaração foi introduzida no Postgres 9.0. Nas versões anteriores, você precisa criar uma função para fazer o mesmo.
Detalhes sobre pg_class
no manual .
Noções básicas sobre índices no manual .
Postgres 9.4
Você pode usar a nova função to_regclass()
para verificar sem gerar uma exceção:
DO
$$
BEGIN
IF to_regclass('myschema.mytable_mycolumn_idx') IS NULL THEN
CREATE INDEX mytable_mycolumn_idx ON myschema.mytable (mycolumn);
END IF;
END
$$;
Retorna NULL se um índice (ou outro objeto) com esse nome não existir. Vejo:
Postgres 9.5
Agora disponível:
CREATE INDEX IF NOT EXISTS ...
Isso também funciona para CREATE INDEX CONCURRENTLY IF NOT EXISTS
.
No entanto, o manual adverte :
Observe que não há garantia de que o índice existente seja semelhante ao que teria sido criado.
É uma verificação simples para o nome do objeto. Aplica-se a todas as variantes aqui.