触发器update(Update触发器问题(SQL2000))

本文目录
- Update触发器问题(SQL2000)
- 如何创建一个update触发器
- sql触发器 update
- 有关sql insert触发器和update触发器
- SQL语句创建update触发器
- sql 触发器update问题
- SQL 触发器 update 为什么执行两次
- mysql触发器实现oracle物化视图示例代码
- 在触发器里多次更新记录时update触发器执行几次
- mysql 实现每月更新一次的触发器问题
Update触发器问题(SQL2000)
触发器这样写:
CREATE
TRIGGER
Update_grade
ON
[SC]
FOR
UPDATE
AS
declare
@y_B
INT,@n_B
INT
SELECT
@Y_B=B
FROM
DELETED
SELECT
@N_B=B
FROM
INSERTED
if
(((@N_B-@Y_B)*100)/@Y_B)》10
raiserror(’更新失败!’,16,1)
GO
触发器只完成当字段B的增量超过10%时,报告错误.
而事务回滚操作(ROLLBACK)一般要在调用UPDATE语句的连接上给出
更新成功的报告也要在前台调用UPDATE的程序没有收到“更新失败”信息时给出。
如何创建一个update触发器
使用create
trigger命令创建触发器
语法如下
create
trigger
trigger_name
on{table|view}
[with
encryption]
{
{{for|after|insted
of}{[delete][,][insert][,][update]}
[not
for
replication]
as
[{if
update
(column)
[{and|or}
update
(column)]
[...n]
|if
(columns_updated(){bitwise_operator}updated_bitmask)
{comparison_operator}column_bitmask[...n]
}]
sql_statement
[...n]
}
}
至于存储过程是使用create
procedure创建存储过程的
语法如下
create
procedure
procedure_name[;version
number]
[{@parament
date_type}
[varying]
[=default
value][output]
][,...n]
[with
{recompite|encryption|recompile,encryption}]
[for
replication]
as
sql_statement
[...n]
sql触发器 update
使用更新什么字段才执行触发器就行了
CREATE
TRIGGER
GXDHSL
ON
RKD
FOR
UPDATE
AS
IF(Update(
字段名
))
begin
DECLARE
@DHDH
VARCHAR(50)
--计划单号
DECLARE
@SL
decimal(18,6)
--修改前数量
DECLARE
@DHSL
decimal(18,6)
--修改后数量
SELECT
@DHDH=ysdh,@SL=SSSL
FROM
DELETED
SELECT
@DHSL=SSSL
FROM
INSERTED
UPDATE
GL_QGD
SET
DHSL=DHSL-ISNULL(@SL,0)
WHERE
DH=@DHDH
end
go
有关sql insert触发器和update触发器
DML触发器有三类:
1, insert触发器;
2, update触发器;
3, delete触发器;
触发器的组成部分:
触发器的声明,指定触发器定时,事件,表名以类型
触发器的执行,PL/SQL块或对过程的调用
触发器的限制条件,通过where子句实现
类型:
应用程序触发器,前台开发工具提供的;
数据库触发器,定义在数据库内部由某种条件引发;分为:
DML触发器;
数据库级触发器;
替代触发器;
DML触发器组件:
1,触发器定时
2,触发器事件
3,表名
4, 触发器类型
5, When子句
6, 触发器主体
可创建触发器的对象:数据库表,数据库视图,用户模式,数据库实例
创建DML触发器:
Create [or replace] trigger [模式.]触发器名
Before| after insert|delete|(update of 列名)
On 表名
[for each row]
When 条件
PL/SQL块
For each row的意义是:在一次操作表的语句中,每操作成功一行就会触发一次;不写的话,表示是表级触发器,则无论操作多少行,都只触发一次;
When条件的出现说明了,在DML操作的时候也许一定会触发触发器,但是触发器不一定会做实际的工作,比如when 后的条件不为真的时候,触发器只是简单地跳过了PL/SQL块;
Insert触发器的创建:
create or replace trigger tg_insert
before insert on student
begin
dbms_output.put_line(’insert trigger is chufa le .....’);
end;
/
执行的效果:
SQL》 insert into student
2 values(202,’dongqian’,’f’);
insert trigger is chufa le .....
update表级触发器的例子:
create or replace trigger tg_updatestudent
after update on student
begin
dbms_output.put_line(’update trigger is chufale .....’);
end;
/
运行效果:
SQL》 update student set se=’f’;
update trigger is chufale .....
已更新8行;
可见,表级触发器在更新了多行的情况下,只触发了一次;
如果在after update on student后加上
For each row的话就成为行级触发器,运行效果:
SQL》 update student set se=’m’;
update trigger is chufale .....
update trigger is chufale .....
update trigger is chufale .....
update trigger is chufale .....
update trigger is chufale .....
update trigger is chufale .....
update trigger is chufale .....
update trigger is chufale .....
已更新8行;
:new 与: old:必须是针对行级触发器的,也就是说要使用这两个变量的触发器一定有for each row
这两个变量是系统自动提供的数组变量,:new用来记录新插入的值,old用来记录被删除的值;
使用insert的时候只有:new里有值;
使用delete的时候只有:old里有值;
使用update的时候:new和:old里都有值;
可以这样使用: dbms_output.put_line(’insert trigger is chufa
dbms_output.put_line(’new id is : ’||:new.stui
dbms_output.put_line(’new name is : ’||:new.st
dbms_output.put_line(’new se is : ’||:new.se);
可以这样从数据字典中查看一个表上有哪几个触发器:
SQL》 select trigger_name from user_triggers
2 where table_name=upper(’student’);
TRIGGER_NAME
------------------------------
TG_INSERT
TG_UPDATESTUDENT
带有:old变量的行级delete触发器:
create or replace trigger tg_deletestudent
before delete on student
for each row
begin
dbms_output.put_line(’old is: ’||:old.stuid);
dbms_output.put_line(’old name: ’||:old.stuname);
end;
/
运行效果:
SQL》 delete from student;
old is: 202
old name: dongqian
old is: 101
old name: liudehua
old is: 102
old name: lingqingxia
old is: 103
old name: lichanggong
old is: 104
old name: zhenxiuwen
old is: 1001
old name: lilianjie
old is: 1009
old name: tongleifuck
old is: 203
old name: kfdj
old is: 209
old name: fuck
已删除9行
When的使用:如果在begin也就是说触发器的PL/SQL主体块执行前加上when(old.se=’f’)的话,DML操作照做不误,但是只会在删除
Se=’f’的那行的时候才会执行触发器的主体动作,执行效果:
SQL》 delete from student;
old is: 209
old name: fuck
已删除9行; 这里虽然删了9行,但是只执行了一次触发器的主体,做为一个行级触发器;
混合类型触发器:
Inserting,deleting,updating三个谓词可以分别指示当前操作到底是哪个;
create or replace trigger hunhetrigger
before insert or update or delete on student
for each row
begin
if inserting then
dbms_output.put_line(’insert le.........’);
end if;
if deleting then
dbms_output.put_line(’delete le .......’);
end if;
end;
/
插入的时候就自动判断当前动作为插入:
SQL》 insert into student values(303,’me’,’f’);
insert le.........
删除的时候就自动判断当前动作为删除:
SQL》 delete from student;
delete le .......
注意,既然触发器内部的主体PL/SQL是语句,那么它同样也可以是插入删除操作而不一定只是dbms_output打印一些信息;
这正是日志表的原理:在用户执行了DML语句的时候触发主体为插入日志表以记录操作轨迹的触发器;
为什么用触发器? 当我们有两个表用来记录商品的出库入库情况,good_store用来记录库存的产品类别和数量,
而good_out用来记录出库的产品类别和数量,那么每当我们出库的某个类别的产品一定数量的时候,我们应该在good_out中插入该产品的类别和
出库数量,而同时也应该在good_store表中用update来更新库存的相应类别的产品的数量;这就交给了我们两个必须完成的任务:插入good_out
表后更新good_store表,这样的手工过程使得我们觉得非常ugly,如果只做其中一个那造成数据的不一致;所以现在我们可以用触发器,在
Good_out表的插入操作上绑定一个对good_store进行更新的触发器;当然这个过程应该是一个事务,你不必担心插入good_out表执行了,而绑定在这个动作上的触发器操作不会执行,相信Oracle设计为原子性了;
注意:触发器会使得原来的SQL语句速度变慢;
替代触发器:
创建在视图上的触发器,就是替代触发器,只能是行级触发器;
为什么要用替代触发器?
假如你有一个视图是基于多个表的字段连接查询得到的;现在如果你想直接对着这个视图insert;那你一定在想,我对视图的插入操作
怎么来反应到组成这个视图的各个表中呢?事实上,除了定义一个触发器来绑定在对视图上的插入动作上外,你没有别的办法通过系统的报错而直接向视图中插入数据;这就是我们用替代触发器的原因;替换的意思实际上是触发器的主体部分把对视图的插入操作转换成详细的对各个表的插入;
变异表:变异表就是当前SQL语句正在修改的表,所以在一个变异表上绑定的触发器不可以使用cout()函数,原因很简单:SQL语句刚刚修改了表,你怎么统计??
约束表:
维护:
Alter trigger …..disenable; 使得触发器不可用;
Alter trigger ……enable; 开启触发器;
Oracle的内置程序包
扩展数据库的功能;
为PL/SQL提供对SQL功能的访问;
一般具有sys权限的高级管理人员使用;
一个典型的程序包就是dbms_output,你老是用它的过程put_line();
Dbms_standard 提供语言工具;
Dbms_lob操作Oracle LOB;就是针对大型数据的操作设计的;
Dbms_lock用户定义的锁;
Dbms_job 允许对PL/SQL过程进行调度;
Dbms_alert 支持数据库事件的异步通知;
1,dbms_output的一些过程:
a):enable
b):disable
c):put只是把数据放到缓存(SQL-Plus的缓存,实际就是整个窗口)中,无输出功能;
d):put_line可以使得以前放在缓存中所有数据输出;并且换到下一行;
e):new_line
f):get_line
g):get_lines
2,dmbs_lob ,这个包只能是由系统管理员来操作;
Clob以字符数据存储可达2G;
Blob以二进制数据存储可达4G;
Nclob以unicode字符存储;
一个文件下载列表的例子:
创建下载目录表:
create table downfilelist
(
id varchar(20) not null primary key,
name varchar(40) not null,
filelocation bfile,
description clob
)
/
创建目录:
create or replace directory filedir as ’f:\oracle’
/只是向Oralce注册了目录,实际上并不会真的建立目录在磁盘上;Oracle无权管理和锁定操作系统的文件系统;
向目录表中插入数据:
insert into downfilelist
values(’10001’,’oracle plsal编程指南’,bfilename(upper(’filedir’),’demo.mp3’),’this is a mp3 music’)
insert into downfilelist
values(’10002’,’java 大权’, bfilename(upper(’filedir’),’x.jpg’),’good super girl’)
/在filedir的目录f:\oracle下实际存储着demo.mp3 ,x.jpg;
注意,如果你试图查询,效果是 :
sys》select * from downfilelist;
SP2-0678: 列或属性类型无法通过 SQL*Plus 显示
因为第三列是无法显示的,是一个二进制的;
下面使用dbms_lob的一些过程来进行操作:
1,read过程
declare
tempdesc clob;
ireadcount int;
istart int;
soutputdesc varchar(100);
begin
ireadcount:=5;
istart:=1;
select description into tempdesc from downfilelist where id=’10001’;
dbms_lob.read(tempdesc,ireadcount,istart,soutputdesc); 把clob类型的tempdesc中的数据读到字符类型的soutputdesc里;
dbms_output.put_line(’Top 5 character is: ’||soutputdesc);
end;
/注意,对unicode来说,汉字和字母所占的位数是一样的;
2,getlength函数
select description into tempclob from downfilelist where id=‘10001’;
ilen:=dbms_lob.GetLength(tempclob);
append,copy……..
发现这样的现象:select x into y的时候,y并不是独立于x的拷贝,因为当修改y的时候x也被修改了;
3, fileexists函数
select id ,dbms_lob.fileexists(filelocation) from downfilelist;
如果在bfile类型字段filelocation指定的系统下的目录中存在filelocation指定的系统文件,则返回int 1,否则返回0;
这说明Oracle还是可以检测到系统的文件情况的,如同java.io包里的类一样;
对bfile类型数据的操作函数有fileisopen,fileopen,fileclose等等;
如果对您有帮助,请记得采纳为满意答案,谢谢!祝您生活愉快!
vaela
SQL语句创建update触发器
create trigger up_salary on employee INSTEAD OF update
as if update (salary)
begin
declare @newSalary numeric(10,2)
declare @oldSalary numeric(10,2)
select @newSalary = salary from updated
select @oldSalary = salary from employee where emp_id = (select emp_id from updated)
if @newSalary 》 @oldSalary * 1.1
print ’工资变动不能超过原来工资的10%’
else
update employee set salary = @newSalary where emp_id = (select emp_id from updated)
end
go
sql 触发器update问题
触发器有两个临时表,inserted、deleted
inserted中存的是本次触发,更新后的数据、以及新增的数据
deleted中存的是本次触发,更新前的数据、以及删除的数据
如果你cno不是主键,那么inserted和deleted关联一下,那么就能知道更改前的cno和更改后的cno
如果你的cno是主键,如果可以保证每次都是单条记录的更新,那么inserted和deleted里只有一条数据;如果是多条记录更新,暂时么啥想法。。。
SQL 触发器 update 为什么执行两次
触发器执行顺序根据 before 和 after 关键字决定。
使用before 关键字:触发器的执行是在数据的插入.更新或删除之前执行的。
使用after关键字:触发器的执行是在数据的插入.更新或删除之后执行的。
mysql触发器实现oracle物化视图示例代码
oracle数据库支持物化视图--不是基于基表的虚表,而是根据表实际存在的实表,即物化视图的数据存储在非易失的存储设备上。
下面实验创建ON
COMMIT
的FAST刷新模式,在mysql中用触发器实现insert
,
update
,
delete
刷新操作
1、基础表创建,Orders
表为基表,Order_mv为物化视图表
复制代码
代码如下:
mysql》
create
table
Orders(
-》
order_id
int
not
null
auto_increment,
-》
product_name
varchar(30)not
null,
-》
price
decimal(10,0)
not
null
,
-》
amount
smallint
not
null
,
-》
primary
key
(order_id));
Query
OK,
0
rows
affected
mysql》
create
table
Order_mv(
-》
product_name
varchar(30)
not
null,
-》
price_sum
decimal(8.2)
not
null,
-》
amount_sum
int
not
null,
-》
price_avg
float
not
null,
-》
order_cnt
int
not
null,
-》
unique
index(product_name));
Query
OK,
0
rows
affected
2、insert触发器
复制代码
代码如下:
delimiter
$$
create
trigger
tgr_Orders_insert
after
insert
on
Orders
for
each
row
begin
set
@old_price_sum=0;
set
@old_amount_sum=0;
set
@old_price_avg=0;
set
@old_orders_cnt=0;
select
ifnull(price_sum,0),ifnull(amount_sum,0),ifnull(price_avg,0),ifnull(order_cnt,0)
from
Order_mv
where
product_name=new.product_name
into
@old_price_sum,@old_amount_sum,@old_price_avg,@old_orders_cnt;
set
@new_price_sum=@old_price_sum+new.price;
set
@new_amount_sum=@old_amount_sum+new.amount;
set
@new_orders_cnt=@old_orders_cnt+1;
set
@new_price_avg=@new_price_sum/@new_orders_cnt;
replace
into
Order_mv
values(new.product_name,@new_price_sum,@new_amount_sum,@new_price_avg,@new_orders_cnt);
end;
$$
delimiter
;
3、update触发器
复制代码
代码如下:
delimiter
$$
create
trigger
tgr_Orders_update
before
update
on
Orders
for
each
row
begin
set
@old_price_sum=0;
set
@old_amount_sum=0;
set
@old_price_avg=0;
set
@old_orders_cnt=0;
set
@cur_price=0;
set
@cur_amount=0;
select
price,amount
from
Orders
where
order_id=new.order_id
into
@cur_price,@cur_amount;
select
ifnull(price_sum,0),ifnull(amount_sum,0),ifnull(price_avg,0),ifnull(order_cnt,0)
from
Order_mv
where
product_name=new.product_name
into
@old_price_sum,@old_amount_sum,@old_price_avg,@old_orders_cnt;
set
@new_price_sum=@old_price_sum-@cur_price+new.price;
set
@new_amount_sum=@old_amount_sum-@cur_amount+new.amount;
set
@new_orders_cnt=@old_orders_cnt;
set
@new_price_avg=@new_price_sum/@new_orders_cnt;
replace
into
Order_mv
values(new.product_name,@new_price_sum,@new_amount_sum,@new_price_avg,@new_orders_cnt);
end;
$$
delimiter
;
4、delete触发器
复制代码
代码如下:
delimiter
$$
create
trigger
tgr_Orders_delete
after
delete
on
Orders
for
each
row
begin
set
@old_price_sum=0;
set
@old_amount_sum=0;
set
@old_price_avg=0;
set
@old_orders_cnt=0;
set
@cur_price=0;
set
@cur_amount=0;
select
price,amount
from
Orders
where
order_id=old.order_id
into
@cur_price,@cur_amount;
select
ifnull(price_sum,0),ifnull(amount_sum,0),ifnull(price_avg,0),ifnull(order_cnt,0)
from
Order_mv
where
product_name=old.product_name
into
@old_price_sum,@old_amount_sum,@old_price_avg,@old_orders_cnt;
set
@new_price_sum=@old_price_sum
-
old.price;
set
@new_amount_sum=@old_amount_sum
-
old.amount;
set
@new_orders_cnt=@old_orders_cnt
-
1;
if
@new_orders_cnt》0
then
set
@new_price_avg=@new_price_sum/@new_orders_cnt;
replace
into
Order_mv
values(old.product_name,@new_price_sum,@new_amount_sum,@new_price_avg,@new_orders_cnt);
else
delete
from
Order_mv
where
product_name=@old.name;
end
if;
end;
$$
delimiter
;
5、这里delete触发器有一个bug,就是在一种产品的最后一个订单被删除的时候,Order_mv表的更新不能实现,不知道这算不算是mysql的一个bug。当然,如果这个也可以直接用sql语句生成数据,而导致的直接后果就是执行效率低。
复制代码
代码如下:
-》
insert
into
Order_mv
-》
select
product_name
,sum(price),sum(amount),avg(price),count(*)
from
Orders
-》
group
by
product_name;
在触发器里多次更新记录时update触发器执行几次
如果是行级触发器(for
each
row),则每更新一行触发一次。
如果是语句级,则一条update语句触发一次(即使这条语句更新多行,也只触发一次)。
mysql 实现每月更新一次的触发器问题
1、触发器是update后激发的,我想你需要的是mysql计划任务。
2、计划任务状态
show variables like ’%event%’;
3、使用下列的任意一句开启计划任务:
SET GLOBAL event_scheduler = ON;
SET @@global.event_scheduler = ON;
SET GLOBAL event_scheduler = 1; -- 0代表关闭
SET @@global.event_scheduler = 1;
4、创建event语法
help create event
5、实例
实例0:
每5分钟删除sms表上面ybmid为空白且createdate距现时间超过5分钟的数据。
USE test;
CREATE EVENT event_delnull
ON SCHEDULE
EVERY 5 MINUTE STARTS ’2012-01-01 00:00:00’ ENDS ’2012-12-31 00:00:00’
DO
DELETE FROM sms WHERE ybmid=’’ AND TIMEDIFF(SYSDATE(),createdate)》’00:05:00’;
实例1:
每天调用存储过程一次:
mysql》 delimiter //
mysql》 create event updatePTOonSunday
-》 on schedule every 1 day
-》 do
-》 call updatePTO();
-》 //
Query OK, 0 rows affected (0.02 sec)
这里updatePTO()是数据库里自定义的存储过程
6、查看任务计划:
SELECT * FROM mysql.event\G

更多文章:
dropdownlist 绑定(DropDownList 绑定所有项 并 显示指定项)
2026年10月11日 08:50
易语言网页api接口怎么调用(易语言,怎么读取网页json的api)
2026年10月11日 08:00
majority of(the majority of 和 a majority of的区别以及用法例句)
2026年10月11日 07:40
another time(another time和other time的区别)
2026年10月11日 05:00






