从另一个表中查找触发

Posted

技术标签:

【中文标题】从另一个表中查找触发【英文标题】:Trigger with lookup from another table 【发布时间】:2018-04-21 08:18:39 【问题描述】:

我正在学习专门的 PL/SQL 触发器,我想学习如何使用触发器对多个表进行操作,但我无法理解该过程。这是一个例子:

CREATE TABLE Sess
(code       INTEGER     NOT NULL,
 dateStart  DATE        NOT NULL,
 dateEnd    DATE        NOT NULL,
 CONSTRAINT KeySess PRIMARY KEY(code)
)

CREATE TABLE Ins
(codeIns    CHAR(12)    NOT NULL,
 code       INTEGER     NOT NULL,
 dateIns    DATE        NOT NULL,
 dateAb     DATE,
 note       INTEGER,
 CONSTRAINT KeyIns PRIMARY KEY (codeIns, code)
)

1/ 我正在尝试构建一个触发器来确保这一点:

before Insert or Update Ins

dateAb is between dateStart and dateEnd

2/ 我还想ALTER TABLE 并锁定代码,以及 Ins 中的 codeIns,因此没有人可以更新它们,但我不知道命令。

对于第一个触发器,我尝试了类似的方法:

CREATE OR REPLACE TRIGGER test
BEFORE INSERT OR UPDATE OF dateAb ON Ins
FOR EACH ROW
DECLARE
    start date;
BEGIN
    SELECT DISTINCT s.dateStart INTO start
    WHERE Ins.code = s.code
    IF (:NEW.dateAb < start) THEN
        raise_application_error(-20101,'dateAb incorrect');
    END IF;
END;

注意:我没有声明变量 end 来检查它是否介于两者之间,我的目的是测试正确的语法

注意2:表格是空的。

我有 Warning: Trigger created with compilation errors. 和 3 个错误:

PL/SQL: SQL Statement ignored
4/40    PL/SQL: ORA-00923: key-word FROM absent 
9/5     PLS-00103: Encountered the symbol "IF" when expecting one of the
        following:
        ;

最后就像我说的那样,我不知道锁定表上的列以防止更新或是否有可能的正确语法。

我正在学习,所以如果你们中的一个人能教我正确处理我的两个请求的方法,我将不胜感激。 谢谢

【问题讨论】:

您的select 丢失了from sess swhere 子句应该是 where s.code = :new.code 另外,start 是 SQL 关键字(connect by 语法的一部分),因此您不能将其用作变量。 还有that CHAR column should be a VARCHAR2 【参考方案1】:

试试这个:

create or replace trigger test
    before insert or update of dateab on ins
    for each row
declare
    l_sess_start date;
begin
    select s.datestart into l_sess_start
    from   sess s
    where  s.code = :new.code;

    if :new.dateab < l_sess_start then
        raise_application_error
        ( -20101
        , 'Start date ' || to_char(:new.dateab,'DD-MON-YYYY') ||
          ' cannot be before ' || to_char(l_sess_start,'DD-MON-YYYY'));
    end if;
end;

测试:

insert into sess values (1, date '2018-04-22', date '2018-04-30');

insert into ins values ('Z', 1, date '2018-04-01', date '2018-04-01', null);

ERROR at line 1:
ORA-20101: Start date 01-APR-2018 cannot be before 22-APR-2018
ORA-06512: at "WILLIAM.TEST", line 10
ORA-04088: error during execution of trigger 'WILLIAM.TEST'

【讨论】:

工作感谢! , 有没有办法锁定表上的列以防止更新?比如ALTER TABLE和锁码,还有codeIns。 您可以使用触发器来执行此操作 - 如果更新列会引发错误 如果您不希望用户更新表,请不要授予他们update 权限。【参考方案2】:
PLS-00103: Encountered the symbol "IF" when expecting one of the
           following:
           ;

这个错误是因为你在select语句之后缺少;

【讨论】:

以上是关于从另一个表中查找触发的主要内容,如果未能解决你的问题,请参考以下文章

删除触发器并从另一个表中获取字段

插入触发器 SQL。插入新表后如何从另一个表中检索值

从另一个表中查找列的总值?(使用连接或其他函数)

SQLAlchemy:从另一个查询的结果中查找表中的所有匹配行

从另一个MyISAM表中自动加载MEMORY表

oracle触发器在表中插入新行时更新新的视图行