Indice de nombres en PostgreSQL
- Los nombres de índice son únicos en un único esquema de base de datos.
- Los nombres de índice no pueden ser los mismos que cualquier otro índice, tabla (extranjera), vista (materializada), secuencia o tipo compuesto definido por el usuario en el mismo esquema.
- Dos tablas en el mismo esquema no pueden tener un índice del mismo nombre. (Sigue lógicamente)
Si no le importa el nombre del índice, haga que Postgres lo nombre automáticamente:
CREATE INDEX ON tbl1 (col1);
es (casi) lo mismo que:
CREATE INDEX tbl1_col1_idx ON tbl1 USING btree (col1);
Excepto que Postgres evitará una colisión de nombres y elegirá automáticamente el siguiente nombre gratis:
tbl1_col1_idx
tbl1_col1_idx2
tbl1_col1_idx3
...
Solo inténtalo. Pero, obviamente, no querrá crear múltiples índices redundantes. Por lo tanto, no sería una buena idea crear a ciegas uno nuevo.
Prueba de existencia
Postgres 9.3 o anterior
Una forma muy simple de probar es emitir el nombre calificado para el esquema a regclass
:
SELECT 'myschema.myname'::regclass;
Si arroja una excepción, el nombre es gratis.
O, para probar lo mismo sin lanzar una excepción, usado en una DO
declaración:
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
$$;
Esto no funciona CREATE INDEX CONCURRENTLY
, ya que esa variante no se puede incluir en una transacción externa. Ver comentario de @Gregory a continuación.
La DO
declaración se introdujo con Postgres 9.0. En versiones anteriores, debe crear una función para hacer lo mismo.
Detalles sobre pg_class
en el manual .
Conceptos básicos sobre los índices en el manual .
Postgres 9.4
Puede usar la nueva función to_regclass()
para verificar sin lanzar una excepción:
DO
$$
BEGIN
IF to_regclass('myschema.mytable_mycolumn_idx') IS NULL THEN
CREATE INDEX mytable_mycolumn_idx ON myschema.mytable (mycolumn);
END IF;
END
$$;
Devuelve NULL si no existe un índice (u otro objeto) de ese nombre. Ver:
Postgres 9.5
Ya disponible:
CREATE INDEX IF NOT EXISTS ...
Eso también funciona para CREATE INDEX CONCURRENTLY IF NOT EXISTS
.
Sin embargo, el manual advierte :
Tenga en cuenta que no hay garantía de que el índice existente sea similar al que se habría creado.
Es una simple verificación del nombre del objeto. Se aplica a todas las variantes aquí.