Tắt tất cả các ràng buộc bảng trong Oracle


95

Làm cách nào để tắt tất cả các ràng buộc bảng trong Oracle chỉ bằng một lệnh? Điều này có thể là cho một bảng, một danh sách các bảng hoặc cho tất cả các bảng.

Câu trả lời:


147

Tốt hơn là tránh ghi ra các tệp ống đệm tạm thời. Sử dụng một khối PL / SQL. Bạn có thể chạy điều này từ SQL * Plus hoặc đưa thứ này vào một gói hoặc thủ tục. Việc tham gia USER_TABLES là có để tránh các hạn chế về chế độ xem.

Không chắc rằng bạn thực sự muốn vô hiệu hóa tất cả các ràng buộc (bao gồm NOT NULL, khóa chính, v.v.). Bạn nên suy nghĩ về việc đặt kiểu_kết_thức trong mệnh đề WHERE.

BEGIN
  FOR c IN
  (SELECT c.owner, c.table_name, c.constraint_name
   FROM user_constraints c, user_tables t
   WHERE c.table_name = t.table_name
   AND c.status = 'ENABLED'
   AND NOT (t.iot_type IS NOT NULL AND c.constraint_type = 'P')
   ORDER BY c.constraint_type DESC)
  LOOP
    dbms_utility.exec_ddl_statement('alter table "' || c.owner || '"."' || c.table_name || '" disable constraint ' || c.constraint_name);
  END LOOP;
END;
/

Việc kích hoạt lại các ràng buộc khó hơn một chút - bạn cần bật các ràng buộc khóa chính trước khi có thể tham chiếu chúng trong một ràng buộc khóa ngoại. Điều này có thể được thực hiện bằng cách sử dụng ORDER BY trên bind_type. 'P' = khóa chính, 'R' = khóa ngoài.

BEGIN
  FOR c IN
  (SELECT c.owner, c.table_name, c.constraint_name
   FROM user_constraints c, user_tables t
   WHERE c.table_name = t.table_name
   AND c.status = 'DISABLED'
   ORDER BY c.constraint_type)
  LOOP
    dbms_utility.exec_ddl_statement('alter table "' || c.owner || '"."' || c.table_name || '" enable constraint ' || c.constraint_name);
  END LOOP;
END;
/

2
Không phải đoạn mã đầu tiên đó sẽ cố gắng vô hiệu hóa khóa chính trước khi vô hiệu hóa khóa ngoại?
David Aldridge 25/09/08

@David Tôi nghĩ rằng tôi đã gặp phải vấn đề này với phân đoạn đầu tiên. Tôi giải quyết nó bằng cách thêm 'DESC' giữa 'ORDER BY c.constraint_type' và đóng cửa ')'
AndreiM

@WW Tôi đánh giá cao. Điều này chỉ giúp tôi tránh gặp rắc rối khi viết một câu lệnh SQL để tạo ra các câu lệnh ràng buộc Bật và Tắt.
dave

1
Không thể tắt khóa chính trên các bảng được tổ chức theo chỉ mục. Bạn có thể xử lý những điều này bằng cách thêm AND NOT (t.iot_type IS NOT NULL AND c.constraint_type = 'P')vào đoạn mã đầu tiên.
Andrew Miller

2
Cảnh báo: nếu bạn đã TẮT các quy tắc chống lại, tất cả các ràng buộc sẽ được kích hoạt bằng thủ tục PL / SQL đó. Bạn phải lọc những điều trái ngược đó về nơi để đảm bảo chúng không bị vô hiệu hóa.
nachouve

11

Để tính các phụ thuộc giữa các ràng buộc:

