Một vài điểm. Đầu tiên, bạn đang lạm dụng pragma giao dịch tự trị. Nó có nghĩa là cho các giao dịch riêng biệt mà bạn cần cam kết hoặc hoàn trả độc lập với giao dịch chính. Bạn đang sử dụng nó để khôi phục giao dịch chính - và bạn không bao giờ cam kết nếu không có lỗi.
Và những “hậu quả không lường trước được” ai đó đã đề cập? Một trong số đó là số đếm của bạn luôn trả về 0. Vì vậy, hãy loại bỏ cả pragma vì nó đang bị sử dụng sai và do đó số lượng sẽ trả về một giá trị thích hợp.
Một điều khác là không có cam kết hoặc khôi phục trong trình kích hoạt. Đưa ra lỗi và để mã điều khiển làm những gì nó cần làm. Tôi biết sự trở lại là do pragma. Chỉ cần đừng quên xóa chúng khi bạn xóa pragma.
Trình kích hoạt sau phù hợp với tôi:
CREATE OR REPLACE TRIGGER trg_mytable_biu
BEFORE INSERT OR UPDATE ON mytable
FOR EACH ROW
WHEN (NEW.TYPEB = 'Bert') -- Don't even execute unless this is Bert
DECLARE
L_COUNT NUMBER;
BEGIN
SELECT COUNT(*) INTO L_COUNT
FROM MYTABLE
WHERE ARTICLE = :NEW.ARTICLE
AND TYPEB = :NEW.TYPEB;
IF L_COUNT > 0 THEN
RAISE_APPLICATION_ERROR( -20001, 'Bert already exists!' );
ELSIF :NEW.STOCK_COUNT > 1 THEN
RAISE_APPLICATION_ERROR( -20001, 'Can''t insert more than one Bert!' );
END IF;
END;
Tuy nhiên, không phải là ý kiến hay để một trình kích hoạt trên một bảng truy cập riêng vào bảng đó. Thông thường hệ thống thậm chí sẽ không cho phép nó - trình kích hoạt này sẽ không thực thi chút nào nếu được thay đổi thành "after". Nếu nó được phép thực thi, người ta không bao giờ có thể chắc chắn về kết quả thu được - như bạn đã biết. Trên thực tế, tôi hơi ngạc nhiên khi trình kích hoạt ở trên hoạt động. Tôi sẽ cảm thấy không thoải mái khi sử dụng nó trong cơ sở dữ liệu thực.
Tùy chọn tốt nhất khi trình kích hoạt phải truy cập bảng mục tiêu là ẩn bảng sau một khung nhìn và viết một kích hoạt "thay vì" trên khung nhìn. Đó trình kích hoạt có thể truy cập vào bảng tất cả những gì nó muốn.