Noms d'index dans PostgreSQL
- Les noms d'index sont uniques dans un schéma de base de données unique.
- Les noms d'index ne peuvent pas être identiques à tout autre index, table (étrangère), vue (matérialisée), séquence ou type composite défini par l'utilisateur dans le même schéma.
- Deux tables dans le même schéma ne peuvent pas avoir un index du même nom. (Suit logiquement.)
Si vous ne vous souciez pas du nom de l'index, demandez à Postgres de le nommer automatiquement:
CREATE INDEX ON tbl1 (col1);
est (presque) identique à:
CREATE INDEX tbl1_col1_idx ON tbl1 USING btree (col1);
Sauf que Postgres évitera les conflits de noms et choisira automatiquement le nom suivant libre:
tbl1_col1_idx
tbl1_col1_idx2
tbl1_col1_idx3
...
Juste l'essayer. Mais, évidemment, vous ne voudriez pas créer plusieurs index redondants. Donc, ce ne serait pas une bonne idée de créer aveuglément un nouveau.
Test d'existence
Postgres 9.3 ou plus ancien
Un moyen très simple de tester consiste à convertir le nom qualifié du schéma en regclass
:
SELECT 'myschema.myname'::regclass;
S'il lève une exception, le nom est libre.
Ou, pour tester le même sans lever une exception, utilisé dans une DO
déclaration:
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
$$;
Cela ne fonctionne pas CREATE INDEX CONCURRENTLY
car cette variante ne peut pas être encapsulée dans une transaction externe. Voir le commentaire de @Gregory ci-dessous.
La DO
déclaration a été introduite avec Postgres 9.0. Dans les versions antérieures, vous devez créer une fonction pour faire de même.
Détails sur pg_class
dans le manuel .
Notions de base sur les index dans le manuel .
Postgres 9.4
Vous pouvez utiliser la nouvelle fonction to_regclass()
pour vérifier sans lever d’exception:
DO
$$
BEGIN
IF to_regclass('myschema.mytable_mycolumn_idx') IS NULL THEN
CREATE INDEX mytable_mycolumn_idx ON myschema.mytable (mycolumn);
END IF;
END
$$;
Renvoie NULL si un index (ou un autre objet) portant ce nom n'existe pas. Voir:
Postgres 9.5
Maintenant disponible:
CREATE INDEX IF NOT EXISTS ...
Cela fonctionne aussi pour CREATE INDEX CONCURRENTLY IF NOT EXISTS
.
Cependant, le manuel met en garde :
Notez qu'il n'y a aucune garantie que l'index existant ressemble à celui qui aurait été créé.
C'est un contrôle simple du nom de l'objet. S'applique à toutes les variantes ici.