Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Kích hoạt Oracle sau khi chèn hoặc xóa

Những gì bạn gặp phải là ngoại lệ "bảng đột biến" cổ điển. Trong trình kích hoạt ROW, Oracle không cho phép bạn chạy một truy vấn đối với bảng mà trình kích hoạt được xác định - vì vậy đó là SELECT chống lại TABLE1 trong DELETING một phần của trình kích hoạt gây ra sự cố này.

Có một số cách để giải quyết vấn đề này. Có lẽ tốt nhất trong tình huống này là sử dụng một trình kích hoạt phức hợp, trông giống như sau:

CREATE OR REPLACE TRIGGER TABLE1_NUM_TRG
  FOR INSERT OR DELETE ON TABLE1
COMPOUND TRIGGER
  TYPE NUMBER_TABLE IS TABLE OF NUMBER;
  tblTABLE2_IDS  NUMBER_TABLE;

  BEFORE STATEMENT IS
  BEGIN
    tblTABLE2_IDS := NUMBER_TABLE();
  END BEFORE STATEMENT;

  AFTER EACH ROW IS
  BEGIN
    IF INSERTING THEN
      UPDATE TABLE2 t2
        SET    t2.TABLE2NUM = :new.NUM
        WHERE  t2.ID = :new.TABLE2_ID;
    ELSIF DELETING THEN
      tblTABLE2_IDS.EXTEND;
      tblTABLE2_IDS(tblTABLE2_IDS.LAST) := :new.TABLE2_ID;
    END IF;
  END AFTER EACH ROW;

  AFTER STATEMENT IS
  BEGIN
    IF tblTABLE2_IDS.COUNT > 0 THEN
      FOR i IN tblTABLE2_IDS.FIRST..tblTABLE2_IDS.LAST LOOP
        UPDATE TABLE2 t2
          SET t2.TABLE2NUM = (SELECT NUM
                                FROM (SELECT t1.NUM
                                        FROM TABLE1 t1
                                        WHERE t1.TABLE2_ID = tblTABLE2_IDS(i) 
                                        ORDER BY modification_date DESC)
                                WHERE ROWNUM = 1)
          WHERE t2.ID = tblTABLE2_IDS(i);
      END LOOP;
    END IF;
  END AFTER STATEMENT;
END TABLE1_NUM_TRG;

Một trình kích hoạt kết hợp cho phép mỗi thời điểm (BEFORE STATEMENT , BEFORE ROW , AFTER ROWAFTER STATEMENT ) Được xử lý. Lưu ý rằng các điểm thời gian luôn được gọi theo thứ tự đã cho. Khi một câu lệnh SQL thích hợp (tức là INSERT INTO TABLE1 hoặc DELETE FROM TABLE1 ) được thực thi và trình kích hoạt này được kích hoạt, điểm thời gian đầu tiên được gọi sẽ là BEFORE STATEMENT và mã trong BEFORE STATEMENT trình xử lý sẽ cấp phát một bảng PL / SQL để chứa một loạt các số. Trong trường hợp này, các số được lưu trữ trong bảng PL / SQL sẽ là các giá trị TABLE2_ID từ TABLE1. (Ví dụ:một bảng PL / SQL được sử dụng thay vì một mảng vì một bảng có thể chứa nhiều giá trị khác nhau, trong khi nếu chúng ta sử dụng một mảng, chúng ta phải biết trước số lượng chúng ta cần lưu trữ. Chúng tôi không thể biết trước có bao nhiêu hàng sẽ bị ảnh hưởng bởi một câu lệnh cụ thể, vì vậy chúng tôi sử dụng bảng PL / SQL).

Khi AFTER EACH ROW đã đạt đến điểm thời gian và chúng tôi thấy rằng câu lệnh đang được xử lý là một INSERT, trình kích hoạt chỉ tiếp tục và thực hiện CẬP NHẬT cần thiết cho TABLE2 vì điều này sẽ không gây ra sự cố. Tuy nhiên, nếu một DELETE đang được thực hiện, trình kích hoạt sẽ lưu TABLE1.TABLE2_ID vào bảng PL / SQL được cấp phát trước đó. Khi AFTER STATEMENT Cuối cùng đã đạt đến điểm thời gian, bảng PL / SQL được phân bổ trước đó được lặp lại và đối với mỗi TABLE2_ID, bản cập nhật thích hợp sẽ được thực hiện.

Tài liệu tại đây.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. cx_Oracle và Xử lý ngoại lệ - Các phương pháp hay?

  2. Cách sử dụng Chỉ mục ảo trong Cơ sở dữ liệu Oracle

  3. Tìm tất cả các giá trị không phải dạng số trong một cột trong Oracle

  4. Tôi có nên lập chỉ mục (các) cột khóa chính trong Oracle không

  5. Tích hợp ServiceNow với Oracle Identity Cloud Service (IDCS)