如果PostgreSQL不存在,则创build表

在MySQL脚本中,你可以这样写:

CREATE TABLE IF NOT EXISTS foo ...; 

… 其他的东西 …

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

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

这个特性已经在Postgres 9.1中实现了 :

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


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

 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. 

如果用户没有创build表的必要权限,则可能需要使用SECURITY DEFINER 。 这个版本足够安全。

尝试这个 :

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

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

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

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

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

这有点奇怪,但可以简单地

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

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

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

这个解决scheme受到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(); 

没有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; 
Interesting Posts