220 votes

PostgreSQL crée une table s'il n'en existe pas

Dans un script MySQL, vous pouvez écrire:

 CREATE TABLE IF NOT EXISTS foo ...;
 

... d'autres choses ...

et vous pouvez ensuite exécuter le script plusieurs fois sans recréer la table.

Comment faites-vous cela dans PostgreSQL?

351voto

Erwin Brandstetter Points 110228

Cette fonctionnalité a été implémentée dans Postgresql 9.1


Pour les anciennes versions, voici un hack similaire à celui produit par Szymon Guz, mais sans l'inutile étrangeté:

CREATE OR REPLACE FUNCTION create_mytable ()
  RETURNS void AS
$_$
BEGIN

IF EXISTS (
    SELECT *
    FROM   pg_catalog.pg_tables 
    WHERE  schemaname = 'myschema'
    AND    tablename  = 'mytable'
    ) THEN
   RAISE NOTICE 'Table "myschema"."mytable" already exists.';
ELSE
   CREATE TABLE myschema.mytable (i integer);
END IF;

END;
$_$ LANGUAGE plpgsql;

Composez le:

SELECT create_mytable();        -- call as many times as you want. 

Si l'utilisateur n'a pas les privilèges nécessaires pour créer la table que vous souhaitez utiliser SECURITY DEFINER. Cette version est assez sûr.

9voto

ifischer Points 4726

J'ai créé une solution générique à partir des réponses existantes qui peut être réutilisée pour n'importe quelle table:

 CREATE OR REPLACE FUNCTION create_if_not_exists (table_name text, create_stmt text)
RETURNS text AS
$_$
BEGIN

IF EXISTS (
    SELECT *
    FROM   pg_catalog.pg_tables 
    WHERE    tablename  = table_name
    ) THEN
   RETURN 'TABLE ' || '''' || table_name || '''' || ' ALREADY EXISTS';
ELSE
   EXECUTE create_stmt;
   RETURN 'CREATED';
END IF;

END;
$_$ LANGUAGE plpgsql;
 

Usage:

 select create_if_not_exists('my_table', 'CREATE TABLE my_table (id integer NOT NULL);');
 

Il pourrait être simplifié davantage de prendre un seul paramètre si l’on extrayait le nom de la table du paramètre de requête. Aussi j'ai laissé de côté les schémas. N'hésitez pas à étendre ma solution si vous savez comment faire cela - je ne suis pas encore plongé dans les détails de plpgsql (c'est la première fois que je me débrouille avec elle).

5voto

Szymon Guz Points 5357

Il n'y a pas de CREATE TABLE SI PAS EXISTE ... mais vous pouvez écrire une procédure simple pour cela, quelque chose comme:

 CREATE OR REPLACE FUNCTION execute(TEXT) RETURNS VOID AS $$
BEGIN
  EXECUTE $1;
END; $$ LANGUAGE plpgsql;


SELECT 
  execute($$
      CREATE TABLE sch.foo 
      (
        i integer
      )
  $$) 
WHERE 
  NOT exists 
  (
    SELECT * 
    FROM information_schema.tables 
    WHERE table_name = 'foo'
      AND table_schema = 'sch'
  );
 

C'est un peu bizarre, mais peut simplement être

4voto

zpon Points 518

Cette solution est un peu similaire à la réponse par Erwin Brandstetter, mais n'utilise que le langage sql.

Pas toutes les installations PostgreSQL a la plpqsql langue par défaut, cela signifie que vous pouvez avoir à faire appel CREATE LANGUAGE plpgsql avant la création de la fonction, et après avoir enlever la langue à nouveau, pour laisser la base de données dans le même état qu'il était avant (mais seulement si la base de données n'a pas le langage plpgsql pour commencer). Voir la façon dont la complexité augmente?

L'ajout de la plpgsql peut-être pas de problème si vous exécutez votre script localement, cependant, si le script est utilisé pour définir un schéma à un client, il peut être préférable de ne pas laisser de telles modifications dans la base de données clients.

Cette solution est inspirée par un post par Andreas Scherbaum.

-- Function which creates table
CREATE OR REPLACE FUNCTION create_table () RETURNS TEXT AS $$
    CREATE TABLE table_name (
       i int
    );
    SELECT 'extended_recycle_bin created'::TEXT;
    $$
LANGUAGE 'sql';

-- Test if table exists, and if not create it
SELECT CASE WHEN (SELECT true::BOOLEAN
    FROM   pg_catalog.pg_tables 
    WHERE  schemaname = 'public'
    AND    tablename  = 'table_name'
  ) THEN (SELECT 'success'::TEXT)
  ELSE (SELECT create_table())
END;

-- Drop function
DROP FUNCTION create_table();

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X