2012-01-25 24 views
5

Trên cơ sở dữ liệu oracle Tôi có khóa ngoài, không biết tên của nó, chỉ là column_name và reference_column_name. Tôi muốn viết một kịch bản sql mà nên thả chìa khóa nước ngoài này nếu nó tồn tại, vì vậy đây là đoạn code tôi sử dụng:thả chỉ mục hoặc ràng buộc mà không biết tên của nó cho Oracle

declare 
fName varchar2(255 char); 
begin 
SELECT x.constraint_name into fName FROM all_constraints x 
JOIN all_cons_columns c ON 
c.table_name = x.table_name AND c.constraint_name = x.constraint_name 
WHERE x.table_name = 'MY_TABLE_NAME' AND x.constraint_type = 'R' AND c.column_name ='MY_COLUMN_NAME'; 
end; 

Kết quả của kịch bản này là "khối ẩn danh hoàn thành", vì vậy nó đã thành công, nhưng khi tôi thêm phần thả:

declare 
fName varchar2(255 char); 
begin 
SELECT x.constraint_name into fName FROM all_constraints x 
JOIN all_cons_columns c ON 
c.table_name = x.table_name AND c.constraint_name = x.constraint_name 
WHERE x.table_name = 'MY_TABLE_NAME' AND x.constraint_type = 'R' AND c.column_name ='MY_COLUMN_NAME'; 
if (fName != '') THEN 
    alter table MY_TABLE_NAME drop constraint fName; 
end if; 
end; 

Sau đó, tôi có được điều này một:

Error report: ORA-06550: line 9, column 5: PLS-00103: Encountered the symbol "ALTER" when expecting one of the following:

begin case declare exit for goto if loop mod null pragma raise return select update while with << close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe 06550. 00000 - "line %s, column %s:\n%s" *Cause: Usually a PL/SQL compilation error. *Action:

Vì vậy, có thể bất cứ ai cho tôi biết vấn đề là gì đây?

Tôi cũng đã cố gắng để đưa mọi thứ vào một chức năng:

declare 
    function getFName return varchar2 is 
    fName varchar2(255 char); 
    begin 
    SELECT x.constraint_name into fName FROM all_constraints x 
    JOIN all_cons_columns c ON 
    c.table_name = x.table_name AND c.constraint_name = x.constraint_name 
    WHERE x.table_name = 'MY_TABLE_NAME' AND x.constraint_type = 'R' AND c.column_name ='MY_COLUMN_NAME'; 

    return fName; 
    end; 
begin 
    if getFName() != '' then 
    alter table all_events drop constraint getFName(); 
    end if; 
end; 

Kết quả là các lỗi tương tự gây ra bởi tuyên bố "thay đổi bảng"

Cái này cũng không giúp đỡ:

alter table all_events drop constraint 
    (SELECT x.constraint_name into fName FROM all_constraints x 
    JOIN all_cons_columns c ON 
    c.table_name = x.table_name AND c.constraint_name = x.constraint_name 
    WHERE x.table_name = 'MY_TABLE_NAME' AND x.constraint_type = 'R' AND c.column_name ='MY_COLUMN_NAME'); 

Sản lượng là:

Error report: SQL Error: ORA-02250: missing or invalid constraint name 02250. 00000 - "missing or invalid constraint name" *Cause: The constraint name is missing or invalid. *Action: Specify a valid identifier name for the constraint name.

Đối với máy chủ sql (MS SQL), việc này rất dễ dàng. Chỉ cần khai báo một biến với @ và đặt nó, sau đó chỉ cần sử dụng nó. Trên oracle tôi không có bất kỳ đầu mối nào nó không hoạt động ...

Trả lời

6

Phiên bản gốc của bạn là tốt, ngoại trừ việc bạn không thể trực tiếp thực thi DDL trong một khối PL/SQL; đúng hơn, bạn phải bọc nó trong một EXECUTE IMMEDIATE:

execute immediate 'alter table MY_TABLE_NAME drop constraint "' || fName || '"'; 

Đây sẽ là đúng ngay cả khi chế tên tuổi được biết đến tại thời gian biên dịch, nhưng nó gấp đôi đúng trong trường hợp của bạn, vì fName không phải là hạn chế -name, nhưng đúng hơn, một biến chứa tên ràng buộc.

Ngoài ra, đây:

if (fName != '') THEN 

không hợp lệ/có ý nghĩa, vì trong Oracle '' nghĩa NULL. Bạn nên viết

IF fName IS NOT NULL THEN 

thay thế.

+0

Hey chỉ là một câu hỏi thêm về vấn đề này: Với tuyên bố chọn này lý thuyết tôi sẽ nhận được nhiều hơn một tên hạn chế nếu một cột C1 của bảng A1 tham chiếu đến C2 của bảng A2 và C1 tham chiếu đến C3 của bảng A3, vì vậy tôi sẽ nhận được tên cho C1-> C2 và C1-> C3, do đó, câu hỏi là nơi tôi có thể tham gia các thông tin mà cột tôi tham chiếu ??? – radio

+0

@radio: Trên 'all_constraints',' (r_owner, r_constraint_name) 'có hiệu quả là khóa ngoại; bạn có thể tham gia trở lại 'all_constraints' để lấy thông tin về (các) cột được tham chiếu. (Bên trong Oracle, một khóa ngoài được thực hiện như một khóa ngoại để * ràng buộc khác * Điều này có ý nghĩa khi bạn xem xét những gì DBMS cần làm để thực thi ràng buộc khóa ngoài.) – ruakh

+0

@radio: Nhân tiện, mối quan tâm "lý thuyết" của bạn làm tôi lo lắng một chút, bởi vì có những vấn đề lớn hơn với mã của bạn - ví dụ, bạn sử dụng 'all_constraints' và' all_cons_columns' mà không kiểm tra 'chủ sở hữu' và bạn không kiểm tra để đảm bảo rằng ''MY_COLUMN_NAME'' là cột duy nhất trong khóa ngoại. Vì vậy, bit của bạn của mã không phải là mục đích chung. Tôi đã giả định rằng bạn dự định sử dụng nó trong một hoàn cảnh cụ thể mà bạn có rất nhiều thông tin khác, nhưng chỉ đơn thuần là thiếu tên hạn chế vì một lý do nào đó. Nếu bạn cần mã có mục đích chung, bạn có rất nhiều thứ cần sửa. – ruakh

2

Đây là làm thế nào để vứt bỏ mọi trở ngại gõ "R" cho một cột:

begin 
    FOR rec IN (SELECT x.constraint_name fName FROM all_constraints x 
     JOIN all_cons_columns c ON 
     c.table_name = x.table_name AND c.constraint_name = x.constraint_name 
     WHERE x.table_name = 'MY_TABLE_NAME' AND x.constraint_type = 'R' AND c.column_name ='MY_COLUMN_NAME') 
    LOOP 
     EXECUTE IMMEDIATE 'ALTER TABLE MY_TABLE_NAME DROP CONSTRAINT "' || rec.fName || '"'; 
    END LOOP; 
end; 
Các vấn đề liên quan