简体   繁体   中英

Convert SQL Server Trigger to Oracle

I'm trying to convert a sql server trigger which I have written. But I have been struggling with it a bit to convert it to oracle. I'm getting an error like Error at line: 26. Can anyone take a look at it? This would be a great help.

CREATE TRIGGER STAFF_ALLOCATION_LIMIT
ON Staff_Allocation
AFTER INSERT, UPDATE
AS
BEGIN

DECLARE @SID int
SELECT @SID = staff_Id FROM inserted

DECLARE @REC_COUNT int
DECLARE @ST_DATE DATE
DECLARE @END_DATE DATE

SELECT @END_DATE=staff_start_date FROM inserted
SELECT @ST_DATE=DATEADD(DAY, -(7), @END_DATE) 

SELECT @REC_COUNT=COUNT(*) 
FROM Staff_Allocation
WHERE staff_Id = @SID AND staff_start_date>@ST_DATE AND staff_end_date<@END_DATE

IF (@REC_COUNT >8 )
BEGIN
RAISERROR ('Only 8 schedules can be created for a staff per week',
16, 1)
ROLLBACK
END
END

In Oracle

CREATE OR REPLACE TRIGGER STAFF_ALLOCATION_LIMIT
AFTER INSERT OR UPDATE
ON Staff_Allocation
FOR EACH ROW
BEGIN

DECLARE
v_SID number(10)
v_SID = :NEW.staffId;

 v_REC_COUNT number(10)
 v_ST_DATE DATE
 v_END_DATE DATE

SELECT staff_start_date INTO v_END_DATE FROM inserted
 v_ST_DATE:=- * INTERVAL '1' DAY(5)(7) + v_END_DATE FROM dual 

SELECT COUNT(*) INTO v_REC_COUNT 
FROM Staff_Allocation
WHERE staff_Id = @SID AND staff_start_date>v_ST_DATE AND staff_end_date<v_END_DATE

IF (v_REC_COUNT >8 )
THEN
RAISERROR ('Only 8 schedules can be created for a staff per week',
16, 1)
ROLLBACK
END IF;
END

As I've already commented under the previous answer, an ordinary AFTER INSERT or UPDATE trigger will fail because the table is mutating. The savior might be the compound trigger (although there are other techniques one can use, but this one is rather simple).

Here's a demonstration based on Scott's EMP table - I don't want to allow more than 4 employees per department.

SQL> create or replace trigger trg_test
  2  for update or insert on emp
  3  compound trigger
  4
  5    type t_empcnt is record (deptno emp.deptno%type);
  6    type r_empcnt is table of t_empcnt index by pls_integer;
  7    g_empcnt r_empcnt;
  8
  9    after each row is
 10    begin
 11      g_empcnt(g_empcnt.count + 1).deptno := :new.deptno;
 12    end after each row;
 13
 14    after statement is
 15      l_cnt number;
 16    begin
 17      for i in 1 .. g_empcnt.count loop
 18        select count(*) into l_cnt
 19          from emp
 20          where deptno = g_empcnt(i).deptno;
 21
 22        if l_cnt > 4 then
 23          raise_application_error(-20000, 'Too many employees in department');
 24        end if;
 25      end loop;
 26    end after statement;
 27  end;
 28  /

Trigger created.

Testing:

SQL> -- Number of employees per department:
SQL> select deptno, count(*) From emp group by deptno order by deptno;

    DEPTNO   COUNT(*)
---------- ----------
        10          3
        20          3
        30          6

SQL> -- Inserting two new employees into the department 10 - one should pass, another fail:
SQL> insert into emp (deptno, empno, ename) values (10, 1, 'Little');

1 row created.

SQL> insert into emp (deptno, empno, ename) values (10, 2, 'Foot');
insert into emp (deptno, empno, ename) values (10, 2, 'Foot')
            *
ERROR at line 1:
ORA-20000: Too many employees in department
ORA-06512: at "SCOTT.TRG_TEST", line 21
ORA-04088: error during execution of trigger 'SCOTT.TRG_TEST'


SQL>

I don't have your tables so I'm trying to create your trigger, but can't guarantee it'll actually work; if not, say so, we'll try to fix it.

create or replace trigger staff_allocation_limit
for update or insert on staff_allocation
compound trigger

  type t_empcnt is record (sid staff_allocation.sid%type);
  type r_empcnt is table of t_empcnt index by pls_integer;
  g_empcnt r_empcnt;

  after each row is
  begin
    g_empcnt(g_empcnt.count + 1).sid := :new.sid;
  end after each row;

  after statement is
    l_cnt number;
  begin
    for i in 1 .. g_empcnt.count loop
      select count(*) into l_cnt
        from staff_allocation
        where sid = g_empcnt(i).sid
          and staff_start_date >= trunc(sysdate) - 8;

      if l_cnt > 8 then
        raise_application_error(-20000, 'Only 8 schedules can be created for a staff per week');
      end if;
    end loop;
  end after statement;
end;
/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM