如果不存在,PostgreSQL创建表

时间:2009-11-19 19:48:42

标签: postgresql create-table not-exists database-table

在MySQL脚本中,您可以写:

CREATE TABLE IF NOT EXISTS foo ...;

......其他的东西......

然后您可以多次运行该脚本而无需重新创建表。

你如何在PostgreSQL中做到这一点?

6 个答案:

答案 0 :(得分:188)

此功能已implemented in Postgres 9.1

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



对于旧版本,这是一个解决它的函数:

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;

呼叫:

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

注意:

  • schemaname中的列tablenamepg_tables区分大小写。如果在CREATE TABLE语句中对引号进行双引号,则需要使用完全相同的拼写。如果不这样做,则需要使用小写字符串。参见:

  • pg_tables仅包含实际的。标识符可能仍被相关对象占用。参见:

  • 如果执行此角色的角色没有创建表所需的权限,您可能需要使用SECURITY DEFINER来创建该函数并使其拥有< / em>由另一个具有必要权限的角色。这个版本足够安全。

答案 1 :(得分:48)

试试这个:

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)  
)

答案 2 :(得分:6)

我从现有答案中创建了一个通用解决方案,可以在任何表中重复使用:

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;

用法:

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

如果要从查询参数中提取表名,可以进一步简化为仅使用一个参数。我也遗漏了模式。如果你知道如何做到这一点,请随意扩展我的解决方案 - 我还没有深入到plpgsql(这是我第一次处理它)。

答案 3 :(得分:2)

没有CREATE TABLE IF NOT EXISTS ......但你可以为此编写一个简单的程序,例如:

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;

答案 4 :(得分:1)

没有CREATE TABLE IF NOT EXISTS ......但你可以为此编写一个简单的程序,例如:

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'
  );

答案 5 :(得分:1)

这个解决方案有点类似于Erwin Brandstetter的答案,但只使用sql语言。

默认情况下,并非所有PostgreSQL安装都具有plpqsql语言,这意味着您可能必须在创建函数之前调用CREATE LANGUAGE plpgsql,然后必须再次删除该语言,以使数据库处于与其相同的状态之前(但只有数据库没有开始的plpgsql语言)。看看复杂性如何增长?

如果您在本地运行脚本,则添加plpgsql可能不会成为问题,但是,如果脚本用于在客户处设置架构,则可能不希望在客户数据库中保留此类更改。

此解决方案的灵感来自a post by 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();