PostgreSQL: Thực thi DDL trên mọi lược đồ


8

Tôi đã thiết lập DB nhiều bên thuê và cần thêm một số cột. Tôi đang sử dụng các lược đồ (và search_path) để phân vùng người dùng của mình, vì vậy tôi đang tìm kiếm một cách phổ biến để áp dụng thay đổi lược đồ DDL cho tất cả các cơ sở dữ liệu của mình. Ban đầu, tôi nghĩ rằng tôi có thể thực hiện nó như một truy vấn duy nhất (con trỏ trên pg_catalog), nhưng nghĩ rằng một lệnh gọi dòng lệnh psql -fcó thể là cách ưa thích.


@RolandoMySQLDBA: Postgresthay vì PostgreSQLhoàn toàn OK.
a_horse_with_no_name

Câu trả lời:


11

Tôi thích giải pháp sau. Bạn có thể thu thập tên lược đồ thành một tệp (một lược đồ trên mỗi dòng) trong psql:

\o change_schema.sql
\t on

SELECT n.nspname
FROM pg_catalog.pg_namespace n
WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema';

-- reset the output
\o
\t off

Sau đó, bạn có thể dễ dàng làm như sau:

Có tập lệnh thay đổi DDL (ví dụ change_schema.sql:), mà không cần tham chiếu đến lược đồ bao gồm

SET search_path TO :schema;

BEGIN;
...
...
ALTER TABLE orders
ADD COLUMN last_modified timestamp;
...
...
COMMIT;

Sau đó, bạn có thể biến mọi dòng của danh sách lược đồ thành một dòng như

psql -h dbhost -d targetdb -f change_schema.sql -v schema=<schema_name>

với một sedlệnh đơn giản , ví dụ - sau đó bạn chỉ cần chạy các lệnh này. Tất nhiên, bạn có thể biến nó thành một kịch bản shell thích hợp nếu bạn thích.


1
Đây là cách tôi cũng làm điều đó, mặc dù tôi sử dụng shell để lặp qua danh sách lược đồ, thay vì làm dịu nó, vì vậy tôi đã xử lý lỗi tốt hơn. Để hoàn thiện, cách tiếp cận khác sẽ là viết nó dưới dạng thủ tục PL / PGQuery được sử dụng EXECUTEđể chạy các câu lệnh dưới dạng SQL động.
Craig Ringer

9

Để hoàn thiện, một cách tiếp cận khác là lặp qua tất cả các lược đồ và chạy thay đổi với SQL động trong PL / PGQuery, ví dụ:

DO
$$
DECLARE
    schemaname name;
BEGIN
   FOR schemaname IN SELECT nspname FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname <> 'information_schema' LOOP
       EXECUTE format('ALTER TABLE %I.my_table ADD COLUMN blah blah;', schemaname);
   END LOOP;
END;
$$ LANGUAGE plpgsql;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.