2015-04-24 4 views
0

Я пытаюсь создать несколько триггеров и процедур для автоматического заполнения некоторых таблиц в моей базе данных. У меня две таблицы, «Пользователи» и «Утилиты».SQL с использованием процедур вместе с триггерами

Пользователи Таблица:

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 в USERS.Memory_Usage ГДЕ ИМЯ USER_ID.

То, что я создал до сих пор:

Trigger стрелять после INSERT на ПОЛЬЗОВАТЕЛЕЙ таблице:

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; 

Однако, когда я попробуйте ввести INSERT в таблицу ПОЛЬЗОВАТЕЛЕЙ, которую я получаю:

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' 

Кто-нибудь знает, почему это происходит? Любая информация будет глубоко цениться. Благодаря!

ответ

0

Вам нужно будет вызвать процедуру отдельно и обновить таблицу, так как данные все еще не зафиксированы, и процедура попытается обновить одну и ту же таблицу, она не будет работать. Кроме того, я выполнил триггер, и он заполнит вашу таблицу утилит.

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 

EDIT

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' 

EDIT2

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> 
+0

Таким образом, нет простого способа редактировать триггеры/процедуры, чтобы пользователю автоматически предоставлялись утилиты после того, как они «Вставили в стол? Я должен придумать альтернативный способ вызова моей процедуры ПОСЛЕ того, как мой триггер был уволен? – Blued00d

+0

Да, потому что в триггере вы вставляете другую таблицу, но в процедуре вы обновляете базовую таблицу, в которой происходит фактическая вставка, которая по-прежнему не совершена или не отменена. – anudeepks

+0

Было бы недостаточно, чтобы просто добавить строку 'COMMIT;' после моих вставок, но до того, как моя процедура вызывается в моем триггере? Или это не разрешено? – Blued00d

0

Да, читать на мутирует триггерами. Вы пытаетесь обновить вставленную запись одновременно, и если вы пытаетесь вставить несколько утилит, то это станет настоящим беспорядком. Почему бы вместо этого не создать представление о таблицах, которые включают столбец, вычисляющий использование памяти? Или попробуйте виртуальный столбец (или столбец на основе функций) в таблице пользователей, основанный на другой таблице. (Я не тестировал это через таблицы, поэтому не могу сказать, будет ли это работать или нет.)

Смежные вопросы