触发器的基本使用

EXISTS()在触发器中比较常用 用来判断有无返回查询的数据行 如果有 返回true 否则 false

有三种触发器 1.是for触发器
2.是after触发器: for触发器属于after触发器 所以基本上直接用after触发器就好了
3.before触发器
4.instead of触发器

after触发器后面可以跟insert,update,delete等简单的操作,意思就是说 当发生了insert,update,delete的sql语句后 就会触发事件 执行某个事件 接下来看一下实例;

两张表之间的联系:  当插入users表一条数据的时候  系统自动往insertRecord插入数据
create trigger
mytrigger
on Users
after insert     AFTER 指定触发器仅在触发 SQL 语句中指定的所有操作都已成功执行时才被触发
as
insert into InsertRecord(UserName,Age,Gender,[Address]) select UserName,Age,Gender,[Address] from inserted

insert into Users(UserName,Age,Gender,[Address]) values('关晓彤1','19','女','北京');             触发器在Users这里  所以执行这个操作才可以执行上面那个插入语句


这是当对 users进行更新的时候   会往UpdateRecord插入数据
create trigger
mytrigger1
on Users
after update
as
insert into UpdateRecord(UserName,Age,Gender,[Address]) select UserName,Age,Gender,[Address] from deleted;
这里为什么不用 values  因为  这是数据迁移  从一张表上迁移到另一张表 而values是插入数据里面放的是数据  而  select存放的是字段
//字段和关键字重名要用[]括起来   不然会报错

update Users set Age=20 where UserName='关晓彤';   insertupdate先后顺序不要紧
instead of触发器:

create trigger
mytrigger2
on Users
instead of insert
as
if
datename(week,getdate()) in ('星期六','星期天') or (datepart(hour,getdate()) not  between 9 and 15)              //datename是函数返回 某一结果 getdate()返回字符串
begin
print '非工作时间,不允许插入数据';
rollback;
end

insert into Users (UserName,Gender) values('张三丰','男');

alter table Users enable trigger mytrigger;        //enable是启用    名叫mytrigger的触发器 
DISABLE则相反

总结:
1.after insert等 意思就是说在执行after操作后 执行指定的操作
2.before insert等 意思实在执行insert操作之前执行操作 比如删除主键的前提要先删除对应的外键,所以得用before触发器
3.instead of触发器是包涵判断条件的。
4.INSTEAD OF 触发器用来代替通常的触发动作,即当对表进行INSERT、UPDATE 或 DELETE 操作时,系统不是直接对表执行这些操作,而是把操作内容交给触发器,让触发器检查所进行的操作是否正确。如正确才进行相应的操作。
5. 每一个表上只能创建一个 INSTEAD OF 触发器,但可以创建多个 AFTER 触发器。
6. Instead Of 触发器可以进行以下操作:
• 忽略批处理中的某些部分。
•不处理批处理中的某些部分并记录有问题的行。
•如果遇到错误情况则采取备用操作。

