Hạn chế
Bạn có thể hỏi danh mục hệ thống pg_database
- có thể truy cập từ bất kỳ cơ sở dữ liệu nào trong cùng một cụm cơ sở dữ liệu. Phần khó là CREATE DATABASE
chỉ có thể được thực thi dưới dạng một câu lệnh duy nhất. Hướng dẫn sử dụng:
CREATE DATABASE
không thể được thực hiện bên trong một khối giao dịch.
Vì vậy, nó không thể được chạy trực tiếp bên trong một hàm hoặc DO
tuyên bố, nơi nó sẽ được ngầm định bên trong một khối giao dịch. Các thủ tục SQL, được giới thiệu với Postgres 11, cũng không thể giúp được việc này.
Cách giải quyết từ bên trong psql
Bạn có thể giải quyết vấn đề này từ bên trong psql bằng cách thực thi câu lệnh DDL có điều kiện:
SELECT 'CREATE DATABASE mydb'
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec
Hướng dẫn sử dụng:
\gexec
Gửi bộ đệm truy vấn hiện tại tới máy chủ, sau đó xử lý mỗi cột của mỗi hàng trong kết quả đầu ra của truy vấn (nếu có) như một câu lệnh SQL sẽ được thực thi.
Cách giải quyết từ shell
Với \gexec
bạn chỉ cần gọi psql một lần :
echo "SELECT 'CREATE DATABASE mydb' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec" | psql
Bạn có thể cần nhiều tùy chọn psql hơn cho kết nối của mình; vai trò, cổng, mật khẩu, ... Xem:
- Chạy tệp hàng loạt bằng lệnh psql mà không cần mật khẩu
Không thể gọi tương tự với psql -c "SELECT ...\gexec"
kể từ \gexec
là một lệnh psql meta ‑ và -c
tùy chọn yêu cầu một lệnh duy nhất mà sách hướng dẫn nêu rõ:
Lệnh
command
phải là một chuỗi lệnh hoàn toàn có thể phân tích cú pháp bởi máy chủ (tức là nó không chứa các tính năng dành riêng cho psql) hoặc một lệnh dấu gạch chéo ngược. Do đó, bạn không thể kết hợp các lệnh meta SQL và psql trong một-c
tùy chọn.
Cách giải quyết từ bên trong giao dịch Postgres
Bạn có thể sử dụng dblink
kết nối trở lại cơ sở dữ liệu hiện tại, chạy bên ngoài khối giao dịch. Do đó, các hiệu ứng cũng có thể không được quay trở lại.
Cài đặt dblink mô-đun bổ sung cho điều này (một lần cho mỗi cơ sở dữ liệu):
- Cách sử dụng (cài đặt) dblink trong PostgreSQL?
Sau đó:
DO
$do$
BEGIN
IF EXISTS (SELECT FROM pg_database WHERE datname = 'mydb') THEN
RAISE NOTICE 'Database already exists'; -- optional
ELSE
PERFORM dblink_exec('dbname=' || current_database() -- current db
, 'CREATE DATABASE mydb');
END IF;
END
$do$;
Một lần nữa, bạn có thể cần nhiều tùy chọn psql hơn cho kết nối. Xem câu trả lời được thêm vào của Ortwin:
- Mô phỏng TẠO CƠ SỞ DỮ LIỆU NẾU KHÔNG TỒN TẠI cho PostgreSQL?
Giải thích chi tiết cho dblink:
- Làm cách nào để thực hiện các cập nhật không chặn lớn trong PostgreSQL?
Bạn có thể đặt chức năng này để sử dụng nhiều lần.