【问题标题】:Creating a Trigger that runs on two tables创建在两个表上运行的触发器
【发布时间】:2021-05-17 03:28:21
【问题描述】:

我有两张桌子,COPYBORROW。他们的专栏是:

COPY (
Copy_id,
Bk_id,
Loc_id,
Opinion
)

BORROW (
Cus_evo,
B_Date,
R_Date,
Fee,
Copy_id,
Cus_id
)

我想配置一个触发器,确保存储在确切位置(伦敦)的副本(来自COPY 表的Loc-id 列)不能在12 月借用(来自BORROW 表的B_Date 列) .

我创建了以下触发器:

CREATE OR REPLACE TRIGGER BORROW_TRIGGER 
BEFORE INSERT ON BORROW FOR EACH ROW BEGIN
IF(TO_CHAR(TO_DATE(:NEW.B_Date, 'DD-MMM-YYYY'),'MMM'= 'DEC')
AND :NEW.Loc_id='LC0001')
THEN RAISE_APPLICATION_ERROR(-20669,'CANNOT BORROW BOOKS FROM LONDON STORE DURING MONTH DECEMBER');
END IF;
END;
/

触发器未创建并且有错误请云给我正确的触发器??

我遇到的错误

Errors: TRIGGER BORROW_TRIGGER
Line/Col: 3/5 PLS-00049: bad bind variable 'NEW.LOC_ID'

【问题讨论】:

  • 我正在为此使用 sql-server
  • 我正在为此使用 oracle sql-server
  • 如果您使用的是 Oracle,那么您就没有使用 SQL Server。它们是完全不同的竞争产品。
  • 这也是我今天看到的第三个或第四个问题,人们试图在 SQL Server 中使用类似于 Oracle 语法的触发器;我开始怀疑这是巧合。
  • 欢迎来到 Stack Overflow!您可以做几件事来改进您的帖子并提高获得答案的机会:1. 确定服务器制造商和版本(例如“Oracle 19c”或“Microsoft SQLServer 15.0. 2000.5)。2. 提供您看到的实际错误消息。

标签: sql oracle plsql triggers oracle19c


【解决方案1】:

你需要查询COPY表来获取你需要的字段:

CREATE OR REPLACE TRIGGER BORROW_BI
  BEFORE INSERT ON BORROW
  FOR EACH ROW
DECLARE
  strLoc_id  COPY.LOC_ID%TYPE;
BEGIN
  SELECT LOC_ID
    INTO strLoc_id
    FROM DUAL
    LEFT OUTER JOIN COPY c
      ON c.COPY_ID = :NEW.COPY_ID;

  IF TO_CHAR(TO_DATE(:NEW.B_Date, 'DD-MMM-YYYY'), 'MMM') = 'DEC' AND 
     strLoc_id = 'LC0001'
  THEN
    RAISE_APPLICATION_ERROR(-20669,'CANNOT BORROW BOOKS FROM LONDON STORE DURING MONTH DECEMBER');
  END IF;
END BORROW_BI;

【讨论】:

  • Errors: TRIGGER BORROW_BI Line/Col: 12/3 PLS-00103: Encountered the symbol "THEN" when expecting one of the following: ) , * & - + / at mod remainder rem <an exponent (**)> and or || multiset The symbol ")" was substituted for "THEN" to continue.
【解决方案2】:

您可以使用 Select 语句和另一个表 (copy) 中的 COUNT 聚合来检查存在性,方法是在表中使用公共列 (copy_id),例如

CREATE OR REPLACE TRIGGER Trg_Borrow_Trigger_BI
  BEFORE INSERT ON borrow
  FOR EACH ROW
DECLARE    
    v_exists INT;  
BEGIN
    SELECT COUNT(*)
      INTO v_exists
      FROM copy
     WHERE copy_id = :NEW.copy_id
       AND loc_id = 'LC0001'
       AND TO_CHAR( :NEW.b_Date, 'MM' ) = '12';
      
    IF v_exists > 0 THEN
      RAISE_APPLICATION_ERROR(-20669,
                              'CANNOT BORROW BOOKS FROM LONDON STORE DURING MONTH DECEMBER');
    END IF;
END;
/

在哪里

  • TO_DATE()转换是多余的
  • 不可能在loc_id 前面加上:NEW,因为触发器是为 borrow 表没有此列,而copy 表有。

【讨论】:

  • 这是成功创建的触发器,但其中的位置被省略了。
【解决方案3】:

由于您只需要在 b_date 为 12 月时执行检查,因此将其作为 when 条件添加到触发器顶部会更有效。这也简化了触发逻辑。

create or replace trigger borrow_check_trg
    before insert on borrow 
    for each row
    when (to_char(new.b_date,'MM') = '12')
declare
    l_loc_id copy.loc_id%type;
begin
    select c.loc_id into l_loc_id
    from   copy c
    where  c.copy_id = :new.copy_id;

    if l_loc_id = 'LC0001' then
       raise_application_error(-20669, 'Books cannot be borrowed from the London store during December'); 
    end if;
end;

【讨论】:

  • 这个触发器是成功的。
猜你喜欢
  • 2011-06-16
  • 1970-01-01
  • 1970-01-01
  • 2014-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多