2010-03-01 40 views
7

Tôi cần thực hiện một loạt các câu lệnh sql (lên đến ~ 1000000) trên cơ sở dữ liệu Oracle. Các câu lệnh này sẽ dẫn đến trạng thái nhất quán tham chiếu ở cuối và tất cả các câu lệnh sẽ được cuộn lại nếu xảy ra lỗi. Những phát biểu này không có thứ tự tham chiếu. Vì vậy, nếu các ràng buộc khoá ngoại được kích hoạt, một trong những phát biểu có thể gây ra một sự vi phạm chính ở nước ngoài mặc dù, vi phạm này sẽ được sửa với một tuyên bố sẽ được thực thi sau này.Oracle DDL trong giao dịch tự động

Trước tiên, tôi đã thử vô hiệu hóa khóa ngoại và bật chúng sau khi tất cả các câu lệnh được thực thi. Tôi nghĩ rằng tôi sẽ có thể quay trở lại khi có một sự vi phạm chính ở nước ngoài thực sự. Mặc dù vậy, tôi đã sai, tôi phát hiện ra rằng mọi câu lệnh DDL trong Oracle đều bắt đầu bằng một cam kết, vì vậy không có cách nào để khôi phục các câu lệnh theo cách này. Đây là kịch bản của tôi để vô hiệu hóa các khóa ngoại:

begin 
    for i in (select constraint_name, table_name from user_constraints 
      where constraint_type ='R' and status = 'ENABLED') 
    LOOP execute immediate 'alter table '||i.table_name||' disable constraint 
          '||i.constraint_name||''; 
    end loop; 
end; 

Sau khi nghiên cứu, tôi đã đề xuất thực thi các câu lệnh DDL, như trong trường hợp này, trong giao dịch tự quản. Vì vậy, tôi đã cố gắng chạy các câu lệnh DDL trong một giao dịch tự quản. Điều này dẫn đến các lỗi sau:

ORA-00.054: tài nguyên bận rộn và có được với NOWAIT định

Tôi đoán đây là do giao dịch chính vẫn khóa DDL trên bảng.

Tôi có làm gì sai ở đây không, hoặc có cách nào khác để làm cho kịch bản này hoạt động không?

Trả lời

8

Có một số cách tiếp cận tiềm năng.

Điều đầu tiên cần xem xét là bất cứ điều gì bạn làm ở cấp bảng sẽ áp dụng cho tất cả các phiên sử dụng bảng đó. Nếu bạn không có quyền truy cập độc quyền vào bảng đó, có thể bạn không muốn bỏ/tạo lại các ràng buộc hoặc vô hiệu hóa/bật chúng.

Điều thứ hai cần lưu ý là bạn có thể không muốn ở vị trí quay lại hàng triệu lần chèn/cập nhật. Quay lại có thể là SLOW.

Nói chung tôi sẽ tải vào bảng tạm thời. Sau đó, thực hiện một INSERT đơn lẻ từ bảng tạm thời vào bảng đích. Như một câu lệnh duy nhất, Oracle sẽ áp dụng tất cả các ràng buộc kiểm tra ở cuối.

Nếu bạn không thể đi qua một bảng tạm thời (ví dụ: cập nhật dữ liệu hiện có), trước khi bắt đầu thực hiện các ràng buộc deferrable initially immediate. Sau đó, trong phiên của bạn,

SET CONSTRAINTS emp_job_nn, emp_salary_min DEFERRED; 

Sau đó, bạn có thể áp dụng các thay đổi và khi bạn cam kết, các ràng buộc sẽ được xác thực.

Bạn nên tự làm nổi bật mình bằng DML error logging vì nó có thể giúp xác định mọi hàng gây ra vi phạm.

+0

Tôi vừa phát hiện ra mẹo "SET CONSTRAINTS" và đến đây để trả lời câu hỏi của riêng tôi và tôi đã thấy câu trả lời của bạn :). Cảm ơn bạn. – swamplord

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