触发需要PL / SQL协助

时间:2013-06-06 18:25:53

标签: sql database oracle plsql

我正在尝试创建一个触发器,当一个记录插入到employee表(一个新员工)时,触发器触发并将一条记录作为'N / A'插入employee_dept_history表中(因为这个员工是新的,没有以前的部门)。此外,如果当前员工切换部门,则触发器应在employee_dept_history表中插入记录,并且员工depatment_id会更改。我在创建这个触发器时遇到了问题。我想知道是否有人能用我的代码引导我走向正确的方向。我无法得到以下触发器来显示'N / A'。我怎么能让这个触发器工作?我是否需要为新旧部门创建局部变量?

CREATE OR REPLACE TRIGGER employee_dept_trigger
   BEFORE INSERT OR UPDATE ON employee
   FOR EACH ROW

BEGIN
   INSERT INTO employee_dept_history
   VALUES(:NEW.employee_id, 
       :NEW.employee_name, 
        from_department_name (NEEDS TO OUTPUT 'N/A'),
        to_department_name, 
        sysdate);
 END employee_dept_trigger;

EMPLOYEE_DEPT_HISTORY表格如下:

CREATE TABLE empployee_dept_history
(
    EMPLOYEE_ID NUMBER(4)
    EMPLOYEE_NAME VARCHAR2(50)
    FROM_DEPARTMENT_NAME VARCHAR2(50)
    TO_DEPARTMENT_NAME VARCHAR2(50)
    OPERATION_TIME DATE
);

EMPLOYEE表:

(
    EMPLOYEE_ID NUMBER(4)
    EMPLOYEE_NAME VARCHAR2(20)
    JOB VARCHAR2(50)
    MANAGER_ID NUMBER(4)
    HIRE_DATE DATE
    SALARY NUMBER(9)
    COMMISION NUMBER(9)
    DEPARTMENT_ID NUMBER(4)
);

3 个答案:

答案 0 :(得分:2)

注意:这个答案类似于其他两个,但我会发布它,因为它以一种可能有用的方式不同地定义触发器。 请注意,我已经对其他两个答案进行了投票,因为他们会很好地完成这项工作。

首先,如果您只对DEPARTMENT_ID列的更改感兴趣,可以在触发器定义中指定:

CREATE OR REPLACE TRIGGER employee_dept_trigger
   BEFORE INSERT OR UPDATE OF department_id ON employee
   FOR EACH ROW
....

触发器可以使用“自动”逻辑值INSERTINGUPDATING来确定插入或更新是否称为它。您可以使用INSERTING值来表明这是一名新员工:

IF INSERTING THEN
   -- set old department name = 'N/A'
ELSE
   -- set old department name = whatever
END IF;

您的问题没有描述部门名称的来源,所以这个例子在涉及部门名称时会进入伪代码:

CREATE OR REPLACE TRIGGER employee_dept_trigger
   BEFORE INSERT OR UPDATE OF department_id ON employee
   FOR EACH ROW
BEGIN
  IF INSERTING THEN
    -- New employee
    INSERT INTO employee_dept_history VALUES (
       :NEW.employee_id,
       :NEW.employee_name,
       'N/A',
       (SELECT department_name from ...), <-- based on :NEW.department_id
       SYSDATE);
  ELSE
    -- Existing employee
    INSERT INTO employee_dept_history VALUES (
       :NEW.employee_id,
       :NEW.employee_name,
       (SELECT department_name from ...), <-- based on :OLD.department_id
       (SELECT department_name from ...), <-- based on :NEW.department_id
       SYSDATE);
  END IF;
END employee_dept_trigger;

答案 1 :(得分:1)

要么是

CREATE OR REPLACE TRIGGER employee_dept_trigger
   BEFORE INSERT OR UPDATE ON employee
   FOR EACH ROW
DECLARE
  from_department_name varchar(255);
  to_department_name varchar(255);
BEGIN
   select from DEPARTMENT where DEPARTMENT_ID=:NEW.DEPARTMENT_ID into to_department_name;
   IF INSERTING THEN
   INSERT INTO employee_dept_history
   VALUES(:NEW.employee_id, 
       :NEW.employee_name, 
        'N/A',
        to_department_name, 
        sysdate);
   end if;
   IF UPDATING THEN
   select from DEPARTMENT where DEPARTMENT_ID=:OLD.DEPARTMENT_ID into from_department_name;
   INSERT INTO employee_dept_history
   VALUES(:NEW.employee_id, 
        :NEW.employee_name, 
        from_department_name ,
        to_department_name, 
        sysdate);
   end if;
 END employee_dept_trig;

或者我不明白你的问题。

答案 2 :(得分:1)

你可能想要这样的东西:

CREATE OR REPLACE TRIGGER employee_dept_trigger
   BEFORE INSERT OR UPDATE ON employee
   FOR EACH ROW

BEGIN

IF INSERTING THEN
   INSERT INTO employee_dept_history
   VALUES(:NEW.employee_id, 
       :NEW.employee_name, 
        'N/A',
        :NEW.DEPARTMENT_ID, 
        sysdate);
ELSE
   INSERT INTO employee_dept_history
   VALUES(:NEW.employee_id, 
       :NEW.employee_name, 
       :OLD.DEPARTMENT_ID, 
       :NEW.DEPARTMENT_ID,
        sysdate);
END IF;
 END employee_dept_trigger;

虽然你没有说明部门名称的来源,但它还不是很正确。我使用部门ID只是为了给你一个想法..