2011-11-30 40 views
32

Tôi đã kiểm tra tài liệu do Oracle cung cấp và tìm cách sửa đổi ràng buộc mà không làm rơi bảng. Vấn đề là, nó bị lỗi khi sửa đổi vì nó không nhận ra từ khóa.Cố gắng sửa đổi một ràng buộc trong PostgreSQL

Sử dụng EMS SQL Manager cho PostgreSQL.

Alter table public.public_insurer_credit MODIFY CONSTRAINT public_insurer_credit_fk1 
    deferrable, initially deferred; 

tôi đã có thể làm việc xung quanh nó bằng cách thả các hạn chế sử dụng:

ALTER TABLE "public"."public_insurer_credit" 
    DROP CONSTRAINT "public_insurer_credit_fk1" RESTRICT; 

ALTER TABLE "public"."public_insurer_credit" 
    ADD CONSTRAINT "public_insurer_credit_fk1" FOREIGN KEY ("branch_id", "order_id", "public_insurer_id") 
    REFERENCES "public"."order_public_insurer"("branch_id", "order_id", "public_insurer_id") 
    ON UPDATE CASCADE 
    ON DELETE NO ACTION 
    DEFERRABLE 
    INITIALLY DEFERRED; 
+9

Tại sao bạn kiểm tra tài liệu Oracle (và gắn thẻ câu hỏi này với 'plsql') khi bạn đang sử dụng PostgreSQL? Lỗi chính xác (từ khóa nào không được công nhận)? – Bruno

+0

LRI: lỗi cú pháp tại hoặc gần "MODIFY" LINE 1: Thay đổi bảng công cộng.public_insurer_credit MODIFY CONSTRAINT p ... ^ (0.359 giây) – MISMajorDeveloperAnyways

+7

Kiểm tra tài liệu Oracle cho Postgres và đổ lỗi cho Postgres. Epic. –

Trả lời

23

Theo hướng dẫn đúng (được cung cấp bởi PostgreSQL, không bởi Oracle), không có modify ràng buộc có sẵn trong câu lệnh ALTER TABLE:

Đây là liên kết đến hướng dẫn chính xác:

http://www.postgresql.org/docs/current/static/sql-altertable.html

+0

Cảm ơn bạn đã liên kết đến tài liệu thích hợp. Tôi đã được cung cấp tài liệu Oracle PL/SQL từ DBA của chúng tôi. Số liệu. – MISMajorDeveloperAnyways

+2

Oracle và PL/SQL của Oracle là những thứ hoàn toàn khác nhau. Lý do duy nhất mà họ làm được là vì bạn đang sử dụng * Advanced Server * của EnterpriseDB có hỗ trợ cho PL/SQL của Oracle (và các tính năng tương thích khác của Oracle). Nhưng sau đó họ cần phải cung cấp cho bạn hướng dẫn EnterpriseDB, không phải hướng dẫn sử dụng Oracle –

+1

Bất cứ ai có thể giải thích tại sao câu trả lời này có một downvote? –

52

Không có lệnh ALTER nào cho các ràng buộc trong Postgres. Cách dễ nhất để thực hiện việc này là để thả ràng buộc và thêm lại với các thông số mong muốn. Tất nhiên bất kỳ thay đổi nào của ràng buộc sẽ được chạy với dữ liệu bảng hiện tại.

BEGIN; 
ALTER TABLE t1 DROP CONSTRAINT ... 
ALTER TABLE t1 ADD CONSTRAINT ... 
COMMIT; 
+14

+1 để thực hiện giao dịch. –

+5

Hãy coi chừng: nếu tôi hiểu chính xác, các câu lệnh DDL lấy một khóa AccessExclusive trên bàn, vì vậy nếu các lệnh này mất một thời gian dài, trang web của bạn sẽ bị dừng lại cho đến khi các lệnh hoàn tất. [Trang tài liệu] (http://www.postgresql.org/docs/current/static/sql-altertable.html) có thêm chi tiết, bao gồm cách chỉ định rõ ràng chỉ mục thay vì tạo chỉ mục một cách tự động. –

25

Kể từ phiên bản 9.4, PostgreSQL hỗ trợ ALTER TABLE ... ALTER CONSTRAINT cho khóa ngoài.

Tính năng này sẽ "Allow constraint attributes to be altered, so the default setting of NOT DEFERRABLE can be altered to DEFERRABLE and back." Nhìn vào câu hỏi của bạn, tôi nghĩ đó là (loại) những gì bạn đang tìm kiếm.

Thông tin chi tiết và một ví dụ có thể được tìm thấy ở đây:
http://www.depesz.com/2013/06/30/waiting-for-9-4-alter-table-alter-constraint-for-fks/

+2

http://www.postgresql.org/docs/9.4/static/sql-altertable.html –

+1

Lưu ý rằng tài liệu 9.4 nói 'Hiện tại chỉ có các ràng buộc khoá ngoại có thể bị thay đổi.'! –

+0

@MichaelHerrmann Tôi đã đề cập đến điều này trong câu trả lời của tôi rồi. – mkurz

2

ALTER CONSTRAINT sẽ đòi hỏi biết tên chính nước ngoài, mà không phải lúc nào cũng thuận tiện.

Đây là chức năng, nơi bạn chỉ cần biết tên bảng và cột. Cách sử dụng:

select replace_foreign_key('user_rates_posts', 'post_id', 'ON DELETE CASCADE'); 

Chức năng:

CREATE OR REPLACE FUNCTION 
    replace_foreign_key(f_table VARCHAR, f_column VARCHAR, new_options VARCHAR) 
RETURNS VARCHAR 
AS $$ 
DECLARE constraint_name varchar; 
DECLARE reftable varchar; 
DECLARE refcolumn varchar; 
BEGIN 

SELECT tc.constraint_name, ccu.table_name AS foreign_table_name, ccu.column_name AS foreign_column_name 
FROM 
    information_schema.table_constraints AS tc 
    JOIN information_schema.key_column_usage AS kcu 
     ON tc.constraint_name = kcu.constraint_name 
    JOIN information_schema.constraint_column_usage AS ccu 
     ON ccu.constraint_name = tc.constraint_name 
WHERE constraint_type = 'FOREIGN KEY' 
    AND tc.table_name= f_table AND kcu.column_name= f_column 
INTO constraint_name, reftable, refcolumn; 

EXECUTE 'alter table ' || f_table || ' drop constraint ' || constraint_name || 
', ADD CONSTRAINT ' || constraint_name || ' FOREIGN KEY (' || f_column || ') ' || 
' REFERENCES ' || reftable || '(' || refcolumn || ') ' || new_options || ';'; 

RETURN 'Constraint replaced: ' || constraint_name || ' (' || f_table || '.' || f_column || 
' -> ' || reftable || '.' || refcolumn || '); New options: ' || new_options; 

END; 
$$ LANGUAGE plpgsql; 

Ðể ý: chức năng này sẽ không sao chép thuộc tính của chính nước ngoài đầu tiên. Chỉ lấy tên bảng/tên cột nước ngoài, giảm phím hiện tại và thay thế bằng tên mới.

+0

Giải pháp rất thú vị – tom10271

Các vấn đề liên quan