0

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

我正在尝试创建一个触发器来检查代码的值。如果插入的代码有重复,则触发索引加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”:开始函数杂注过程子类型类型当前游标删除之前存在符号“开始”替换“声明”以继续。

除了这个错误:

错误(19,4):PLS-00103:在预期以下情况之一时遇到符号“文件结尾”:(开始案例声明结束异常退出 goto if loop mod null pragma raise return select update while with <<继续关闭当前删除获取锁插入打开回滚保存点设置sql执行提交forall合并管道清除

我该如何解决这些错误?

4

2 回答 2

0

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

触发器是在 DRI 标准化之前发明的。它们的目的是加强参照完整性。如果您在可行的情况下使用 DRI 并仅针对 RI 触发,那么您与 DBMS 相处得更好。

要执行您想要的操作,请将您更改insert为使用测试行是否存在的相关子查询(以免插入重复项),设置c_index为 0。然后update使用set c_index =c_index +1.

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,无论如何。

于 2013-04-17T06:59:48.837 回答
0

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

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 的问题仍然存在,请尝试将其删除,例如,有时它不是临时性的。

于 2013-04-17T07:03:33.253 回答