PostgreSQL ไม่สนับสนุนIF NOT EXISTS
สำหรับCREATE DATABASE
คำสั่ง รองรับเฉพาะในCREATE SCHEMA
. ยิ่งไปกว่าCREATE DATABASE
นั้นไม่สามารถออกธุรกรรมได้ดังนั้นจึงไม่สามารถDO
ปิดกั้นได้ยกเว้นการจับ
เมื่อCREATE SCHEMA IF NOT EXISTS
มีการออกและมี schema อยู่แล้วให้แจ้ง (ไม่ใช่ข้อผิดพลาด) พร้อมกับข้อมูลวัตถุที่ซ้ำกัน
ในการแก้ปัญหาเหล่านี้คุณต้องใช้dblink
ส่วนขยายซึ่งจะเปิดการเชื่อมต่อใหม่กับเซิร์ฟเวอร์ฐานข้อมูลและดำเนินการสืบค้นโดยไม่ต้องทำธุรกรรม คุณสามารถใช้พารามิเตอร์การเชื่อมต่อซ้ำได้ด้วยการจัดหาสตริงว่าง
ด้านล่างเป็นPL/pgSQL
รหัสซึ่งอย่างเต็มที่จำลองที่มีพฤติกรรมเช่นเดียวกับในCREATE DATABASE IF NOT EXISTS
CREATE SCHEMA IF NOT EXISTS
มันเรียกร้องCREATE DATABASE
ผ่านทางdblink
จับduplicate_database
ข้อยกเว้น (ซึ่งออกเมื่อฐานข้อมูลอยู่แล้ว) errcode
และแปลงเป็นแจ้งให้ทราบล่วงหน้ากับขยายพันธุ์ ข้อความ String ได้ผนวกในทางเดียวกันว่ามันไม่, skipping
CREATE SCHEMA IF NOT EXISTS
CREATE EXTENSION IF NOT EXISTS dblink;
DO $$
BEGIN
PERFORM dblink_exec('', 'CREATE DATABASE testdb');
EXCEPTION WHEN duplicate_database THEN RAISE NOTICE '%, skipping', SQLERRM USING ERRCODE = SQLSTATE;
END
$$;
โซลูชันนี้ไม่มีเงื่อนไขการแย่งชิงเหมือนในคำตอบอื่น ๆ ซึ่งฐานข้อมูลสามารถสร้างขึ้นโดยกระบวนการภายนอก (หรืออินสแตนซ์อื่น ๆ ของสคริปต์เดียวกัน) ระหว่างการตรวจสอบว่ามีฐานข้อมูลอยู่หรือไม่และการสร้างของตนเอง
ยิ่งไปกว่านั้นเมื่อCREATE DATABASE
ล้มเหลวด้วยข้อผิดพลาดอื่นนอกเหนือจากฐานข้อมูลที่มีอยู่แล้วข้อผิดพลาดนี้จะถูกเผยแพร่เป็นข้อผิดพลาดและไม่ถูกละทิ้งโดยไม่โต้ตอบ มีเพียงการจับสำหรับduplicate_database
ข้อผิดพลาด ดังนั้นจึงมีพฤติกรรมตามที่IF NOT EXISTS
ควร
คุณสามารถใส่รหัสนี้ลงในฟังก์ชันของตัวเองเรียกมันโดยตรงหรือจากธุรกรรม เพียงแค่ย้อนกลับ (กู้คืนฐานข้อมูลที่ถูกทิ้ง) จะไม่ทำงาน
ผลลัพธ์การทดสอบ (เรียกว่าสองครั้งผ่าน DO จากนั้นโดยตรง):
$ sudo -u postgres psql
psql (9.6.12)
Type "help" for help.
postgres=# \set ON_ERROR_STOP on
postgres=# \set VERBOSITY verbose
postgres=#
postgres=# CREATE EXTENSION IF NOT EXISTS dblink;
CREATE EXTENSION
postgres=# DO $$
postgres$# BEGIN
postgres$# PERFORM dblink_exec('', 'CREATE DATABASE testdb');
postgres$# EXCEPTION WHEN duplicate_database THEN RAISE NOTICE '%, skipping', SQLERRM USING ERRCODE = SQLSTATE;
postgres$# END
postgres$# $$;
DO
postgres=#
postgres=# CREATE EXTENSION IF NOT EXISTS dblink;
NOTICE: 42710: extension "dblink" already exists, skipping
LOCATION: CreateExtension, extension.c:1539
CREATE EXTENSION
postgres=# DO $$
postgres$# BEGIN
postgres$# PERFORM dblink_exec('', 'CREATE DATABASE testdb');
postgres$# EXCEPTION WHEN duplicate_database THEN RAISE NOTICE '%, skipping', SQLERRM USING ERRCODE = SQLSTATE;
postgres$# END
postgres$# $$;
NOTICE: 42P04: database "testdb" already exists, skipping
LOCATION: exec_stmt_raise, pl_exec.c:3165
DO
postgres=#
postgres=# CREATE DATABASE testdb;
ERROR: 42P04: database "testdb" already exists
LOCATION: createdb, dbcommands.c:467
dblink_connect
และด้วยเหตุนี้ไม่ได้รับอนุญาตให้ใช้งาน