0

我正在尝试创建一些触发器和过程来自动填充我的数据库中的一些表。我有两个表,用户和实用程序。

用户表:

CREATE TABLE USERS ( 
User_id Number(38,0) NOT NULL PRIMARY KEY, 
User_name char(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 , 
Utility_Cost Number(38,0) NULL , 
Running char(4) NULL , 
User_id Number(38,0) NULL , 
);

现在我想在我的数据库中发生什么。

  1. 当一个用户被插入到用户表中时,它会触发一个触发器。
  2. 然后,此触发器将为已创建的用户将一堆实用程序插入到 UTILITIES 表中(User_ID 将与刚刚创建的 User_ID 匹配)。
  3. 将实用程序插入 UTILITIES 表后,我想运行一个过程,该过程将 SUM(Utility_Cost) 在 UTILITIES 表中,并将 SUM 存储在 USER_ID 匹配的 USERS.Memory_Usage 中。

到目前为止我创建的内容:

在 USERS 表上插入后触发触发:

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

从触发器调用的过程:

CREATE OR REPLACE PROCEDURE sum_data
IS
BEGIN
  UPDATE USERS
  SET MEMORY_USAGE = (SELECT SUM(UTILITY_COST) 
                      FROM UTILITIES 
                      WHERE USERS.USER_ID = UTILITIES.USER_ID)
  WHERE USERS.User_id = :new.User_id;
END;

但是,当我尝试插入 USERS 表时,我得到:

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

有谁知道为什么会这样?任何信息将不胜感激。谢谢!

4

2 回答 2

1

您将不得不单独调用该过程并更新表,因为数据仍未提交并且该过程将尝试更新同一个表,它不会工作。除此之外,我已经执行了触发器,它将填充您的实用程序表。

SQL> CREATE TABLE USERS (
  2  User_id Number(38,0) NOT NULL PRIMARY KEY,
  3  User_name char(18) NULL ,
  4  Storage_Size varchar(18) NULL ,
  5  Memory_Usage Number(38,0) NULL
  6  );

Table created.


SQL> CREATE TABLE UTILITIES (
  2  Utility_id Number(38,0) NOT NULL PRIMARY KEY,
  3  Utility_Name varchar(18) NULL ,
  4  Utility_Cost Number(38,0) NULL ,
  5  Running char(4) NULL ,
  6  User_id Number(38,0) NULL
  7  );

Table created.

SQL> CREATE SEQUENCE seq_utility
  2    MINVALUE 1
  3    MAXVALUE 100
  4    START WITH 1
  5    INCREMENT BY 1
  6    CACHE 5;

Sequence created.

SQL> CREATE OR REPLACE PROCEDURE sum_data ( user_id number) is
  2  luser_id number:=user_id;
  3  BEGIN
  4    UPDATE USERS
  5    SET MEMORY_USAGE = (SELECT SUM(UTILITY_COST) FROM UTILITIES WHERE USERS.USER_ID =luser_id);
  6  END;
  7  /

Procedure created.

SQL> CREATE OR REPLACE TRIGGER users_after_insert
  2  AFTER INSERT ON USERS
  3   FOR EACH ROW
  4  BEGIN
  5      INSERT INTO UTILITIES (UTILITY_NAME, RUNNING, USER_ID, UTILITY_ID, UTILITY_COST)
  6      VALUES
  7      ('Javaw.exe', 'YES', :New.USER_ID, seq_utility_id.nextval, round(dbms_random.value(25000, 100000)));
  8     --sum_data(:New.USER_ID);
  9  END;
 10
 11  /

Trigger created.

SQL>  insert into users (user_id,user_name) values (125,'TESTUSER');

1 row created.

SQL> select  * from utilities;

UTILITY_ID UTILITY_NAME       UTILITY_COST RUNN    USER_ID
---------- ------------------ ------------ ---- ----------
         4 Javaw.exe                 68271 YES
         5 Javaw.exe                 62481 YES         124
        10 Javaw.exe                 60727 YES         125

SQL> select * from users;

   USER_ID USER_NAME          STORAGE_SIZE       MEMORY_USAGE
---------- ------------------ ------------------ ------------
       123 TESTUSER
       124 TESTUSER
       125 TESTUSER

编辑

   SQL>  CREATE OR REPLACE TRIGGER users_after_insert
  2         AFTER INSERT ON USERS
  3          FOR EACH ROW
  4         BEGIN
  5             INSERT INTO UTILITIES (UTILITY_NAME, RUNNING, USER_ID, UTILITY_ID, UTILITY_COST)
  6             VALUES
  7             ('Javaw.exe', 'YES', :New.USER_ID, seq_utility_id.nextval, round(dbms_random.value(25000, 100000)));
  8             commit;
  9             sum_data(:New.USER_ID);
 10         END;
 11
 12         /

Trigger created.

SQL>  insert into users (user_id,user_name) values (126,'TESTUSER');
 insert into users (user_id,user_name) values (126,'TESTUSER')
             *
ERROR at line 1:
ORA-04092: cannot COMMIT in a trigger
ORA-06512: at "SCOTT.USERS_AFTER_INSERT", line 5
ORA-04088: error during execution of trigger 'SCOTT.USERS_AFTER_INSERT'


A commit within autonomous pragma transaction:

           SQL> CREATE OR REPLACE TRIGGER users_after_insert
  2         AFTER INSERT ON USERS
  3          FOR EACH ROW
  4             declare
  5             PRAGMA AUTONOMOUS_TRANSACTION;
  6         BEGIN
  7           commit;
  8             INSERT INTO UTILITIES (UTILITY_NAME, RUNNING, USER_ID, UTILITY_ID, UTILITY_COST)
  9             VALUES
 10             ('Javaw.exe', 'YES', :New.USER_ID, seq_utility_id.nextval, round(dbms_random.value(25000, 100000)));
 11                sum_data(:New.USER_ID);
 12         END;
 13
 14         /

Trigger created.

SQL>  insert into users (user_id,user_name) values (126,'TESTUSER');
 insert into users (user_id,user_name) values (126,'TESTUSER')
             *
ERROR at line 1:
ORA-06519: active autonomous transaction detected and rolled back
ORA-06512: at "SCOTT.USERS_AFTER_INSERT", line 9
ORA-04088: error during execution of trigger 'SCOTT.USERS_AFTER_INSERT'

编辑2

    SQL> create view users_views as select a.user_id,a.user_name,SUM(p.UTILITY_COST) as "memory_usage"
  2     from users a,utilities p where a.user_id=p.user_id group by a.user_id,a.user_name;

View created.

SQL> select * from users_views;

   USER_ID USER_NAME          memory_usage
---------- ------------------ ------------
       125 TESTUSER                  60727
       124 TESTUSER                  62481

SQL>
于 2015-04-24T01:56:07.873 回答
0

是的,请阅读突变触发器。您正在尝试更新同时插入的记录,如果您尝试插入多个实用程序,那么它就会变得一团糟。为什么不在表上创建一个包含计算内存使用量的列的视图呢?或者在基于另一个表的用户表上尝试虚拟列(或基于函数的列)。(我没有跨表测试过,所以我不能说它是否有效。)

于 2015-04-24T02:02:06.970 回答