PostgreSQL创建表(如果不存在)

PostgreSQL创建表(如果不存在),sql,postgresql,ddl,create-table,database-table,Sql,Postgresql,Ddl,Create Table,Database Table,在MySQL脚本中,您可以编写: CREATE TABLE IF NOT EXISTS foo ...; 。。。其他东西 然后可以多次运行脚本,而无需重新创建表 如何在PostgreSQL中执行此操作?如果不存在创建表,则没有创建表。。。但您可以为此编写一个简单的过程,例如: CREATE OR REPLACE FUNCTION execute(TEXT) RETURNS VOID AS $$ BEGIN EXECUTE $1; END; $$ LANGUAGE plpgsql; SE

在MySQL脚本中,您可以编写:

CREATE TABLE IF NOT EXISTS foo ...;
。。。其他东西

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


如何在PostgreSQL中执行此操作?

如果不存在创建表,则没有创建表。。。但您可以为此编写一个简单的过程,例如:

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'
  );
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;
这一特点已得到:



对于旧版本,这里提供了一个解决此问题的功能:

CREATE OR REPLACE FUNCTION create_mytable()
  RETURNS void
  LANGUAGE plpgsql AS
$func$
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
$func$;
电话:

注:

  • pg_tables
    中的
    schemaname
    tablename
    列区分大小写。如果在
    CREATE TABLE
    语句中双引号引用标识符,则需要使用完全相同的拼写。如果没有,则需要使用小写字符串。见:

  • pg_表格
    仅包含实际表格。标识符可能仍被相关对象占用。见:

  • 如果执行此函数的角色没有必要的权限创建您可能希望用于该函数的表,并使其由具有必要权限的其他角色拥有。这个版本足够安全


我从现有答案中创建了一个通用解决方案,可用于任何表格:

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

如果要从查询参数中提取表名,则可以进一步简化为只取一个参数。我还遗漏了模式

此解决方案与Erwin Brandstetter的答案有些相似,但只使用sql语言

默认情况下,并非所有PostgreSQL安装都使用plpqsql语言,这意味着您可能必须在创建函数之前调用
CREATE language plpgsql
,然后再次删除该语言,才能使数据库保持与以前相同的状态(但前提是数据库一开始就没有plpgsql语言)

如果在本地运行脚本,则添加plpgsql可能不是问题,但是,如果脚本用于在客户处设置架构,则可能不希望在客户数据库中保留这样的更改

此解决方案的灵感来自

试试这个:

app\u用户不存在时创建表(
用户名varchar(45)不为空,
密码varchar(450)不为空,
已启用的整数不为空默认值“1”,
主键(用户名)
)

如果不存在CREATE TABLE,则不存在该表……但您可以为此编写一个简单的过程,例如:

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

我被迫使用一个现有的postgres 8.4数据库。这个黑客做了,谢谢你!@Boundless:我看到你的编辑被拒绝为“太小”。我应用了它,因为它不会造成伤害。但是,你应该只执行一次
CREATE函数
。它是
SELECT CREATE\u mytable();
您可能想多次调用。布兰德斯特特:我同意您的看法。我遇到的问题是,我不知道函数是否已创建(就像表可能存在或不存在一样)。因此,我想确保在调用函数之前创建了该函数。这实际上是一个更干净的解决方案。应该进行投票。事实上,我担心有多少涉及“函数”的解决方案。@s我注意到其他解决方案是在Postgres 9.1之前发布的,其中包括
(如果不存在)
选项。不确定这个答案如何影响但由于@erwin brandstetter answer本身是完整的。@comiventor正确,这一个确实表明了参数的用法是正确的。在看到这一个之前,我没有发现这一点。这确实有点帮助。触发器内部并不总是起作用:错误:关系“foo”已经存在即使在plpgsql可用的情况下,您的解决方案也非常棒。它易于扩展,可以在当时不存在的对象上创建视图和函数。例如,来自外部服务器的表视图。您节省了我的时间!谢谢!
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;