`
hanjian861202
  • 浏览: 165112 次
  • 性别: Icon_minigender_1
  • 来自: 南京
文章分类
社区版块
存档分类
最新评论

Oracle级联删除yu级联更新

阅读更多

SQL与ORACLE的外键约束--级联删除

最近软件系统中要删除一条记录,就要关联到同时删除好多张表,他们之间还存在着约束关系.所以考虑到在创建表时加上约束关系,具体如下:

SQL的外键约束可以实现级联删除与级联更新;

ORACLE则只充许级联删除。

SQL级联删除与级联更新使用格式:
CREATE TABLE A001(ID INT PRIMARY KEY,NAME VARCHAR(20))
CREATE TABLE A002(ID INT REFERENCES A001(ID)ON DELETE CASCADE ON UPDATE CASCADE,AGE TINYINT)

ORACLE级联删除使用格式:
CREATE TABLE A001(ID INT PRIMAY KEY,NAME VARCHAR2(20))
CREATE TABLE A002(ID INT REFERENCES A001(ID)ON DELETE CASCADE,AGE NUMBER(2,0))


--------------
CREATE TABLE groups
(
id VARCHAR2(16) CONSTRAINT pk_groupid PRIMARY KEY,
name VARCHAR2(32),
description VARCHAR2(50)
)
TABLESPACE userspace;


CREATE TABLE usringrp
(
group_id VARCHAR2(16) CONSTRAINT fk_uing_grpid
REFERENCES groups(id)
ON DELETE CASCADE,
user_id VARCHAR2(16)
)
TABLESPACE userspace;

---------------
PowerDesigner
参照完整性约束


限制(Restrict)。不允许进行修改或删除操作。若修改或删除主表的主键时,如果子表中存在子记录,系统将产生一个错误提示。这是缺省的参照完整性设置。
置空(Set Null)。如果外键列允许为空,若修改或删除主表的主键时,把子表中参照的外键列设置为空值(NULL)。
置为缺省(Set Default)。如果指定了缺省值,若修改或删除主表的主键时,把子表中参照的外键设置为缺省值(Default)。
级联(Cascade)。把主表中主键修改为一个新的值时,相应修改子表中外键的值;或者删除主表中主键的记录时,要相应删除子表中外键的记录。

 

----------------------------------------------------------------------------------------------------------------------------------
     

触发器:就像程序里的goto一样,要谨慎使用。优点是可以在不改变源码的情况下使用来实现某些功能;缺点是可控性差。

      我平时比较少用触发器,主要是因为程序逻辑不对的时候不容易发现错误,有时数据量大了也可能产生性能上的问题,但这个东西总有用武之地,在很多场合还是会起到巨大的作用。
      这两天就遇到一个问题,有两张表的一个字段需要进行同步更新,也就是A表修改时要把对应的B表的记录字段修改,反过来B表修改时也要把A表的修改,保持两边数据的一个同步,这个可以在前台很容易的实现,但开发人员不想修改代码了,就考虑在后台用trigger实现。
     功能很简单,但在实现时遇到一个问题,就是A上的DML触发了上面的TRIGGER,然后这个TRIGGER去更新B表,这样
就会触发B表上的触发器,而B表上的TRIGGER又会更新A表,这样就迭代触发,没有结束了,也就是会产生变异表(mutating)
     我不知道ORACLE的触发器是否有属性来限制这种情况的发生,但以前做SQL SERVER时知道有种Instaed of的触发器,他表示当DML启动他后,他将以TRIGGER里的代码来代替这个DML动作,也就是DML不会真正的执行,只会启动INSTEAD TRIGGER,最终执行的是TRIGGER里面的编码。
     查看了Docs,看到ORACLE也支持这个类型的触发器,但这个只能建立到视图上,不能基于表建立,我要的功能肯定是可以实现的,在这里我把原表进行了rename,引如了两张视图,名字就是以前的表名,这样对于他们前台应用就做了个
透明的切换,然后在两个视图上建立INSTEAD触发器,将任何两个视图上的更新都传播到后面的两个基表,这样不管你更新那个视图,我都可以捕获到数据,以代码在后面更新,也不存在互相触发,因为触发器修改的对象已经转移到表了,而此时表上是没有trigger的,呵呵!!!

过程如下

--创建测试表
SQL> create table mytest1(row_num number,row_name varchar2(50));

表被创建

SQL> create table mytest2(row_num number,row_name varchar2(50));

表被创建

--测试数据
SQL> INSERT INTO MYTEST1 VALUES(1,'Fhhh!!!');

1 行 已插入

SQL> INSERT INTO MYTEST2 VALUES(1,'Watch your mouth!!!');

1 行 已插入

SQL> COMMIT;

提交完成

 

--先在一个表上创建触发器
SQL> CREATE OR REPLACE TRIGGER TRI_TEST1
2 BEFORE UPDATE
3 ON MYTEST1
4 FOR EACH ROW
5 DECLARE
6 lv_new VARCHAR2(20);
7 lv_parent VARCHAR2(20);
8 BEGIN
9 lv_new := :new.row_name;
10 lv_parent := :OLD.row_name;
11 IF lv_new <> lv_parent THEN
12 UPDATE MYTEST2
13 SET ROW_NAME = :NEW.ROW_NAME
14 WHERE ROW_NUM = :NEW.ROW_NUM;
15 END IF;
16 DBMS_OUTPUT.PUT_LINE(lv_new || lv_parent);
17 END;
18 /
触发器被创建

 

--测试更新
SQL> set serveroutput on
SQL> UPDATE MYTEST1 SET ROW_NAME = 'DO it!!!';
DO it!!! Fhhhh!!!

1 行 已更新

--更新成功
SQL> SELECT * FROM MYTEST2;

ROW_NUM ROW_NAME
---------- --------------------------------------------------
1 DO it!!!

 

--另外张表创建触发器
SQL> CREATE OR REPLACE TRIGGER TRI_TEST2
2 BEFORE UPDATE
3 ON MYTEST2
4 FOR EACH ROW
5 DECLARE
6 lv_new VARCHAR2(20);
7 lv_parent VARCHAR2(20);
8 BEGIN
9 lv_new := :new.row_name;
10 lv_parent := :OLD.row_name;
11 IF lv_new <> lv_parent THEN
12 UPDATE MYTEST1
13 SET ROW_NAME = :NEW.ROW_NAME
14 WHERE ROW_NUM = :NEW.ROW_NUM;
15 END IF;
16 DBMS_OUTPUT.PUT_LINE(lv_new || lv_parent);
17 END;
18 /

 

--产生了变异表,更新失败
SQL> update mytest1 set row_name = 'mouthkkkkkoo';

update mytest1 set row_name = 'mouthkkkkkoo'

ORA-04091: table MYTEST1 is mutating, trigger/function may not see it
ORA-06512: at "TRI_TEST2", line 8
ORA-04088: error during execution of trigger 'TRI_TEST2'
ORA-06512: at "TRI_TEST1", line 8
ORA-04088: error during execution of trigger 'TRI_TEST1'


--更新失败
SQL> update mytest2 set row_name = 'mouthkkkkkoo';

update mytest2 set row_name = 'mouthkkkkkoo'

ORA-04091: table MYTEST2 is mutating, trigger/function may not see it
ORA-06512: at "TRI_TEST1", line 8
ORA-04088: error during execution of trigger 'TRI_TEST1'
ORA-06512: at "TRI_TEST2", line 8
ORA-04088: error during execution of trigger 'TRI_TEST2'

--删除触发器
SQL> drop trigger TRI_TEST2;

触发器被删掉

SQL> drop trigger TRI_TEST1;

触发器被删掉


--创建视图
SQL> CREATE VIEW V_TEST1 AS SELECT * FROM MYTEST1;

视图被创建

SQL> CREATE VIEW V_TEST2 AS SELECT * FROM MYTEST2;

视图被创建

--基于视图创建Instead触发器
SQL> CREATE OR REPLACE TRIGGER TRI_TEST1
2 INSTEAD OF UPDATE
3 ON V_TEST1
4 FOR EACH ROW
5 DECLARE
6 lv_new VARCHAR2(20);
7 lv_parent VARCHAR2(20);
8 BEGIN
9 lv_new := :new.row_name;
10 lv_parent := :OLD.row_name;
11 IF lv_new <> lv_parent THEN
12 UPDATE MYTEST2
13 SET ROW_NAME = :NEW.ROW_NAME
14 WHERE ROW_NUM = :NEW.ROW_NUM;
15 UPDATE MYTEST1
16 SET ROW_NAME = :NEW.ROW_NAME
17 WHERE ROW_NUM = :NEW.ROW_NUM;
18 END IF;
19 DBMS_OUTPUT.PUT_LINE(lv_new || lv_parent);
20 END;
21 /
触发器被创建

SQL> CREATE OR REPLACE TRIGGER TRI_TEST2
2 INSTEAD OF UPDATE
3 ON V_TEST2
4 FOR EACH ROW
5 DECLARE
6 lv_new VARCHAR2(20);
7 lv_parent VARCHAR2(20);
8 BEGIN
9 lv_new := :new.row_name;
10 lv_parent := :OLD.row_name;
11 IF lv_new <> lv_parent THEN
12 UPDATE MYTEST2
13 SET ROW_NAME = :NEW.ROW_NAME
14 WHERE ROW_NUM = :NEW.ROW_NUM;
15 UPDATE MYTEST1
16 SET ROW_NAME = :NEW.ROW_NAME
17 WHERE ROW_NUM = :NEW.ROW_NUM;
18 END IF;
19 DBMS_OUTPUT.PUT_LINE(lv_new || lv_parent);
20 END;
21 /
触发器被创建

--功能已经实现
SQL> update v_test1 set row_name = 'I with you!!!';

1 行 已更新

SQL> commit;

提交完成

SQL> select * from v_test2;

ROW_NUM ROW_NAME
---------- --------------------------------------------------
1 I with you!!!


SQL> update v_test2 set row_name = 'Don't me!!!';

1 行 已更新

SQL> commit;

提交完成

SQL> select * from v_test1;

ROW_NUM ROW_NAME
---------- --------------------------------------------------
1 Don't me!!!

 

分享到:
评论

相关推荐

    Oracle数据库中的级联查询、级联删除、级联更新操作教程

    Oracle数据库中的级联查询、级联删除和级联更新是数据库设计中常用的操作,它们用于在多表关联的关系型数据库中实现数据的联动处理。在Oracle中,这些操作主要涉及外键约束和触发器。 首先,级联查询是通过自连接来...

    ajax+jQuery+ssh+oracle级联实例

    在IT行业中,构建高效、动态的Web应用是关键任务之一,而"ajax+jQuery+ssh+oracle级联实例"提供了一个具体的实现方案。这个实例涵盖了前端到后端的关键技术,包括异步数据交互(Ajax)、JavaScript库(jQuery)、...

    mysql级联更新和级联删除

    ### MySQL级联更新与级联删除详解 在数据库设计中,外键约束是维护数据完整性和一致性的重要手段之一。MySQL的InnoDB存储引擎支持多种不同的处理外键的方式,包括级联更新(Cascade Update)和级联删除(Cascade ...

    hibernate many-to-many级联保存,级联更新,级联删除

    本文将深入探讨如何在Hibernate中处理Many-to-Many关系的级联保存、级联更新和级联删除。 一、Many-to-Many关系基础 在数据库设计中,Many-to-Many关系意味着两个实体之间存在多对多的关系。例如,学生可以选修多门...

    解析Oracle中多表级联删除的方法

    在Oracle数据库中,多表级联删除是一种常见的需求,特别是在数据关系复杂的环境中。级联删除允许在删除一个表中的记录时,自动删除依赖于该记录的其他表中的相关记录。以下将详细介绍三种在Oracle中实现多表级联删除...

    用JDBC实现数据库的级联删除与更新

    根据给定文件的信息,本文将围绕“用JDBC实现数据库的级联删除与更新”这一主题进行深入探讨,包括理解需求、设计思路、具体实现步骤以及相关代码示例。 ### 1. 需求理解 #### 1.1 业务场景 在本案例中,存在两个...

    Oracle Adf级联菜单过滤

    在Oracle ADF中,级联菜单(Cascading Menus)是常见的一种交互元素,尤其在处理多表关联数据时非常实用。级联菜单允许用户在选择一个选项后,根据该选项的值动态地过滤下一级菜单的内容,这样可以提供更加直观和...

    MySQL中利用外键实现级联删除、更新

    "MySQL 中利用外键实现级联删除、更新" 在 MySQL 中,外键是指在一个表中的一列或多列,引用另一个表中的主键或唯一索引。外键可以强制实施数据的一致性和完整性,使得数据更加可靠。外键在 MySQL 中的实现主要是...

    级联删除笔记【自用0分】

    级联删除和级联更新是数据库管理中非常重要的概念,特别是在多表关联的情况下,能够确保数据的一致性和完整性。本文将详细介绍如何在SQL Server中实现级联更新和级联删除,包括通过触发器的方式和使用外键约束的方式...

    实现年月日的级联更新

    在IT领域,级联更新(Cascading Updates)是一种数据库管理技术,用于当某一字段的值发生改变时,自动更新依赖于该字段的其他相关记录。这种机制在数据一致性、关联性和完整性方面扮演着关键角色,尤其在多表关联的...

    qt实现sqlite3级联删除demo

    【标题】:“qt实现sqlite3级联删除demo” 在数据库管理中,级联删除是一种常见的功能,它允许在删除一个表中的记录时,自动删除与之相关联的其他表中的记录。在Qt环境下,结合SQLite3数据库,我们可以实现这一功能...

    SQL server创建触发器实现级联删除

    ### SQL Server 创建触发器实现级联删除 在数据库管理中,触发器是一种特殊类型的存储过程,它被设计为响应特定的事件(如插入、更新或删除数据)而自动执行。本文将详细介绍如何在 SQL Server 中创建一个触发器来...

    javaScript下拉列表级联更新

    在javaScript中使下拉列表实现级联更新

    存储过程-游标-级联删除

    在数据库管理中,级联删除是一种常见的操作,它涉及到一个表中的记录被删除时,与之关联的其他表中的记录也会自动被删除。在大型数据库系统中,这种功能通常通过外键约束来实现,但在某些情况下,如需要自定义删除...

    mybatis关联/级联以及动态sql

    MyBatis支持级联保存、更新和删除。这可以通过在Mapper接口的方法上使用`@Cascade`注解或者在XML映射文件中使用`&lt;cascade&gt;`标签来实现。 接着,我们来看动态SQL。动态SQL是MyBatis的一个强大特性,它允许我们在SQL...

    MSserver自关联表的级联删除

    然而,自关联表的级联删除并不像简单的外键级联删除那样直接,因为它涉及到了递归关系。 在上述标题和描述中提到的MS Server自关联表的级联删除,主要通过触发器来实现。触发器是一种特殊的存储过程,它会在特定的...

    SQL 级联删除与级联更新的方法

    本篇文章将详细讲解SQL中的级联删除(Cascade Delete)和级联更新(Cascade Update)。 **级联删除(Cascade Delete)** 级联删除是指在删除主表中的一条记录时,所有依赖于该记录的外键也将被自动删除。在创建表...

    cas.rar_MATLAB 级联失效_级联_级联失效 代码_级联失效代码_级联失效算法

    然而,压缩包内的"update.exe"可能是一个更新程序,用于更新或安装与级联失效模拟相关的软件组件。在使用这个程序之前,需要谨慎操作,确保它是来自可靠来源,以防止潜在的安全风险,如恶意软件或病毒。 在研究级联...

Global site tag (gtag.js) - Google Analytics