SQL使用多个触发器

时间:2015-04-22 21:58:55

标签: sql database oracle triggers

嘿所有我正在创建一个用于管理系统实用程序的数据库。我的数据库有3个表:Users,Utilites和Files(将Files表保留,因为问题不应该影响它)。

TABLES

CREATE TABLE USERS ( 
User_id Number(38,0) NOT NULL PRIMARY KEY, 
User_name char(18) NULL , 
User_pass varchar(18) NULL , 
Storage_Size varchar(18) NULL , 
Memory_Usage Number(38,0) NULL 
);

CREATE TABLE UTILITIES ( 
Utility_id Number(38,0) NOT NULL PRIMARY KEY, 
Utility_Name varchar(18) NULL , 
Cost Number(38,0) NULL , 
Running char(4) NULL , 
User_id Number(38,0) NULL , 
);

TRIGGERS

//触发汇总所有UTILITIES的费用:

CREATE OR REPLACE TRIGGER memory_after_insert 
AFTER INSERT OR UPDATE OR DELETE
    ON UTILITIES
BEGIN
   UPDATE USERS
   SET MEMORY_USAGE = (SELECT SUM(COST) FROM UTILITIES WHERE USERS.USER_ID = UTILITIES.USER_ID);
END;

//触发汇总所有FILES的费用

CREATE OR REPLACE TRIGGER storage_after_insert 
AFTER INSERT OR UPDATE OR DELETE
    ON FILES
BEGIN
  UPDATE USERS
  SET STORAGE_USAGE = (SELECT SUM(FILE_SIZE) FROM FILES WHERE USERS.USER_ID = FILES.USER_ID);
END;

现在我想创建一个触发器,在INSERT中进入USERS(用户创建)将INSERT进入UTILITIES所有系统实用程序(我有X默认实用程序,我希望每个用户都有)

示例触发器我想出了:

CREATE OR REPLACE TRIGGER users_after_insert
  AFTER INSERT ON USERS
  FOR EACH ROW
BEGIN
  INSERT INTO UTILITIES (UTILITY_NAME, RUNNING, USER_ID, UTILITY_ID, COST)
  VALUES
  ('Javaw.exe', 'YES', :new.USER_ID, seq_utility_id.nextval, round(dbms_random.value(25000, 100000)));
  INSERT INTO UTILITIES (UTILITY_NAME, RUNNING, USER_ID, UTILITY_ID, COST)
  VALUES
  ('Firefox.exe', 'YES', :new.USER_ID, seq_utility_id.nextval, round(dbms_random.value(60000, 200000)));
END;

当我在我的数据库中有这个触发器时,它会导致我的其他触发器陷入困境。我收到以下错误:

ORA-04091: table STUDENT052.USERS is mutating, trigger/function may not see it
ORA-06512: at "STUDENT052.MEMORY_AFTER_INSERT", line 2
ORA-04088: error during execution of trigger 'STUDENT052.MEMORY_AFTER_INSERT'
ORA-06512: at "STUDENT052.USERS_AFTER_INSERT", line 2
ORA-04088: error during execution of trigger 'STUDENT052.USERS_AFTER_INSERT'

在添加第三个触发器之前,其他2个触发器工作正常。我认为问题在于此触发器。如果有人知道如何解决这个问题,将不胜感激!谢谢!

2 个答案:

答案 0 :(得分:0)

首先,您的前两个查询存在问题。使用内存使用情况更新USERS表时没有where条件。你应该添加:

WHERE USERS.User_id =:new.User_id;

否则,即使您只想更新单个用户记录,整个表也会被锁定。

CREATE OR REPLACE TRIGGER memory_after_insert 
AFTER INSERT OR UPDATE OR DELETE
    ON UTILITIES
BEGIN
   UPDATE USERS
   SET MEMORY_USAGE = (SELECT SUM(COST) FROM UTILITIES WHERE USERS.USER_ID = UTILITIES.USER_ID) WHERE USERS.User_id = :new.User_id;
END;

我认为您收到错误(users_after_insert)的原因是因为当您为用户插入新的默认实用程序时,您的第一个触发器会相互触发,从而锁定整个USERS表。所以做这个改变应该可以解决你的问题。

答案 1 :(得分:0)

我创建了一个使用2更新语句的过程。您可以看到它是否符合您的需求,创建触发器并将值插入实用程序表。

GC.GetTotalMemory()