SQL触发器在满足条件时停止更新

问题描述 投票:0回答:4

我有3个表:ProjectsComponentsSuppliers

[我想做的是编写一个触发器,如果​​组件和项目与供应商所在的城市相同,则不允许修改city的值。

到目前为止我尝试过的:

create or replace TRIGGER Supplier_control
BEFORE UPDATE of city
ON Suppliers
BEGIN
    DECLARE v_counter NUMBER := 0;
    SELECT COUNT(*) FROM (SELECT * FROM Suppliers s JOIN Projects p ON (s.city=p.city) JOIN Components c ON (c.city=s.city)) INTO v_counter;
    IF (v_counter != 0)
    THEN
        raise_application_error(-20111,'Can't change the city for this supplier!');
    END IF;
END;

尝试运行此命令后,出现以下错误:

Error at line 3: PLS-00103: Encountered the symbol "JOIN" when expecting one of the following:

   ) , with group having intersect minus order start union where
   connect

请注意,行号是指BEGIN之后的行号!

我也尝试过在BEGIN之前编写声明部分,但出现以下错误:

Error at line 3: PL/SQL: SQL Statement ignored

要摆脱这些错误需要做什么?

oracle plsql database-trigger
4个回答
2
投票

存在一些语法错误。

  1. [DECLAREBEGIN语句之前。
  2. [INTOSELECT之后且在FROM之前。
  3. raise_application_error(-20111,'Can't change the city for this supplier!');,您不能写Can't,因为第一个单引号将以Can't的引号结束,导致字符串在此结束。因此,您应该删除它或执行以下操作:raise_application_error(-20111,'Can''t change the city for this supplier!');

话虽如此,完整的代码应如下所示:

CREATE OR REPLACE TRIGGER Supplier_control
BEFORE UPDATE of city
ON Suppliers
DECLARE v_counter NUMBER := 0;
BEGIN

    SELECT COUNT(*) 
    INTO v_counter
    FROM (SELECT * FROM Suppliers s JOIN Projects p ON (s.city=p.city) JOIN Components c ON (c.city=s.city));

    IF (v_counter != 0) THEN
        raise_application_error(-20111,'Can''t change the city for this supplier!');
    END IF;

END;

希望这会有所帮助。


0
投票

您正在尝试访问在声明中分配为零的变量。设置查询中的变量(其结果将是数字)

create or replace TRIGGER Supplier_control
BEFORE UPDATE of city
ON Suppliers
BEGIN
    DECLARE v_counter NUMBER := 0;
-- change this line
    SET v_counter = (SELECT COUNT(*) FROM (SELECT * FROM Suppliers s JOIN Projects p ON (s.city=p.city) JOIN Components c ON (c.city=s.city)));
    IF (v_counter != 0)
    THEN
        raise_application_error(-20111,'Can't change the city for this supplier!');
    END IF;
END;

将计数查询更改为已编辑的查询。首先,如果输出为数字,则只需运行查询SELECT COUNT(*) FROM (SELECT * FROM Suppliers s JOIN Projects p ON (s.city=p.city) JOIN Components c ON (c.city=s.city)),然后将其分配给变量v_counter


0
投票

不需要加入的开销,也不需要转移任何日期。假设City在Projects and Components中已建立索引(可能应该是在FK中建立索引),则以下内容仅需要在每个表上建立一个简单的索引概率。

create or replace trigger supplier_control
before update of city
on suppliers
for each row
declare 
    project_component_exists integer ;
begin
    select null
      into project_component_exists
      from dual
     where exists ( select null 
                      from projects  
                     where city = :old.city
                  ) 
       and exists ( select null 
                      from components  
                     where city = :old.city
                  );
    raise_application_error(-20111,'Can''t change the city for this supplier!');                  
exception 
 when no_data_found
 then null;    
end;   

0
投票

通过lower()upper()进行检查以匹配,包括不区分大小写,在整个表项目的值中城市是否匹配。

由于表名发生更改错误的风险,因此您不需要,也不应在select语句中使用Supplier表:>

CREATE OR REPLACE TRIGGER Supplier_control
BEFORE UPDATE of city
ON Suppliers
DECLARE 
    v_counter PLS_INTEGER;
BEGIN
    SELECT COUNT(*) 
      INTO v_counter
      FROM Projects p 
     WHERE lower(:new.city)=lower(p.city);

    IF (v_counter != 0) THEN
        raise_application_error(-20111,'Can''t change the city for this supplier!');
    END IF;
END;

其中v_counter的初始化是多余的,如果没有找到匹配的记录,则它已经为零。此外,请注意declare关键字包含变量定义部分的顺序。

© www.soinside.com 2019 - 2024. All rights reserved.