【问题标题】:Trigger to check for duplicates and update a value of an attribute触发检查重复项并更新属性值
【发布时间】:2013-04-09 07:22:08
【问题描述】:

我有一个具有代码和索引属性的表。

我正在尝试创建一个触发器来检查代码的值。如果插入的代码有重复,则触发索引加1。示例:

code|c_index
111 | 1
112 | 1
113 | 1
111 | 2
114 | 1
112 | 2
111 | 3

这是我的代码,但它不起作用:

create trigger trg_update
after insert on trial

for each row

declare v_index;

begin

select max(nvl(trial.c_index, 0)) into v_index
from trial;

if new.code = code then
set new.c_index = v_index

else 
set new.c_index = 1

end if;
end;

..................

我尝试过做一个更好的新的,但还是不行:

create trigger trg_update
after insert on trial
for each row
declare v_index number;

begin

if :new.code = :old.code then
select max(nvl(c_index, 0)) into v_index
from trial
where code = :new.code;

set :new.c_index = v_index + 1

else 
set :new.c_index = 1

end if;
end;

上面的代码有什么问题,问题的解决方法是什么?

..................................................

更新:

运行这段代码后:

create trigger trg_update
AFTER insert on trial
for each ROW

DECLARE v_index NUMBER := -1; -- "-1" is put in place so to be below the minimum value of the column
DECLARE v_cnt NUMBER   := 0;

BEGIN

SELECT MAX(c_index), COUNT(*)
  INTO :v_index, v_cnt
  FROM trial
 WHERE code = :new.code;

IF v_index <> -1 AND v_cnt > 1 THEN
--Only one update here, for the newly inserted row explicitly
  UPDATE trial
     SET c_index = c_index +1
   WHERE code    = :new.code
     AND c_index = v_index
     AND ROWNUM  = 1;

END IF;
END;

显示的一些问题:

1- 错误(2,1):PLS-00103:遇到符号“DECLARE” 2- 错误(7,8):PLS-00049:错误的绑定变量“V_INDEX” 3- 错误(9,15):PLS-00049:错误的绑定变量 'NEW.CODE'

这是尝试修复错误 2 和 3 后的新代码:

create or replace trigger trg_update
AFTER insert on trial
for each ROW

declare vindex NUMBER := -1; -- "-1" is put in place so to be below the minimum value of the column
declare vcnt NUMBER   := 0;

BEGIN

SELECT MAX(c_index), COUNT(*)
  INTO vindex, vcnt
  FROM trial
 WHERE code = :new.code;

IF vindex <> -1 AND vcnt > 1 THEN
--Only one update here, for the newly inserted row explicitly
  UPDATE trial
     SET c_index = c_index +1
   WHERE code    = :new.code AND c_index = vindex AND ROWNUM  = 1;

END IF;

END;

但是,第一个错误仍然显示。

错误(2,1):PLS-00103:在预期以下情况之一时遇到符号“DECLARE”:begin function pragma procedure subtype type current cursor delete exists prior 将符号“begin”替换为“DECLARE”继续。

除了这个错误:

错误(19,4):PLS-00103:在预期以下情况之一时遇到符号“文件结尾”:( begin case declare end exception exit for goto if loop mod null pragma raise return select update while with

我该如何解决这些错误?

【问题讨论】:

  • 您使用的是什么数据库系统?

标签: sql oracle if-statement for-loop each


【解决方案1】:

首先,在插入新值之前在数据库中设置数据,执行以下操作:

UPDATE trial tr
   SET c_index = (SELECT MAX(c_index) + 1
                  FROM trial
                 WHERE code = tr.code);

COMMIT;

之后,这里是一个触发器,它将相应地更新值(新插入的):

CREATE OR REPLACE TRIGGER trg_update
AFTER INSERT ON trial
FOR EACH ROW

DECLARE
v_index NUMBER := -1; -- "-1" is put in place so to be below the minimum value of the column v_cnt NUMBER := 0;

BEGIN

  SELECT MAX(c_index), COUNT(*)
    INTO v_index, v_cnt
    FROM trial
   WHERE code = :new.code;

  IF v_index <> -1 AND v_cnt > 1 THEN
  --Only one update here, for the newly inserted row explicitly
    UPDATE trial
       SET c_index = c_index +1
     WHERE code    = :new.code
       AND c_index = v_index
       AND ROWNUM  = 1;

  END IF;
END;

我编辑了触发器,它在我这边运行良好,但请注意它会在第一次更新查询后正常运行。如果 DECLARE 的问题仍然存在,请尝试删除它,例如,有时它不是临时性的。

【讨论】:

  • 感谢您的回复和帮助。我运行了上面的代码,但没有正确编译;这些是对我来说出现的错误:1-错误(2,1):PLS-00103:遇到符号“DECLARE”2-错误(7,8):PLS-00049:错误的绑定变量'V_INDEX'3-错误(9,15): PLS-00049: bad bind variable 'NEW.CODE' 但是,我会在纠正两个错误(2 和 3)后发布新代码。我无法修复第一个错误,因为我不能不了解错误本身。
  • 代码中有两个 DECLARE,对此我深表歉意。不幸的是,我无法在我工作的地方创建这些表并测试我在此处粘贴的查询和触发器。
  • 您好,即使在为两个变量保留一个 decleare 之后,也会出现相同的错误!!!我仍在尝试寻找解决方案以找出解决方法。任何方法,非常感谢。还在找人帮我。我需要尽快完成这个触发器。
  • 好的,让我在给定的条件下尝试重新工作,然后我会看看我能做什么并编辑我的评论。
  • 我再次尝试了您的代码。它编译没有错误,这很好,非常好。我直接去测试插入,但是确实给我报错:SQL Error: ORA-04098: trigger
【解决方案2】:

您会发现以这种方式使用触发器在很多方面都会很痛苦。一开始很诱人,似乎是个好主意,但事实并非如此。

触发器是在 DRI 标准化之前发明的。它们的目的是加强参照完整性。如果您在可行的情况下使用 DRI,否则只为 RI 触发,您将与 DBMS 相处得更好。

要做你想做的事,改变你的insert以使用一个相关的子查询来测试行的存在(以免插入重复),将c_index设置为0。然后update与@987654324的行@。

create procedure tablename_add @code int
as
-- add the row if it's not already there
insert tablename values (@code, 0)
where code not in 
      (select code from tablename where code = @code)
-- increase the count by one
update tablename set c_index = c_index + 1
where code = @code

您甚至不需要定义交易。如果没有行,INSERT 将成功并将c_index 设置为零,否则将无效。然后更新将增加c_index1,无论如何。

【讨论】:

  • 感谢您的回复和帮助。我没明白你的想法。请您再解释一下好吗?
  • 我将您需要的 SQL 添加到我的答案中。 HTH。
猜你喜欢
  • 2012-01-18
  • 2021-07-03
  • 2019-10-07
  • 1970-01-01
  • 1970-01-01
  • 2018-06-10
  • 1970-01-01
  • 1970-01-01
  • 2017-06-19
相关资源
最近更新 更多