Tắt kiểm tra khóa ngoại PostgreSQL để di chuyển


82

Tôi đang tạo rất nhiều di chuyển có khóa ngoại trong PostgreSQL 9.4.

Điều này đang gây ra một vấn đề đau đầu vì tất cả các bảng đều phải theo thứ tự chính xác mà các khóa ngoại mong đợi khi chúng được di chuyển. Nó thậm chí còn trở nên khó khăn hơn nếu tôi phải chạy di chuyển từ các gói khác mà di chuyển mới của tôi phụ thuộc vào khóa ngoại.

Trong MySQL, tôi có thể đơn giản hóa việc này bằng cách chỉ cần thêm SET FOREIGN_KEY_CHECKS = 0;vào đầu tệp di chuyển của mình. Làm cách nào để tôi có thể thực hiện việc này tạm thời trong PostgresSQL chỉ với độ dài của mã di chuyển?

BTW, sử dụng Trình tạo lược đồ Laravel cho việc này.

Câu trả lời:


76

PostgreSQL không hỗ trợ bất kỳ tùy chọn cấu hình nào, nhưng có một khả năng khác.

postgres=# \d b
        Table "public.b"
┌────────┬─────────┬───────────┐
│ Column │  Type   │ Modifiers │
╞════════╪═════════╪═══════════╡
│ id     │ integer │           │
└────────┴─────────┴───────────┘
Foreign-key constraints:
    "b_id_fkey" FOREIGN KEY (id) REFERENCES a(id) DEFERRABLE

Tính toàn vẹn của tham chiếu trong Postgres được triển khai bởi trình kích hoạt và bạn có thể tắt trình kích hoạt trên bảng. Với phương pháp này, bạn có thể tải lên bất kỳ dữ liệu nào (rủi ro), nhưng nhanh hơn đáng kể - vì việc kiểm tra dữ liệu lớn rất tốn kém. Và nếu quá trình tải lên của bạn an toàn, thì bạn có thể làm điều đó.

BEGIN;
ALTER TABLE b DISABLE TRIGGER ALL;
-- now the RI over table b is disabled
ALTER TABLE b ENABLE TRIGGER ALL;
COMMIT;

Khả năng tiếp theo là sử dụng các ràng buộc hoãn lại. Kiểm tra ràng buộc di chuyển này để cam kết thời gian. Vì vậy, bạn không nên tôn trọng trật tự với INSERTcác lệnh:

ALTER TABLE b ALTER CONSTRAINT b_id_fkey DEFERRABLE;

BEGIN
postgres=# SET CONSTRAINTS b_id_fkey DEFERRED;
SET CONSTRAINTS
postgres=# INSERT INTO b VALUES(100); -- this is not in a table
INSERT 0 1
postgres=# INSERT INTO b VALUES(10);
INSERT 0 1 
postgres=# COMMIT;
ERROR:  insert or update on table "b" violates foreign key constraint "b_id_fkey"
DETAIL:  Key (id)=(100) is not present in table "a".

Phương pháp này nên được ưu tiên cho bạn, vì dữ liệu được chèn vào sẽ được kiểm tra.


2
Vì một số lý do, điều này có hiệu quả một lần với tôi và sau đó không hề. Tôi đang ở trong các postgres aurora aws, nơi họ khóa super uservai trò để khách hàng không thể làm rối cài đặt sao chép. Có vẻ như tôi phải là một người dùng siêu việt để vô hiệu hóa một số trình kích hoạt hệ thống. (Tôi hiện đang sử dụng tài khoản quản trị viên của mình cũng là chủ sở hữu-- Tôi không chắc tại sao nó hoạt động một lần.) Đặt tùy chọn sao chép cũng không phải là một tùy chọn khả thi, vì điều đó cũng yêu cầu super uservai trò. Lựa chọn duy nhất của tôi dường như được thả và tái tạo các phím nước ngoài ...
ps2goat

Ở đây cũng vậy. Làm DISABLE TRIGGER ALLđiều đó, nhưng nó không có hiệu lực. Tôi thậm chí không nhận được bất kỳ cảnh báo nào. Nó chỉ bị phớt lờ.
jayarjo

Trên Amazon RDS, điều này gây ra lỗi sau:> quyền bị từ chối: "RI_ConstraintTrigger_a_23031" là trình kích hoạt hệ thống, vì vậy, công thức này không dành cho mọi trường hợp, rất tiếc :)
kolypto

147

Đối với quá trình di chuyển, việc tắt tất cả các trình kích hoạt sẽ dễ dàng hơn với:

SET session_replication_role = 'replica';

Và sau khi di chuyển, kích hoạt lại tất cả với

SET session_replication_role = 'origin';

2
Chúa ơi, điều này vừa đơn giản hơn vừa thích hợp hơn cho nhiệm vụ cụ thể trong tầm tay. (Có.)
ijoseph

8
Lời cảnh báo: điều này yêu cầu đặc quyền của người dùng cấp cao. Hãy thử "SET CONSTRAINTS ALL DEFERRED".
JJC

8
Tôi đang ở trên 10.4và câu lệnh ở trên này dường như không hoạt động.
Stephane

2
Liệu ai đó có thể phác thảo những nguy hiểm / rủi ro của phương pháp này và nó nên được sử dụng trong những trường hợp nào và làm thế nào để giảm thiểu rủi ro? Thực hành tốt nhất là gì nếu đây được coi là một thực hành kém?
karns

6
Btw, tham số này có thể được đặt trong AWS RDS trong nhóm tham số cơ sở dữ liệu và được áp dụng mà không cần khởi động lại db! Rất hữu ích nếu bạn đang sử dụng DMS vào một db trống với lược đồ và ràng buộc hiện có được tạo.
Mike Atlas
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.