SQL 满足条件时触发停止更新
SQL trigger to stop update when a condition is met
我有 3 个表:Projects
、Components
和 Suppliers
。
我想做的是编写一个触发器,如果组件和项目与供应商具有相同的城市,则不允许修改 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
需要做什么才能消除这些错误?
您正在尝试访问声明中指定为零的变量。
从查询中设置变量(结果将是一个数字)
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
有些语法错误。
DECLARE
在 BEGIN
语句之前。
INTO
在 SELECT
之后和 FROM
之前。
- 在
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;
希望这对您有所帮助。
检查 lower()
或 upper()
匹配包括不区分大小写,城市是否匹配整个 table 项目的值。
您不需要也不应该在 select 声明中使用 Supplier table,因为 table name is mutating error 的风险:
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
关键字的顺序,包括变量定义部分。
不需要 Join 的开销,甚至不需要转移任何日期。假设 City 在 Projects 和 Components 中被索引(可能应该是一个索引的 FK),下面只需要在每个 table 上有一个简单的索引概率。
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;
我有 3 个表:Projects
、Components
和 Suppliers
。
我想做的是编写一个触发器,如果组件和项目与供应商具有相同的城市,则不允许修改 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
需要做什么才能消除这些错误?
您正在尝试访问声明中指定为零的变量。 从查询中设置变量(结果将是一个数字)
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
有些语法错误。
DECLARE
在BEGIN
语句之前。INTO
在SELECT
之后和FROM
之前。- 在
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;
希望这对您有所帮助。
检查 lower()
或 upper()
匹配包括不区分大小写,城市是否匹配整个 table 项目的值。
您不需要也不应该在 select 声明中使用 Supplier table,因为 table name is mutating error 的风险:
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
关键字的顺序,包括变量定义部分。
不需要 Join 的开销,甚至不需要转移任何日期。假设 City 在 Projects 和 Components 中被索引(可能应该是一个索引的 FK),下面只需要在每个 table 上有一个简单的索引概率。
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;