SQL触发器的视图

时间:2015-02-27 09:51:14

标签: sql oracle view triggers conditional-statements

我有一张名为Absence的表,记录员工缺勤的时间

CREATE TABLE Absence
(
  absence_id_pk varchar(6) NOT NULL,
  staff_id_fk varchar(6),
  start_date date,
  end_date date,
  reason varchar(30),
  PRIMARY KEY (absence_id_pk),
  FOREIGN KEY (staff_id_fk) REFERENCES Full_Time_Employee(staff_id_fk)
);

我创建了一个视图来计算员工缺席的总天数:

CREATE VIEW employee_absence 
AS
SELECT staff_id_pk, 
staff.first_name, 
staff.last_name, 
SUM(end_date -start_date) AS "Total Days Absent"
FROM Staff, Absence 
WHERE Absence.staff_id_fk = Staff.staff_id_pk 
GROUP BY staff_id_pk, staff.first_name, staff.last_name
ORDER BY staff_id_pk;

我是Triggers的新手,我想要的是一个触发器,当员工的总天数不存在时,会向屏幕打印一条消息> 20天。作为触发器的全新手段,我不知道如何解决这个问题。

非常感谢任何帮助或想法!

2 个答案:

答案 0 :(得分:1)

您可以通过以下两种方式之一来实现:

  1. 检查基表上的约束。
  2. 触发基表
  3. 我会在触发器上选择检查约束,如果他的缺席时间超过20天,我就不允许员工在表格中输入记录。

    检查约束

    SQL> DROP TABLE absence PURGE;
    
    Table dropped.
    
    SQL>
    SQL> CREATE TABLE Absence
      2  (
      3    absence_id_pk varchar(6) NOT NULL,
      4    staff_id_fk varchar(6),
      5    start_date date,
      6    end_date date,
      7    reason varchar(30),
      8    PRIMARY KEY (absence_id_pk)
      9  );
    
    Table created.
    
    SQL>
    SQL> ALTER TABLE Absence ADD CONSTRAINT chk CHECK(end_date - start_date <= 20);
    
    Table altered.
    
    SQL>
    SQL> INSERT INTO absence(absence_id_pk, start_date, end_date) VALUES(1, SYSDATE -20, SYSDATE);
    
    1 row created.
    
    SQL> INSERT INTO absence(absence_id_pk, start_date, end_date) VALUES(2, SYSDATE -21, SYSDATE);
    INSERT INTO absence(absence_id_pk, start_date, end_date) VALUES(2, SYSDATE -21, SYSDATE)
    *
    ERROR at line 1:
    ORA-02290: check constraint (LALIT.CHK) violated
    
    
    SQL>
    

    TRIGGER appraoch

    SQL> DROP TABLE absence PURGE;
    
    Table dropped.
    
    SQL>
    SQL> CREATE TABLE Absence
      2  (
      3    absence_id_pk varchar(6) NOT NULL,
      4    staff_id_fk varchar(6),
      5    start_date date,
      6    end_date date,
      7    reason varchar(30),
      8    PRIMARY KEY (absence_id_pk)
      9  );
    
    Table created.
    
    SQL> CREATE OR REPLACE TRIGGER trg
      2     BEFORE INSERT
      3   ON absence
      4  FOR EACH ROW
      5  BEGIN
      6     IF :NEW.end_date - :NEW.start_date > 20
      7        THEN
      8           RAISE_APPLICATION_ERROR(-20001, 'Total days absent are more than 20');
      9     END IF;
     10  END;
     11  /
    
    Trigger created.
    
    SQL>
    SQL> INSERT INTO absence(absence_id_pk, start_date, end_date) VALUES(1, SYSDATE -20, SYSDATE);
    
    1 row created.
    
    SQL> INSERT INTO absence(absence_id_pk, start_date, end_date) VALUES(2, SYSDATE -21, SYSDATE);
    INSERT INTO absence(absence_id_pk, start_date, end_date) VALUES(2, SYSDATE -21, SYSDATE)
                *
    ERROR at line 1:
    ORA-20001: Total days absent are more than 20
    ORA-06512: at "LALIT.TRG", line 4
    ORA-04088: error during execution of trigger 'LALIT.TRG'
    
    
    SQL>
    

    如果您仍想允许插入,只需显示消息。然后,删除 RAISE_APPLICATION_ERROR 并改为添加 DBMS_OUTPUT

    SQL> DROP TABLE absence PURGE;
    
    Table dropped.
    
    SQL>
    SQL> CREATE TABLE Absence
      2  (
      3    absence_id_pk varchar(6) NOT NULL,
      4    staff_id_fk varchar(6),
      5    start_date date,
      6    end_date date,
      7    reason varchar(30),
      8    PRIMARY KEY (absence_id_pk)
      9  );
    
    Table created.
    
    SQL> CREATE OR REPLACE TRIGGER trg
      2     BEFORE INSERT
      3   ON absence
      4  FOR EACH ROW
      5  BEGIN
      6     IF :NEW.end_date - :NEW.start_date > 20
      7        THEN
      8           DBMS_OUTPUT.PUT_LINE('Total days absent are more than 20');
      9     END IF;
     10  END;
     11  /
    
    Trigger created.
    
    SQL>
    SQL> INSERT INTO absence(absence_id_pk, start_date, end_date) VALUES(1, SYSDATE -20, SYSDATE);
    
    1 row created.
    
    SQL> INSERT INTO absence(absence_id_pk, start_date, end_date) VALUES(2, SYSDATE -21, SYSDATE);
    Total days absent are more than 20
    
    1 row created.
    
    SQL>
    

答案 1 :(得分:0)

您的解决方案存在一些问题。

  • 切勿在触发器中使用DBMS_OUTPUT。当您编写它并从IDE进行测试时,这可能会正常工作,但它通常不会导致任何消息传递到任何应用程序。触发器写入日志表。
  • 您的视图触发器仅在问题发生后才会在下一次插入上捕获问题。这可能是几天或几个月之后,到那时缺席可能已经大于20。
  • 实际上没有理由对视图执行插入操作。您无法使用视图插入新的缺席,因为该视图不会公开日期。或者你只是为了检查缺席的日子而执行INSERT?在这种情况下,为什么不从视图中查询天数&gt; 20?

您最好的做法是让表格上的After Insert和Update触发器检查缺少的天数,如果日期&gt;则写入日志条目。 20.此日志条目可以包含触发器可以获取的任何信息:如果操作是插入或更新,则影响的员工,执行操作的用户,执行操作的日期和时间,缺席天数操作生效,操作后缺席天数等等。

预定作业可以检查日志表并在遇到新条目时执行某些操作(发送电子邮件等)。