PostgreSQL crée la table si elle n'existe pas

dans un script MySQL vous pouvez écrire:

CREATE TABLE IF NOT EXISTS foo ...;

... d'autres trucs ...

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

Comment faites-vous cela dans PostgreSQL?

102
demandé sur Christopher Rapcewicz 2009-11-19 22:48:41

6 réponses

cette fonctionnalité a été implémentée dans Postgres 9.1 :

CREATE TABLE IF NOT EXISTS myschema.mytable (i integer);




Pour anciennes versions , voici une fonction pour travailler autour d'elle:

CREATE OR REPLACE FUNCTION create_mytable ()
  RETURNS void AS
$func$
BEGIN
   IF EXISTS (SELECT 1 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
$func$ LANGUAGE plpgsql;

appel:

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

Notes:

  • le les colonnes schemaname et tablename de pg_tables sont sensibles à la casse. Si vous doublonnez les identificateurs dans la déclaration CREATE TABLE , vous devez utiliser la même orthographe. Si vous ne le faites pas, vous devez utiliser les minuscules cordes. Voir:

  • pg_tables contient seulement les tables . Le l'identificateur peut toujours être occupé par des objets connexes. Voir:

  • si le rôle exécuter cette fonction n'a pas les privilèges nécessaires pour créer la table que vous pourriez vouloir utiliser SECURITY DEFINER pour la fonction et le faire possédé par un autre rôle avec les privilèges nécessaires. Cette version est assez sûre.

157
répondu Erwin Brandstetter 2018-07-18 07:30:07

essayez ceci:

CREATE TABLE IF NOT EXISTS app_user (

  username varchar(45) NOT NULL,  
 password varchar(450) NOT NULL,  
  enabled integer NOT NULL DEFAULT '1',  
  PRIMARY KEY (user_id)  
)
37
répondu Achilles Ram Nakirekanti 2016-02-20 17:29:37

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;

Utilisation:

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

il pourrait être simplifié davantage pour prendre juste un paramètre si on extrairait le nom de table hors 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 le faire - Je ne suis pas encore profondément plpgsql (c'est la première fois que je m'en occupe).

6
répondu ifischer 2013-10-08 13:37:00

il n'y a pas de créer la TABLE si elle n'existe pas... mais vous pouvez écrire une procédure simple pour cela, quelque chose comme:

CREATE OR REPLACE FUNCTION prc_create_sch_foo_table() RETURNS VOID AS $$
BEGIN

EXECUTE 'CREATE TABLE /* IF NOT EXISTS add for PostgreSQL 9.1+ */ sch.foo (
                    id serial NOT NULL, 
                    demo_column varchar NOT NULL, 
                    demo_column2 varchar NOT NULL,
                    CONSTRAINT pk_sch_foo PRIMARY KEY (id));
                   CREATE INDEX /* IF NOT EXISTS add for PostgreSQL 9.5+ */ idx_sch_foo_demo_column ON sch.foo(demo_column);
                   CREATE INDEX /* IF NOT EXISTS add for PostgreSQL 9.5+ */ idx_sch_foo_demo_column2 ON sch.foo(demo_column2);'
               WHERE NOT EXISTS(SELECT * FROM information_schema.tables 
                        WHERE table_schema = 'sch' 
                            AND table_name = 'foo');

         EXCEPTION WHEN null_value_not_allowed THEN
           WHEN duplicate_table THEN
           WHEN others THEN RAISE EXCEPTION '% %', SQLSTATE, SQLERRM;

END; $$ LANGUAGE plpgsql;
2
répondu igilfanov 2017-08-18 08:16:02

cette solution est quelque peu similaire à la réponse D'Erwin Brandstetter, mais n'utilise que le langage sql.

toutes les installations PostgreSQL N'ont pas la langue plpqsql par défaut, cela signifie que vous pouvez devoir appeler CREATE LANGUAGE plpgsql avant de créer la fonction, et ensuite devoir supprimer la langue à nouveau, pour laisser la base de données dans le même état qu'avant (mais seulement si la base de données n'avait pas la langue plpgsql pour commencer). Voir comment la complexité pousse?

ajouter le plpgsql peut ne pas être un problème si vous exécutez votre script localement, cependant, si le script est utilisé pour configurer le schéma chez un client, il peut ne pas être souhaitable de laisser des changements comme celui-ci dans la base de données des clients.

cette solution est inspirée de un billet de 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();
1
répondu zpon 2013-12-18 09:41:31

il n'y a pas de créer la TABLE si elle n'existe pas... mais vous pouvez écrire une procédure simple pour cela, quelque chose comme:

CREATE OR REPLACE FUNCTION execute(TEXT) RETURNS VOID AS $$
BEGIN
  EXECUTE ;
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'
  );
1
répondu Szymon Lipiński 2018-06-25 19:48:10