SET Serveroutput ON
BEGIN
    FOR c IN
    (SELECT c.owner,c.table_name,c.constraint_name
    FROM user_constraints c,user_tables t
    WHERE c.table_name=t.table_name
    AND c.status='ENABLED'
    ORDER BY c.constraint_type DESC,c.last_change DESC
    )
    LOOP
        FOR D IN
        (SELECT P.Table_Name Parent_Table,C1.Table_Name Child_Table,C1.Owner,P.Constraint_Name Parent_Constraint,
            c1.constraint_name Child_Constraint
        FROM user_constraints p
        JOIN user_constraints c1 ON(p.constraint_name=c1.r_constraint_name)
        WHERE(p.constraint_type='P'
        OR p.constraint_type='U')
        AND c1.constraint_type='R'
        AND p.table_name=UPPER(c.table_name)
        )
        LOOP
            dbms_output.put_line('. Disable the constraint ' || d.Child_Constraint ||' (on table '||d.owner || '.' ||
            d.Child_Table || ')') ;
            dbms_utility.exec_ddl_statement('alter table ' || d.owner || '.' ||d.Child_Table || ' disable constraint ' ||
            d.Child_Constraint) ;
        END LOOP;
    END LOOP;
END;
/

5

Đó không phải là một lệnh duy nhất, nhưng đây là cách tôi thực hiện. Tập lệnh sau đã được thiết kế để chạy trong SQL * Plus. Lưu ý, tôi đã cố ý viết điều này để chỉ hoạt động trong lược đồ hiện tại.

set heading off

spool drop_constraints.out

select
    'alter table ' || 
    owner || '.' || 
    table_name || 
    ' disable constraint ' || -- or 'drop' if you want to permanently remove
    constraint_name || ';'
from
    user_constraints;

spool off

set heading on

@drop_constraints.out

Để hạn chế những gì bạn bỏ qua, hãy lọc thêm mệnh đề where vào câu lệnh select: -

  • lọc trên kiểu ràng buộc để chỉ loại bỏ các loại ràng buộc cụ thể
  • lọc trên table_name để thực hiện điều đó chỉ cho một hoặc một vài bảng.

Để chạy trên nhiều giản đồ hiện tại, hãy sửa đổi câu lệnh select để chọn từ all_constraints thay vì user_constraints.

Lưu ý - vì một số lý do, tôi không thể lấy dấu gạch dưới để KHÔNG hoạt động giống như in nghiêng trong đoạn trước. Nếu ai đó biết cách sửa nó, xin vui lòng chỉnh sửa câu trả lời này.


Nếu bạn muốn vô hiệu hóa các ràng buộc thay vì DROPing chúng, chỉ cần chỉnh sửa câu lệnh SELECT ở trên: 'thả ràng buộc' để đọc 'vô hiệu hóa ràng buộc' HTH: o)
Andrew

Vâng, đó là một gợi ý hay - trong tương lai, vui lòng chỉnh sửa bài đăng để thêm thông tin này. Đó là lý do tại sao tôi có các bài đăng của mình dưới dạng wiki cộng đồng có thể chỉnh sửa.
Mike McAllister

5

Sử dụng con trỏ sau để tắt tất cả các ràng buộc .. Và thay đổi truy vấn để kích hoạt các ràng buộc ...

DECLARE

cursor r1 is select * from user_constraints;
cursor r2 is select * from user_tables;

BEGIN
  FOR c1 IN r1
  loop
    for c2 in r2
    loop
       if c1.table_name = c2.table_name and c1.status = 'ENABLED' THEN
        dbms_utility.exec_ddl_statement('alter table ' || c1.owner || '.' || c1.table_name || ' disable constraint ' || c1.constraint_name);
       end if;
    end loop;
  END LOOP;
END;
/

4

Điều này có thể được viết trong PL / SQL khá đơn giản dựa trên chế độ xem hệ thống DBA / ALL / USER_CONSTRAINTS, nhưng các chi tiết khác nhau không hề đơn giản như nó nghe. Bạn phải cẩn thận về thứ tự thực hiện và bạn cũng phải tính đến sự hiện diện của các chỉ mục duy nhất.

