回答:
この機能は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 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
とtablename
でpg_tables
は大文字と小文字が区別されます。CREATE TABLE
ステートメントで識別子を二重引用符で囲む場合は、まったく同じスペルを使用する必要があります。そうでない場合は、小文字の文字列を使用する必要があります。見る:
pg_tables
実際のテーブルのみが含まれます。識別子はまだ関連オブジェクトによって占有されている可能性があります。見る:
この関数を実行するロールに、テーブルを作成するために必要な特権がない場合SECURITY DEFINER
、その関数に使用し、必要な特権を持つ別のロールによって所有されるようにすることができます。このバージョンは十分に安全です。
CREATE FUNCTION
一度だけ実行する必要があります。それSELECT create_mytable();
はあなたが何度も電話をかけたいかもしれないということです。
これを試して:
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)
)
IF NOT EXISTS
オプションを含むPostgres 9.1より前に投稿されました。
私は既存の回答から任意のテーブルで再利用できる一般的なソリューションを作成しました:
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);');
クエリパラメータからテーブル名を抽出する場合は、パラメータを1つだけ取るようにさらに簡略化できます。また、スキーマも省略しました。
このソリューションは、Erwin Brandstetterの回答に多少似ていますが、SQL言語のみを使用しています。
すべてのPostgreSQLインストールにデフォルトでplpqsql言語があるわけではありません。つまりCREATE LANGUAGE plpgsql
、関数を作成する前に呼び出す必要があり、その後、言語を再度削除して、データベースを以前と同じ状態のままにする必要があります(ただし、データベースがそもそもplpgsql言語がありませんでした)。複雑さがどのように増大するかをご覧ください。
スクリプトをローカルで実行している場合、plpgsqlの追加は問題にならない可能性がありますが、スクリプトを使用して顧客でスキーマを設定する場合、このような変更を顧客データベースに残しておくことは望ましくない場合があります。
このソリューションは、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;
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'
);