★★★★★ORACLE触发器的问题★★★★★

powersite 2003-09-01 03:57:29
表A,每当插入行后,要立即将A中有关数据进行分析统计然后将结果再存入另一表B,
此时,对于表A而言,触发器内作的操作仅仅是“只读”操作,但是因为涉及到表A多行数据的访问,显然,不可能用":NEW"来满足数据。
请问,此时能够对于表A作SELECT COUNT(*) WHERE 。。。。。类似的操作吗?
如果不行,那么,有什么别的解决方法吗?以能够达到表A变化后,立即令B的数据也进行改动。当然,A->B,是有很多变动的规则,必须用SQL才能够完成表达。
该问题我觉得在实际应用中,也很有实用价值,请高手帮忙,指导!谢谢!
...全文
19 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
keyset 2003-09-03
  • 打赏
  • 举报
回复
触发器体中的 SQL 语句不能进行下列操作:
读或修改触发语句的任何变异表,其中包括触发表本身。
读或修改触发表的约束表中的主关键字,唯一关键字和外部关键字列。除此之外的其他列可以修改。
由于行触发器对变异表操作存在这两个限制,上述功能想实现的话可以先建一个包(临时表也可以),再建前语句级触发器将上面查询出的数据存放到包或临时表中,最后再建一个行级触发器,从包中读取已存放的数据来进行操作.

下面是实现的例子:


////////////////////////


create or replace package pck_scoscottzcntestsen as
type tab_num is table of number
index by binary_integer;
type tab_class is table of varchar2(10)
index by binary_integer;
v_num tab_num;
v_class tab_class;
v_count number :=0;
end;

//////////
行级

create or replace trigger trg_scoscottzcntestsen1
before update on scott.zcn
for each row
begin
pck_scoscottzcntestsen.v_count := pck_scoscottzcntestsen.v_count + 1;
pck_scoscottzcntestsen.v_num(pck_scoscottzcntestsen.v_count) := :new.num;
pck_scoscottzcntestsen.v_class(pck_scoscottzcntestsen.v_count) := :new.class;
end ;


///////////////////////////////////////////////////////////////////
////语句级
create or replace trigger trg_scoscottzcntestsen2
after update of name on scott.zcn
declare
v_maxnum constant number :=5;
v_curnum number :=0;
v_num number;
v_class varchar2(10);
begin
for icount in 1.. pck_scoscottzcntestsen.v_count loop
v_class := pck_scoscottzcntestsen.v_class(icount);
select count(1) into v_curnum
from scott.zcn a
where a.class = v_class;
if v_curnum > v_maxnum then
raise_application_error(-20000,v_class || 'scott:sen当前人数已满!asdfasdf');
end if;
end loop;
pck_scoscottzcntestsen.v_count := 0;
end ;

powersite 2003-09-01
  • 打赏
  • 举报
回复
beckhambobo(beckham) ,谢谢你的关注,但是,我这儿用COUNT只是一个比方,假如说我要SUM呢?我的目的是是否能访问A表取得数据?
beckhambobo 2003-09-01
  • 打赏
  • 举报
回复
create or replace trigger TRIG_INS_UPDATE_A
before insert or update on A
for each row
declare
num number;
begin
select count(1) into num from b where no=:new.no;
if inserting then
if num=0 then
INSERT INTO B( NO,COUNT) values(:new.no,1);
else
update b set count=count+1 where no=:new.no;
end if;
end if;
End;
/
powersite 2003-09-01
  • 打赏
  • 举报
回复
目前我的触发器这样编写的话,当执行到Execute Immediate S using :New.No时,会出错说,A表的数据已经更改,不能继续,,,,
powersite 2003-09-01
  • 打赏
  • 举报
回复
谢谢 enhydraboy(乱舞的浮尘) 的关注!
那如此说来,我的代码岂非已经是“行触发”了?
enhydraboy 2003-09-01
  • 打赏
  • 举报
回复
FOR EACH ROW

example:
CREATE TRIGGER scott.salary_check
BEFORE
INSERT OR UPDATE OF sal, job ON scott.emp
FOR EACH ROW
WHEN (new.job <> 'PRESIDENT')
pl/sql_block
powersite 2003-09-01
  • 打赏
  • 举报
回复
索性,我把程序简要的帖上来:
create or replace trigger TRIG_INS_UPDATE_A
after insert or update on A
for each row
declare
S Varchar2(5000);
begin
S := 'DELETE FROM B WHERE NO=:P';
EXECUTE IMMEDIATE S USING :New.No;

S := 'INSERT INTO B( NO,COUNT)(Select NO,count(*) FROM A WHERE No=:p group by no)';
Execute Immediate S using :New.No;
End ........
powersite 2003-09-01
  • 打赏
  • 举报
回复
enhydraboy(乱舞的浮尘) ,怎样指定?
AFTER INSERT之中,是不是当前行已经确实存入了数据库中?只要不对于A表进行数据变动操作,完全可以进行自由访问?
enhydraboy 2003-09-01
  • 打赏
  • 举报
回复
ORACLE和SQL SERVER完全不同。
ORACLE的触发器有行触发的概念,你只需要指定行触发方式就可以了。
powersite 2003-09-01
  • 打赏
  • 举报
回复
我可能没讲清楚,是在A中插入一条记录,然后要将该记录与已有记录中的某些数据合计起来,插入到表B中,这样的目的啊,
enhydraboy 2003-09-01
  • 打赏
  • 举报
回复
ORACLE和SQL SERVER完全不同。
ORACLE的触发器有行触发的概念,你只需要指定行触发方式就可以了。
powersite 2003-09-01
  • 打赏
  • 举报
回复
我可能没讲清楚,是在A中插入一条记录,然后要将该记录与已有记录中的某些数据合计起来,插入到表B中,这样的目的啊,
pluto74 2003-09-01
  • 打赏
  • 举报
回复
看样子你没有理解触发器阿,你插入多条的话,每插入一条触发一次阿。

17,086

社区成员

发帖
与我相关
我的任务
社区描述
Oracle开发相关技术讨论
社区管理员
  • 开发
  • Lucifer三思而后行
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