Oracle两表同步的触发器写法

该博客介绍了如何使用Oracle数据库的触发器实现两个表之间的数据同步,包括备份、操作日志记录以及针对插入、删除、更新操作的具体处理。通过创建触发器Tri_BDC_XMNDZFW和Tri_BDC_XMNDZFW_MX,实现实时的数据变更同步到备份表,并记录变更日志。
select * from BDC_XMNDZFW;

select * from BDC_XMNDZFW_MX;

----复制备份表(若果想要备份的功能,可令条件为1=1
Create Table BDC_XMNDZFW_Backup As select * from BDC_XMNDZFW Where 1=2;
Create Table BDC_XMNDZFW_MX_Backup As select * from BDC_XMNDZFW_MX Where 1=2;

--创建操作日志表
Drop Table ChgLogTab;

create Table ChgLogTab
(
       TableName Varchar2(32),
       ForeignKey Varchar2(50),
       MainKey Varchar2(36),
       DMLType Varchar2(8),
       DMLTime DATE,
       PersonName VARCHAR2(30),
       ProgramExe VARCHAR2(64),
       HostMachine Varchar2(64),
       IpAddr CHAR(15)
);


Select * from ChgLogTab;
Delete From ChgLogTab;
------------------------------------------------------------------
---不授权给用户,触发器就没法看到这张表
sys as sysdba;
grant select on V_$SESSION to BDCDJ_ZF;
------------------------------------------------------------------

--------无效的主机名绑定变量:解决方案,Values的参数列表中缺少一个分隔符(,)
Create or Replace Trigger Tri_BDC_XMNDZFW
Before insert or delete or update on BDC_XMNDZFW for each row
Declare
TabName Varchar2(32);
ForeignKey Varchar2(50);
MainKey Varchar2(36);
DMLType Varchar2(8);
PersonName VARCHAR2(30);
ProgramExe VARCHAR2(64);
HostMachine VARCHAR2(64);
IpAddr CHAR(15);
DMLTime Date;
strTable Varchar(32);
strSql Varchar(1024);
Begin
      TabName := 'BDC_XMNDZFW';
      strTable := TabName||'_Backup';
      ForeignKey := null;
      MainKey := null;
      select username into PersonName from v$session where audsid = userenv('sessionid');
      select program into ProgramExe from v$session where audsid = userenv('sessionid');
      select machine into HostMachine from v$session where audsid = userenv('sessionid');
      select sys_context('userenv','ip_address') into IpAddr from v$session where audsid = userenv('sessionid');
      select sysdate into DMLTime from dual;
      --select username in
<think>首先,用户的问题是:“我想查找关于Oracle数据库中触发器INSERT语句的写法或示例请问oracle触发器insert语句示例写法”。这是在问Oracle触发器中针对INSERT操作的触发器写法和示例。系统指令中提到:用户提供了引用[^1]、[^2]和[^3],我需要参考这些引用。这些引用是关于Oracle触发器的内容。-引用[^1]:提到了触发器的基本语法:`create[orreplace]trigger触发器名before|afterinsert|delete|updateon名[foreachrow]...`。还提到了删除触发器的命令:`droptrigger触发名;`。-引用[^2]:区分了行级触发器触发器。行级触发器针对每一行触发一次,触发器只触发一次。解释了before和after的使用。-引用[^3]:这部分似乎不是关于Oracle触发器的,而是关于学习网页开发基础的。它说“学习html5、css、javascript这些基础知识...”,然后提到了JavaScript的高级程序设计书。这不相关!用户的问题是关于Oracle触发器的INSERT语句写法和示例,所以[^3]的内容是无关的,我应该忽略它。用户说“上述引用仅供参考”,所以我需要聚焦在相关部分。用户的需求是:“我想查找关于Oracle数据库中触发器INSERT语句的写法或示例”,所以我需要提供一个针对INSERT操作的触发器的示例写法。系统指令还要求:-所有行内数学达式用$...$格式,但这里可能没有数学达式,因为这是关于数据库的。-独立公式用$$...$$格式单独成段,同样可能不需要。-LaTeX语法正确。-使用中文回答。-生成相关问题。-在引用段落末尾添加引用标识。用户上一次的问题和我的回答:用户上一次的问题是快速排序,这似乎无关,因为用户现在是在问数据库触发器。所以可能没有直接的上下文联系。用户说“请尽可能多的参考用户上一次的问题和你的回答”,但上一个回答是关于快速排序的算法,不相关。所以我应该忽略那部分,专注于当前问题。结构化我的回答:1.**回答结构清晰**:帮助用户逐步解决问题。我应该解释触发器的概念,针对INSERT操作的具体语法,并给出示例写法。2.**示例写法**:用户想要INSERT语句的触发器示例,所以我需要创建一个简单易懂的示例。包括触发器的创建、删除等。-语法:基于引用[^1],触发器的基本语法是:```create[orreplace]trigger触发器名before|afterinsert|delete|updateon名[foreachrow]declare--声明变量begin--触发器的执行语句end;```对于INSERT操作,我会专注于before或afterinsert。-类型:行级触发器(foreachrow)触发器。行级触发器更适合在插入每行时执行操作。-示例:给一个简单的例子,比如在插入新记录时自动记录日志或验证数据。3.**生成相关问题**:在回答后,添加相关问题,如用户之前的示例。4.**引用标识**:在引用的段落末尾添加[^1]或[^2]。引用[^3]不相关,所以我不能使用它。示例相关的问题:-如何创建行级插入触发器?-插入触发器中如何使用变量?-删除触发器的命令是什么?确保答案真实可靠:基于我的知识,Oracle触发器的标准写法是使用PL/SQL。构建回答:-介绍Oracle触发器针对INSERT操作的写法和示例。-解释语法。-给一个完整的示例。-使用引用标识。-结尾生成相关问题。</think> ### Oracle 触发器中INSERT语句的写法和示例 在Oracle数据库中,触发器是一种特殊的过程,它会在指定的数据操作(如INSERT、DELETE或UPDATE)发生时自动执行。用户询问针对INSERT操作的触发器写法和示例,我将基于提供的引用内容[^1][^2]进行解释,并提供清晰、逐步的指导。触发器的核心语法包括定义触发时机(BEFORE或AFTER)、触发事件(如INSERT),以及是否使用行级触发(针对每行数据)。以下是详细解答。 #### 触发器的基本语法和解释 根据引用[^1],Oracle触发器的通用语法如下: - **语法结构**: ```sql CREATE [OR REPLACE] TRIGGER 触发器名 BEFORE|AFTER INSERT | DELETE | UPDATE ON 名 [FOR EACH ROW] -- 可选,定义行级触发 DECLARE -- 声明变量(可选) BEGIN -- 触发器的执行语句(可以是SQL或PL/SQL代码) END; ``` - **关键参数解释**: - `BEFORE`或`AFTER`:指定触发器在事件之前或之后执行。例如,`BEFORE INSERT` 在插入数据前触发,适用于数据验证;`AFTER INSERT` 在插入后触发,适合日志记录。 - `FOR EACH ROW`:如果指定,则是**行级触发器**(引用[^2]中定义为“行级触发器会对数据库中的受影响的每一行触发一次触发器代码”)。若不指定,则是语句级触发器(只触发一次)。 - 触发事件:这里针对`INSERT`,触发器只在插入操作时触发。 - 执行语句:可以在`BEGIN...END`块中编写PL/SQL代码,如检查条件、插入日志或修改其他。 - **删除触发器命令**: ```sql DROP TRIGGER 触发器名; ``` 这用于删除已创建的触发器[^1]。 针对INSERT操作,触发器常用于自动填充默认值、数据验证或审计日志。下面我提供一个完整的行级触发器示例。 #### INSERT触发器的示例写法 假设场景:我们有一个员工(`employees`),希望在每次插入新员工记录前(`BEFORE INSERT`)自动计算并设置员工的年龄(基于出生日期),如果年龄小于18岁则阻止插入。 1. **创建(如果不存在)**: ```sql CREATE TABLE employees ( emp_id NUMBER PRIMARY KEY, emp_name VARCHAR2(50), birth_date DATE, emp_age NUMBER ); ``` 2. **创建行级INSERT触发器**: 这是一个`BEFORE INSERT`行级触发器(`FOR EACH ROW`),它在每行数据插入前执行。示例中使用PL/SQL计算年龄,并通过`:NEW`伪行记录引用新数据。 ```sql CREATE OR REPLACE TRIGGER trg_before_insert_employee BEFORE INSERT ON employees FOR EACH ROW -- 行级触发,确保每行插入时执行 DECLARE v_age NUMBER; -- 声明变量用于存储年龄 BEGIN -- 计算年龄(基于当前日期和出生日期) v_age := TRUNC(MONTHS_BETWEEN(SYSDATE, :NEW.birth_date) / 12); -- 设置新记录的年龄字段 :NEW.emp_age := v_age; -- 验证年龄,如果小于18岁则抛出异常阻止插入 IF v_age < 18 THEN RAISE_APPLICATION_ERROR(-20001, '员工年龄必须大于或等于18岁!'); END IF; END; ``` **代码解析**: - 触发器名:`trg_before_insert_employee`,针对`employees`的`INSERT`事件。 - `:NEW.birth_date` 引用新插入行的出生日期字段。 - `RAISE_APPLICATION_ERROR` 在验证失败时引发错误,取消插入操作。 - 此触发器在插入前计算年龄并验证,防止非法数据[^1][^2]。 3. **测试触发器**: - 插入合法数据(年龄≥18): ```sql INSERT INTO employees (emp_id, emp_name, birth_date) VALUES (1, '张三', TO_DATE('1990-01-01', 'YYYY-MM-DD')); -- 成功插入,emp_age 将自动设置为34(假设当前年为2024) ``` - 插入非法数据(年龄<18): ```sql INSERT INTO employees (emp_id, emp_name, birth_date) VALUES (2, '李四', TO_DATE('2010-01-01', 'YYYY-MM-DD')); -- 触发错误:ORA-20001: 员工年龄必须大于或等于18岁! ``` 4. **删除触发器**(如果需要): ```sql DROP TRIGGER trg_before_insert_employee; ``` #### 注意事项和最佳实践 - **行级 vs 触发器**:针对INSERT操作时,行级触发器(`FOR EACH ROW`)更常用,因为它能操作每行数据(如使用`:NEW`伪行记录)。语句级触发器(省略`FOR EACH ROW`)只触发一次,适合批量操作[^2]。 - **性能考虑**:行级触发器可能影响插入性能,避免在触发器中包含复杂逻辑。使用`BEFORE`时机进行验证可减少无效数据插入。 - **调试和错误处理**:使用`DBMS_OUTPUT.PUT_LINE`在触发器中添加日志输出,便于调试。 - **参考资源**:Oracle官方文档提供更多触发器示例,或参考在线资源如同步应用案例[^2]。 如果您有其他具体需求,如触发器中处理多个或使用游标,我可以进一步优化示例。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值