2009-09-14 31 views
9

Trong oracle Tôi có thể chỉ định các cột, mà nên tạo ra một bắn của một cò:Oracle: không bao gồm bản cập nhật của một cột cho bắn một kích hoạt

create or replace trigger my_trigger 
before update of col1, col2, col3 on my_table for each row 
begin 
    // the trigger code will be executed only if col1 or col2 or col3 was updated 
end; 

Bây giờ tôi muốn làm như sau: I don' t muốn kích hoạt để kích hoạt, khi chỉ một cột được cập nhật. Sao có thể như thế được?

Tôi có thể liệt kê tất cả các cột ngoại trừ cột, không nên kích hoạt kích hoạt trình kích hoạt. Điều này khá cồng kềnh đối với các bảng có nhiều cột.

Một cách khác là sử dụng chức năng CẬP NHẬT như thế này:

if not updating('COL3') then ... 

Nhưng nếu tôi thay đổi COL1 COL3 cùng một lúc, báo cáo kết quả ước lượng là false. Đó không phải là những gì tôi muốn kể từ khi, tôi muốn hạn chế thực hiện khi chỉ một cột (COL3) đã được cập nhật.

+0

Sẽ ít cồng kềnh hơn khi liệt kê tất cả các cột sử dụng từ điển dữ liệu. 'SELECT column_name FROM user_tab_columns WHERE table_name = 'MY_TABLE' AND column_name! = 'COL3'; ' –

+0

Điều đó đúng, nhưng ai đó sẽ cần duy trì kích hoạt. Nếu chúng ta sẽ thêm một cột mới hoặc đổi tên nó ... Tôi đã có thể nghe thấy anh ta nói to. Tôi muốn tìm một cách đáng tin cậy với ít đau đớn hơn cho anh ấy và đặc biệt là tôi. ;-) –

Trả lời

11

Bạn có thể làm một cái gì đó như thế này:

create or replace trigger my_trigger 
before update on my_table 
for each row 
declare 
    n_cols integer := 0; 
begin 
    for r in (select column_name from all_tab_columns 
      where table_name = 'MY_TABLE' 
      and owner = 'MY_SCHEMA') 
    loop 
     if updating(r.column_name) then 
     n_cols := n_cols + 1; 
     exit when n_cols > 1; 
     end if; 
    end loop; 
    if n_cols > 1 then 
     do_something; 
    end if; 
end; 

Có lẽ không phải là terribly hiệu quả mặc dù!

0

Tôi không nghĩ rằng có một cách bạn có thể tránh phải liệt kê tất cả các cột khác trong bảng, hoặc trong cơ thể kích hoạt hoặc người nào khác trong mệnh đề before update of ....

Tuy nhiên, bạn có thể viết trình kích hoạt thay đổi trên bảng để tự động kích hoạt trình kích hoạt cập nhật nếu bất kỳ cột nào được thêm hoặc xóa. Đó là một công việc ít hơn một chút, nhưng sau đó bảo trì nên được tự động.

3

Có lẽ đó không phải là câu trả lời bạn muốn nghe, nhưng tôi nghĩ bạn đang quá phóng đại gánh nặng bảo trì. Nó không phải là bình thường đối với cấu trúc của một bảng để thay đổi rất thường xuyên sau khi nó đi vào sản xuất. Nếu bạn có một bảng mà có thể thay đổi thường xuyên của số cột hoặc tên, sau đó tôi sẽ đề nghị bạn có một vấn đề lớn hơn, kiến ​​trúc.

Vì vậy, chỉ cần nhập tất cả các tên cột ngay bây giờ và chờ xem liệu bảo trì có trở thành vấn đề hay không. Đó là chắc chắn không phải là giá trị mã hóa một thực hiện phức tạp trong một kích hoạt - một loại thuế mà bạn sẽ phải trả trên mỗi bản cập nhật duy nhất - để tránh một sự thay đổi không thường xuyên cho kịch bản DDL.

5

Tôi đã gặp vấn đề tương tự ngày hôm qua. Tôi muốn mã một kích hoạt mà bắn trên mọi lĩnh vực ngoại trừ một, bảng có 103 colums.

Trước tiên tôi mã:

if (:OLD.col1<>:NEW.col1 or :OLD.col2<>:NEW.col2 or :OLD.col3<>:NEW.col3 ....) 

Nhưng tôi đã có một số vấn đề với các giá trị null, vì vậy tôi nói thêm:

if (NVL(:OLD.col1,0)<>NVL(:NEW.col1,0) or NVL(:OLD.col2,0)<>NVL(:NEW.col2,0) ....) 

Nhưng sau đó tôi đã có một số vấn đề với cột NGÀY, nó đã trở thành một mớ hỗn độn.

Tôi nghĩ rằng giải pháp tốt nhất là liệt kê tất cả các cột mà bạn muốn xác minh trong "OF":

AFTER INSERT OR UPDATE of cOL1, col2, col3 ... colN ON table1 

Nó không phải là "thanh lịch" nhưng ...nó hoạt động hoàn hảo.

+0

điều này thực sự là thanh lịch nhất của tất cả .. –

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