表 KSOURCE.USERINFO 发生了变化, 触发器/函数不能读它

最后一只恐龙 2009-06-05 09:02:53
UserInfo(UserID,UserName,DepartID,SerialNum,...)
对于一个部门(DepartID相同)下的用户,我要让其序号SerialNum保持连续,就建立了一个触发器:

CREATE OR REPLACE TRIGGER "KSOURCE".TRUSERINFO_INSERT AFTER
INSERT ON "KSOURCE"."USERINFO" REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW
Declare
v_SerialNum Number;
Begin
Select Count(*) Into v_SerialNum From UserInfo Where DepartID=:New.DepartID;
if (:New.SerialNum <> v_SerialNum) Then
Update UserInfo Set SerialNum=v_SerialNum Where UserID=:New.UserID;
end if;
End;



这样,如果用户输入的SerialNum不连续了,自动改成连续的,但Insert时却出现如下提示:
表 KSOURCE.USERINFO 发生了变化, 触发器/函数不能读它
...全文
277 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
jdsnhan 2009-06-09
  • 打赏
  • 举报
回复
不可跳号的需求很多,比如财务上发票号

完全可以序号SerialNum本身自动生成,不用人为干预他。

如果还要考虑delete后,所有的序号SerialNum同步刷新,在100w级数据量的时候,系统就没法用了

所以,关于delete,前台是不许删除的。打开数据库删除管不了。





eternal_hour 2009-06-09
  • 打赏
  • 举报
回复
Serial Number 又不是主键, 为什么要它连续呢。 如果真的需要的话, 你可以使用

SELECT ROWNUM SerialNum
, tbl.COL1
, tbl.COL2
FROM ( SELECT *
FROM target_table
ORDER BY ...
) tbl
;

我觉得你的这个Trigger可能没有必要哦
william3033 2009-06-05
  • 打赏
  • 举报
回复
学习,接点分。
william3033 2009-06-05
  • 打赏
  • 举报
回复
学习,接点分。
最后一只恐龙 2009-06-05
  • 打赏
  • 举报
回复
难道Oracle的封锁粒度是整个表,Insert时整个表被锁住了?我建立的可是After触发器啊。如果真的这样,我在删除一个记录时,如删除SerialNum=2的,要把SerialNum>2的都减1,是不是就不能使用触发器了?
inthirties 2009-06-05
  • 打赏
  • 举报
回复
由于是自治形式的,所以在你的程序块里,最后需要加上commit;


==================================================================
Inthirties关注Oracle数据库 维护 优化,安全,备份,恢复,迁移,故障处理

如果你需要帮助或想和我一起学习的请联系
联系方式QQ:370140387
电子邮件:dba@Inthirties.com
网站: http://www.inthirties.com

inthirties 2009-06-05
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 Ivy_zheng 的回复:]
难道Oracle的封锁粒度是整个表,Insert时整个表被锁住了?我建立的可是After触发器啊。如果真的这样,我在删除一个记录时,如删除SerialNum=2的,要把SerialNum>2的都减1,是不是就不能使用触发器了?
[/Quote]


这里出错原因,估计是行级的触发器代码中不能再操作该表,包括select,默认的在写TRIGGER的时候把本表锁死,不允许对其进行操作,这里可以通过一些AUTONOMOUS_TRANSACTION(自治事务)来解决


CREATE OR REPLACE TRIGGER "KSOURCE".TRUSERINFO_INSERT AFTER
INSERT ON "KSOURCE"."USERINFO" REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW
Declare
v_SerialNum Number;
[font]PRAGMA AUTONOMOUS_TRANSACTION;[/font]
Begin
Select Count(*) Into v_SerialNum From UserInfo Where DepartID=:New.DepartID;
if (:New.SerialNum <> v_SerialNum) Then
Update UserInfo Set SerialNum=v_SerialNum Where UserID=:New.UserID;
end if;
End;


你试试这个解决方式叻,不过对于你这case,确实比较复杂,在你delete一条中间的数据时,确实还要控制其他的serialnum也随之发生变化。这样才能保持连续


==================================================================
Inthirties关注Oracle数据库 维护 优化,安全,备份,恢复,迁移,故障处理

如果你需要帮助或想和我一起学习的请联系
联系方式QQ:370140387
电子邮件:dba@Inthirties.com
网站: http://www.inthirties.com

manchun 2009-06-05
  • 打赏
  • 举报
回复
[Quote=引用楼主 Ivy_zheng 的帖子:]
UserInfo(UserID,UserName,DepartID,SerialNum,...)
对于一个部门(DepartID相同)下的用户,我要让其序号SerialNum保持连续,就建立了一个触发器:

SQL code
CREATE OR REPLACE TRIGGER "KSOURCE".TRUSERINFO_INSERT AFTER
INSERT ON "KSOURCE"."USERINFO" REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW
Declare
v_SerialNum Number;
Begin
Select Count(*) Into v_SerialNum From UserInfo Where DepartID=…
[/Quote]

可能是序列被别的用户取走了,所以前后变化了。

17,377

社区成员

发帖
与我相关
我的任务
社区描述
Oracle 基础和管理
社区管理员
  • 基础和管理社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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