ในสคริปต์ MySQL คุณสามารถเขียน:
CREATE TABLE IF NOT EXISTS foo ...;
... อย่างอื่น ...
และจากนั้นคุณสามารถเรียกใช้สคริปต์ได้หลายครั้งโดยไม่ต้องสร้างตารางขึ้นใหม่
คุณจะทำสิ่งนี้ใน PostgreSQL ได้อย่างไร
ในสคริปต์ MySQL คุณสามารถเขียน:
CREATE TABLE IF NOT EXISTS foo ...;
... อย่างอื่น ...
และจากนั้นคุณสามารถเรียกใช้สคริปต์ได้หลายครั้งโดยไม่ต้องสร้างตารางขึ้นใหม่
คุณจะทำสิ่งนี้ใน PostgreSQL ได้อย่างไร
คำตอบ:
ฟีเจอร์นี้มีการนำมาใช้ใน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
ตัวเลือก
ฉันสร้างโซลูชันทั่วไปจากคำตอบที่มีอยู่ซึ่งสามารถใช้ซ้ำสำหรับตารางใด ๆ :
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);');
มันอาจจะง่ายขึ้นอีกที่จะใช้เพียงหนึ่งพารามิเตอร์ถ้าจะแยกชื่อตารางออกจากพารามิเตอร์แบบสอบถาม นอกจากนี้ฉันออกจาก schemas
โซลูชันนี้ค่อนข้างคล้ายกับคำตอบของ 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 ถ้าไม่มี 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 ถ้าไม่มี 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'
);