<think>我们正在讨论Oracle触发器中如何声明和使用变量。根据引用[1]和[2],我们可以总结如下: 在Oracle触发器中,声明变量的位置在触发器定义的DECLARE部分(如果有的话)。但需要注意的是,触发器有两种类型:行级触发器和语句级触发器。在行级触发器使用FOR EACH ROW)中,我们可以使用:OLD和:NEW来引用当前行的旧值和新值,同时也可以在DECLARE部分声明变量。 触发器基本结构: ```sql CREATE [OR REPLACE] TRIGGER trigger_name BEFORE | AFTER | INSTEAD OF [INSERT] [OR] | [UPDATE] [OR] | [DELETE] [OF column_name] ON table_name [REFERENCING OLD AS old NEW AS new] [FOR EACH ROW] -- 如果指定则为行级触发器,否则为语句级触发器 [WHEN (condition)] DECLARE -- 这里声明变量 variable_name datatype [:= initial_value]; BEGIN -- 触发器逻辑 END; ``` 在DECLARE部分,我们可以声明变量,然后在BEGIN和END之间的代码块中使用这些变量。 例如,根据引用[2]中的示例,在触发器内部我们可以这样使用变量: ```sql CREATE OR REPLACE TRIGGER Test_Tri AFTER INSERT ON Test FOR EACH ROW DECLARE v_class VARCHAR2(4); -- 声明一个变量 BEGIN -- 使用变量 IF :new.iValue > 90 THEN v_class := 'A'; -- 给变量赋值 INSERT INTO Test_log VALUES (:new.iKey, v_class); END IF; END; ``` 注意:在行级触发器中,我们可以使用:OLD和:NEW伪记录来访问行的旧值和新值。在语句级触发器中则不能使用。 另外,在触发器中也可以使用常量、游标等。 总结一下步骤: 1. 在触发器定义的DECLARE部分声明变量(可选)。 2. 在BEGIN和END之间的代码块中使用这些变量,包括赋值和读取。 3. 注意变量的作用域只在当前触发器的代码块中。 如果触发器不需要变量,可以省略DECLARE部分。 在引用[2]中还有一个模式级触发器的例子,其中没有使用变量,但同样可以在DECLARE部分声明变量。 注意:在触发器中声明的变量不能与:NEW或:OLD中的列名相同,否则可能会引起混淆。 例如,如果我们有一个列名为`v_class`,那么我们在触发器中声明变量`v_class`就会覆盖列名,此时应该避免。通常,我们可以通过给变量加前缀(如`v_`)来避免这种冲突。 另外,在触发器中给变量赋值使用`:=`操作符。 所以,用户可以在触发器的DECLARE部分声明变量,然后在触发器体中像在PL/SQL块中一样使用它们。 §§相关问题§§ 1. Oracle触发器中的:OLD和:NEW伪记录有什么使用限制? 2. 在Oracle触发器中如何声明和使用游标? 3. Oracle触发器中的异常处理应该如何实现?</think>### Oracle触发器中声明和使用变量的方法 在Oracle触发器中声明和使用变量的语法如下: ```sql CREATE [OR REPLACE] TRIGGER trigger_name BEFORE|AFTER INSERT|UPDATE|DELETE ON table_name [FOR EACH ROW] -- 行级触发器 DECLARE -- 变量声明区域 variable_name1 DATATYPE [:= initial_value]; -- 声明变量并可选初始化 variable_name2 DATATYPE; BEGIN -- 变量使用区域 variable_name1 := value; -- 变量赋值 :NEW.column_name := expression; -- 修改新值 DBMS_OUTPUT.PUT_LINE(variable_name1); -- 使用变量 END; ``` #### 关键语法说明: 1. **声明位置** 在`DECLARE`和`BEGIN`之间声明变量,支持所有PL/SQL数据类型: ```sql DECLARE v_count NUMBER := 0; -- 数字类型 v_status VARCHAR2(10) := 'NEW'; -- 字符串类型 v_date DATE := SYSDATE; -- 日期类型 ``` 2. **变量赋值** 使用`:=`操作符在`BEGIN-END`块内赋值: ```sql BEGIN v_count := :OLD.quantity * 2; -- 使用旧值计算 v_status := 'UPDATED'; -- 直接赋值 END; ``` 3. **结合:OLD/:NEW伪记录** 在行级触发器中访问数据变更: ```sql CREATE TRIGGER salary_audit BEFORE UPDATE ON employees FOR EACH ROW DECLARE v_diff NUMBER; BEGIN v_diff := :NEW.salary - :OLD.salary; -- 计算差值 IF v_diff > 10000 THEN INSERT INTO audit_log VALUES ('Excessive raise', SYSDATE); END IF; END; ``` #### 注意事项: - 行级触发器(`FOR EACH ROW`)才能使用`:OLD`和`:NEW`伪记录[^1] - 变量作用域仅限于当前触发器 - 使用`DBMS_OUTPUT`调试时需确保服务器输出已启用 - 避免在触发器中进行耗时操作以免影响性能 > 示例:根据订单金额自动计算折扣 > ```sql > CREATE TRIGGER order_discount > BEFORE INSERT ON orders > FOR EACH ROW > DECLARE > v_discount_rate NUMBER; > BEGIN > IF :NEW.amount > 1000 THEN > v_discount_rate := 0.15; -- 15%折扣 > ELSE > v_discount_rate := 0.05; -- 5%折扣 > END IF; > :NEW.discount := :NEW.amount * v_discount_rate; > END; > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值