在一个MySQL脚本中,你可以写:
CREATE TABLE IF NOT EXISTS foo ...;
... 其他的…
然后可以多次运行脚本,而无需重新创建表。
在PostgreSQL中如何做到这一点?
在一个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 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);');
如果要从查询参数中提取表名,可以进一步简化为只取一个参数。我还省略了模式。
没有创建表如果不存在…但是你可以为此写一个简单的过程,比如:
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 9.1中实现了:
CREATE TABLE IF NOT EXISTS myschema.mytable (i integer);
对于旧版本,这里有一个函数来解决它:
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$;
电话:
SELECT create_mytable(); -- call as many times as you want.
笔记
pg_tables中的schemaname和tablename列区分大小写。如果在CREATE TABLE语句中使用双引号标识符,则需要使用完全相同的拼写。如果没有,则需要使用小写字符串。看到的:
PostgreSQL列名区分大小写吗?
Pg_tables只包含实际的表。标识符仍然可能被相关对象占用。看到的:
如何检查一个表是否存在于给定的模式中
如果执行此函数的角色没有创建表的必要特权,则可能需要为该函数使用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 (username)
)
没有创建表如果不存在…但是你可以为此写一个简单的过程,比如:
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'
);