Thứ tự quan trọng vì bạn không thể bỏ khóa duy nhất hoặc khóa chính được tham chiếu bởi khóa ngoại và có thể có khóa ngoại trên các bảng trong các lược đồ khác tham chiếu khóa chính của riêng bạn, vì vậy trừ khi bạn có đặc quyền ALTER BẤT KỲ BẢNG nào thì bạn không thể bỏ PKs và UKs. Ngoài ra, bạn không thể chuyển một chỉ mục duy nhất thành một chỉ mục không phải là duy nhất, vì vậy bạn phải loại bỏ nó để loại bỏ ràng buộc (vì lý do này, hầu như luôn tốt hơn nếu triển khai các ràng buộc duy nhất như một ràng buộc "thực" được hỗ trợ bởi một không -chỉ số đồng nhất).


0

Có vẻ như bạn không thể làm điều này với một lệnh duy nhất, nhưng đây là điều gần nhất với nó mà tôi có thể tìm thấy.


0

Đây là một cách khác để tắt các ràng buộc (nó đến từ https://asktom.oracle.com/pls/asktom/f?p=100:11:2402577774283132::::P11_QUESTION_ID:399218963817 )

WITH qry0 AS
       (SELECT    'ALTER TABLE '
               || child_tname
               || ' DISABLE CONSTRAINT '
               || child_cons_name
                 disable_fk
              ,   'ALTER TABLE '
               || parent_tname
               || ' DISABLE CONSTRAINT '
               || parent.parent_cons_name
                 disable_pk
          FROM (SELECT a.table_name child_tname
                      ,a.constraint_name child_cons_name
                      ,b.r_constraint_name parent_cons_name
                      ,LISTAGG ( column_name, ',') WITHIN GROUP (ORDER BY position) child_columns
                  FROM user_cons_columns a
                      ,user_constraints b
                 WHERE a.constraint_name = b.constraint_name AND b.constraint_type = 'R'
                GROUP BY a.table_name, a.constraint_name
                        ,b.r_constraint_name) child
              ,(SELECT a.constraint_name parent_cons_name
                      ,a.table_name parent_tname
                      ,LISTAGG ( column_name, ',') WITHIN GROUP (ORDER BY position) parent_columns
                  FROM user_cons_columns a
                      ,user_constraints b
                 WHERE a.constraint_name = b.constraint_name AND b.constraint_type IN ('P', 'U')
                GROUP BY a.table_name, a.constraint_name) parent
         WHERE child.parent_cons_name = parent.parent_cons_name
           AND (parent.parent_tname LIKE 'V2_%' OR child.child_tname LIKE 'V2_%'))
SELECT DISTINCT disable_pk
  FROM qry0
UNION
SELECT DISTINCT disable_fk
  FROM qry0;

hoạt động như một sự quyến rũ


0

Trong tập lệnh "vô hiệu hóa", thứ tự theo mệnh đề phải là:

ORDER BY c.constraint_type DESC, c.last_change DESC

Mục tiêu của điều khoản này là vô hiệu hóa các ràng buộc theo đúng thứ tự.


0
SELECT 'ALTER TABLE '||substr(c.table_name,1,35)|| 
' DISABLE CONSTRAINT '||constraint_name||' ;' 
FROM user_constraints c, user_tables u 
WHERE c.table_name = u.table_name; 

Câu lệnh này trả về các lệnh tắt tất cả các ràng buộc bao gồm khóa chính, khóa ngoại và các ràng buộc khác.


0

với con trỏ cho vòng lặp (user = 'TRANEE', table = 'D')

declare
    constr all_constraints.constraint_name%TYPE;
begin
    for constr in
        (select constraint_name from all_constraints
        where table_name = 'D'
        and owner = 'TRANEE')
    loop
        execute immediate 'alter table D disable constraint '||constr.constraint_name;
    end loop;
end;
/

(Nếu bạn thay đổi tắt thành bật, bạn có thể bật tất cả các ràng buộc)


0

Bạn có thể thực hiện tất cả các lệnh được trả về bởi truy vấn sau:

chọn 'ALTER TABLE' || substr (c.table_name, 1,35) || 'HIỆU HÓA CONSTRAINT' || tên_chỉ_lệnh || " ; ' từ user_constraints c --where c.table_name = 'TABLE_NAME';

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.