Một số vấn đề không theo thứ tự cụ thể.
Trước tiên, trong nội dung của trình kích hoạt cấp hàng, bạn cần sử dụng :new
và :old
để tham khảo các bản ghi mới và cũ. Dấu hai chấm đứng đầu là cần thiết. Vì vậy, WHERE
của bạn mệnh đề cần phải được
WHERE PROJECTID = :new.PROJECTID
Thứ hai, nếu bạn đang chạy CREATE TRIGGER
của mình trong SQL * Plus, bạn có thể nhận được danh sách các lỗi và cảnh báo bằng cách sử dụng SHOW ERRORS
lệnh, tức là
SQL> show errors
Bạn cũng có thể truy vấn DBA_ERRORS
bảng (hoặc ALL_ERRORS
hoặc USER_ERRORS
tùy thuộc vào mức đặc quyền của bạn) nhưng đó không phải là điều bạn thường cần sử dụng.
Thứ ba, giả sử các lỗi cú pháp được sửa, bạn sẽ nhận được một đột biến lỗi bảng
nếu bạn sử dụng logic này. Trình kích hoạt cấp hàng trên bảng A (TPM_TRAININGPLAN
trong trường hợp này) không thể truy vấn bảng A vì bảng có thể ở trạng thái không nhất quán. Bạn có thể giải quyết vấn đề đó, như Tim đã trình bày trong bài viết của anh ấy, bằng cách tạo một gói có tập hợp, khởi tạo tập hợp đó trong trình kích hoạt câu lệnh trước, điền dữ liệu trong tập hợp vào trình kích hoạt cấp hàng và sau đó xử lý các hàng đã sửa đổi trong một kích hoạt câu lệnh sau. Tuy nhiên, đó là một lượng phức tạp đáng kể để thêm vào hệ thống, vì bạn sẽ phải quản lý nhiều đối tượng khác nhau.
Nói chung, tốt hơn hết bạn nên triển khai logic này như một phần của bất kỳ API nào bạn sử dụng để thao tác TPM_TRAININGPLAN
bàn. Nếu đó là một thủ tục được lưu trữ, sẽ có ý nghĩa hơn nhiều nếu đặt logic để cập nhật TPM_PROJECT
trong thủ tục được lưu trữ đó thay vì đặt nó trong một trình kích hoạt. Nổi tiếng là khó khăn khi cố gắng gỡ lỗi một ứng dụng có nhiều logic được nhúng trong các trình kích hoạt vì điều đó khiến các nhà phát triển rất khó theo dõi chính xác các hoạt động đang được thực hiện. Ngoài ra, bạn có thể xóa TRAININGDELIVERYSTART
cột từ TPM_PROJECT
bảng và chỉ cần tính ngày bắt đầu tối thiểu trong thời gian chạy.
Thứ tư, nếu trình kích hoạt của bạn kích hoạt khi chèn, cập nhật và xóa, bạn không thể chỉ tham khảo :new
các giá trị. :new
có giá trị cho các lần chèn và cập nhật nhưng nó sẽ là NULL nếu bạn đang xóa. :old
hợp lệ để xóa và cập nhật nhưng sẽ là NULL nếu bạn đang thực hiện chèn. Điều đó có nghĩa là bạn có thể cần phải có logic dọc theo dòng (tham khảo giải pháp gói của Tim)
BEGIN
IF inserting
THEN
trigger_api.tab1_row_change(p_id => :new.projectid, p_action => 'INSERT');
ELSIF updating
THEN
trigger_api.tab1_row_change(p_id => :new.projectid, p_action => 'UPDATE');
ELSIF deleting
THEN
trigger_api.tab1_row_change(p_id => :old.projectid, p_action => 'DELETE');
END IF;
END;