Voici une version courte et douce utilisant l'instruction "DO":
DO $$
BEGIN
BEGIN
ALTER TABLE <table_name> ADD COLUMN <column_name> <column_type>;
EXCEPTION
WHEN duplicate_column THEN RAISE NOTICE 'column <column_name> already exists in <table_name>.';
END;
END;
$$
Vous ne pouvez pas les passer en tant que paramètres, vous devrez effectuer une substitution de variable dans la chaîne côté client, mais il s'agit d'une requête autonome qui n'émet un message que si la colonne existe déjà, ajoute si ce n'est pas le cas et continuera d'échouer sur d'autres erreurs (comme un type de données invalide).
Je ne recommande aucune de ces méthodes s'il s'agit de chaînes aléatoires provenant de sources externes. Quelle que soit la méthode que vous utilisez (chaînes dynamiques côté clé ou côté serveur exécutées sous forme de requêtes), ce serait une recette pour le désastre car cela vous ouvre aux attaques par injection SQL.
DO $$ BEGIN BEGIN CREATE INDEX type_idx ON table1 USING btree (type); EXCEPTION WHEN duplicate_table THEN RAISE NOTICE 'Index exists.'; END; END;$$;
la même approche dansCREATE INDEX
;) Merci pour votre réponse,DO $$
échoue. J'ai essayéDO $$;
ce qui échoue aussi, jusqu'à ce que je viens de démarrer le bloc avecDO $$DECLARE r record;
lequel est donné un exemple sur les docs dev postgres .END; $$
est une erreur de syntaxe (Postgres 9.3), j'ai dû utiliser à laEND $$;
placeEXCEPTION
) est un peu plus générale et peut être utilisée pour des tâches sansIF NOT EXISTS
syntaxe, par exempleALTER TABLE ... ADD CONSTRAINT
.Avec Postgres 9.6, cela peut être fait en utilisant l'option
if not exists
la source
ADD CONSTRAINT IF NOT EXISTS
encore.Appel:
Retourne
TRUE
en cas de succès, sinonFALSE
(la colonne existe déjà).Déclenche une exception pour un nom de table ou de type non valide.
Pourquoi une autre version?
Cela peut être fait avec une
DO
instruction, mais lesDO
instructions ne peuvent rien renvoyer. Et si c'est pour une utilisation répétée, je créerais une fonction.On utilise les types d'identificateur d'objet
regclass
etregtype
pour ,_tbl
et_type
qui a) empêche contrôles injection SQL et b) la validité de la fois immédiatement ( le moins cher de manière possible). Le nom de la colonne_col
doit encore être nettoyé pourEXECUTE
avecquote_ident()
. Plus d'explications dans cette réponse connexe:format()
nécessite Postgres 9.1+. Pour les anciennes versions concaténer manuellement:Vous pouvez qualifier de schéma le nom de votre table, mais ce n'est pas obligatoire.
Vous pouvez double-citer les identifiants dans l'appel de fonction pour préserver la casse du chameau et les mots réservés (mais vous ne devriez pas utiliser tout cela de toute façon).
Je demande à la
pg_catalog
place du fichierinformation_schema
. Explication détaillée:Les blocs contenant une
EXCEPTION
clause comme la réponse actuellement acceptée sont sensiblement plus lents. C'est généralement plus simple et plus rapide. La documentation:la source
DO
déclaration, une légère modification à accepterDEFAULT
et cela a parfaitement fonctionné!La requête de sélection suivante reviendra
true/false
, en utilisant laEXISTS()
fonction.et utilisez l'instruction SQL dynamique suivante pour modifier votre table
la source
Pour ceux qui utilisent Postgre 9.5+ (je crois que la plupart d'entre vous le font), il existe une solution assez simple et propre
la source
la fonction ci-dessous vérifiera la colonne si elle existe, renvoie le message approprié sinon elle ajoutera la colonne à la table.
la source
C'est essentiellement la solution de sola, mais juste un peu nettoyée. C'est assez différent que je ne voulais pas simplement "améliorer" sa solution (en plus, je pense que c'est grossier).
La principale différence est qu'il utilise le format EXECUTE. Ce qui, je pense, est un peu plus propre, mais je crois que cela signifie que vous devez être sur PostgresSQL 9.1 ou plus récent.
Cela a été testé sur 9.1 et fonctionne. Remarque: Cela générera une erreur si le schéma / nom_table / ou le type_données ne sont pas valides. Cela pourrait "être corrigé", mais pourrait être le comportement correct dans de nombreux cas.
usage:
la source
Peut être ajouté aux scripts de migration, invoquer la fonction et supprimer une fois terminé.
la source
Dans mon cas, pour la manière dont il a été créé, il est un peu difficile pour nos scripts de migration de traverser différents schémas.
Pour contourner ce problème, nous avons utilisé une exception qui vient de capturer et ignorer l'erreur. Cela a également eu le bel effet secondaire d'être beaucoup plus facile à regarder.
Cependant, sachez que les autres solutions ont leurs propres avantages qui l'emportent probablement sur cette solution:
la source
Vous pouvez le faire de la manière suivante.
Donc, il supprimera la colonne si elle existe déjà. Et puis ajoutez la colonne à une table particulière.
la source
Vérifiez simplement si la requête a renvoyé un nom_colonne.
Sinon, exécutez quelque chose comme ceci:
Où vous mettez quelque chose d'utile pour 'x' et 'y' et bien sûr un type de données approprié où j'ai utilisé int.
la source