`
jake0719
  • 浏览: 90354 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Oracle级联修改通用过程

阅读更多

转自http://blog.itpub.net/post/16888/118969

 

 

Oracle定义外健的时候可以定义级联删除,但是没有级联修改的语法。当然可以用触发器实现。这里有一个通用的级联修改的过程,代码本身并不复杂,而且说明非常详细(英文)。感谢原作者。

A Generic Cascade Update Procedure

by Michael R. Ault


Introduction 

Many times we have the situation where a master table may be updated and dependent tables are left without a link back to the master. In this situation a cascade update option would be a nice one to have. Unfortunately Oracle Corp. doesn't provide this capability in a native manner so a PL/SQL option must be developed. 

An example of a need for a cascade update would be in the situation where a dependent table could be dependent on one or more tables. For example, there may be two types of customer, one who has bought from us and we have marketing information for and another that is new to us, may buy from us, but may go with another vendor. If there are dependent tables (such as an interaction log that tracks phone calls to and from customers) it would be nice to be able to switch the dependencies from our new customer table to our established customer table. 

Enforcing a Cascade Update

What would be needed to enforce a cascade update? One method would be to utilize data dictionary tables and views to backtrack foreign key relations and then apply updates along this path. However, this may be a lengthy process and can be a performance problem. A simpler method would be to implement a table based cascade update. The table would contain the information a procedure would need to update all tables that are dependent upon a main or master table. Therefore, the table would have to contain the master table name, the dependent table(s) and in case we can't duplicate the exact column name across all of the dependent tables, the column to update. The table DDL script in figure 1 meets these requirements. If required, a fourth column indicating an update order could be added and the cursor in the UPDATE_TABLES procedure detailed later altered to do an ordered retrieve of the information.

CREATE TABLE update_tables
(
    main_table VARCHAR2(30) NOT NULL,
    table_name VARCHAR2(30) NOT NULL, 
    column_name VARCHAR2(30) NOT NULL,
    CONSTRAINT pk_update_tables 
    PRIMARY KEY (main_table,table_name,column_name)
    USING INDEX
    TABLESPACE tool_indexes)
    STORAGE (INITIAL 100K NEXT 100K PCTINCREASE 0)
    TABLESPACE tools
/
-- Column definitions are as follows:
--
-- main_table holds the name of the table that the update
-- cascades from.
--
-- table_name holds the name(s) of the tables to cascade the update
-- into.
--
-- column_name is the name of the column in the target table(s) to
-- update


Figure 1: Example DDL to create a cascade update source table.

The table by itself would be of little use. Since the data in the table is dynamic (i.e. multiple tables and columns that will need to be addressed) we must enable our trigger to be able to dynamically re-assign these values. The easiest way to do this is to create a set of procedures that utilizes the DBMS_SQL Oracle provided package to dynamically re-assign our update variables. Figure 2 shows the commented code for just such a procedure set. The set consists of two procedures, UPDATE_TABLES and UPDATE_COLUMN. 

The Cascade Update Procedures

Use of the DBMS_SQL package to dynamically build the table update command on the fly allows the same set of procedures to be used for any set of master-dependent tables that have entries in the source table. 

The UPDATE_TABLES procedure accepts the master table name, the old value for the column to be updated and the new value for the column. The procedure uses a standard cursor fetch to retrieve the dependent table names and dependent table column names from the source table shown in figure 1. If desired, the table from figure 1 could be altered to accept an ordering value for each master-dependent set to allow the cascade update to be done in a specific order if required. Using this information and the new and old values for the column from the trigger call, the UPDATE_COLUMN procedure dynamically rebuilds the table update command to update the appropriate tables.

-- First create package body
-- Decided to use package so that all procedures will
-- be in one place and very controllable
-- M. Ault 1/14/97 Rev 1.0
--
CREATE OR REPLACE PACKAGE cascade_update AS
-- 
-- First package is update_column
-- This package actually does the work
-- using DBMS_SQL to dynamically rebuild the 
-- UPDATEs at run time for each table.
--
PROCEDURE update_column(
    old_value IN VARCHAR2, 
    new_value IN VARCHAR2,
    table_name IN VARCHAR2,
    update_column IN VARCHAR2
);
--
-- Next procedure is update_tables
-- It is the loop control procedure for
-- the trigger and calls update_column
--
PROCEDURE update_tables(
    source_table IN VARCHAR2,
    old_value IN VARCHAR2, 
    new_value IN VARCHAR2
);
--
-- End of PACKAGE HEADER
--
END cascade_update;
/
--
-- Now build package body
-- That actually holds the 
-- procedures and code
--
CREATE OR REPLACE PACKAGE BODY cascade_update AS

PROCEDURE update_column(
    old_value IN VARCHAR2, 
    new_value IN VARCHAR2,
    table_name IN VARCHAR2,
    update_column IN VARCHAR2)
AS
--
-- define state variables for dbms_sql procedures
--
cur INTEGER;
rows_processed INTEGER;
--
-- start processing
-- (dbms_output calls are for debugging
-- commented out during normal runtime)
--
BEGIN
-- DBMS_OUTPUT.PUT_LINE('Table name: '||table_name||' Column: '||update_column);
-- 
-- initialize the dynamic cursor location for 
-- the dbms_sql process
--
    cur:=DBMS_SQL.OPEN_CURSOR;
--
-- populate the initialized location with the statement to be
-- processed
--
-- DBMS_OUTPUT.PUT_LINE(
-- 'UPDATE '||table_name||' set '||update_column||'='||chr(39)||new_value||chr(39)||chr(10)||
-- ' WHERE '||update_column||'='||chr(39)||old_value||chr(39)||' AND 1=1');
--
    dbms_sql.parse(cur,'UPDATE '||table_name||' set '||update_column||'='||chr(39)||new_value||chr(39)||chr(10)||' WHERE '||update_column||'='||chr(39)||old_value||chr(39)||' AND 1=1',dbms_sql.v7);
-- 
-- execute the dynamically parsed statement
--
rows_processed:=DBMS_SQL.EXECUTE(cur);
--
-- close dynamic cursor to prepare for next table
--
    DBMS_SQL.CLOSE_CURSOR(cur);
-- 
-- END PROCEDURE
--
END update_column;

PROCEDURE update_tables(
    source_table IN VARCHAR2,
    old_value IN VARCHAR2, 
    new_value IN VARCHAR2) as
--
-- Create the cursor to read records
-- from bbs_siteid_tables
-- Use * to prohibit missing a column
--
CURSOR get_table_name IS
    SELECT * FROM bbs_update_tables WHERE main_table=source_table;
--
-- Define rowtype variable to hold record from 
-- bbs_siteid_tables. Use rowtype to allow for
-- future changes.
--
    update_rec update_tables%ROWTYPE;
--
-- start processing
--
BEGIN
--
-- open and fetch values with cursor
--
    OPEN get_table_name;
    FETCH get_table_name INTO update_rec;
-- 
-- now that cursor status is open and values in 
-- variables can begin loop
--
    LOOP
--
-- using the notfound status we had to pre-populate
-- record
--
        EXIT WHEN get_table_name%NOTFOUND;
--
-- Initiate call to the update_column procedure
--
        update_column(old_value, new_value, update_rec.table_name, update_rec.column_name);
-- 
-- Now get next record from table
--
        FETCH get_table_name INTO update_rec;
--
-- processing returns to loop statement
--
    END LOOP;
--
-- close cursor and exit
--
    CLOSE get_table_name;
--
-- end of procedure
--
END update_tables;
--
-- end of package body
--
END cascade_update;
/

Figure 2: The package containing the procedures for cascade update

The Final Piece, the Trigger

Once the source table and procedures are built, we need to design a trigger to implement against our master tables that automatically fires on update to the target master column. Figure 3 shows an example of this trigger. One thing to notice about the trigger is that it passes the master table name to the UPDATE_TABLES procedure as well as the old and new values for the column being updated. This allows the UPDATE_TABLES procedure to select only the names and columns for the tables which are dependent upon the master table for which the trigger is implemented. This allows multiple master tables to utilize a single source table.

-- The calling trigger has to be of the form:

CREATE OR REPLACE TRIGGER cascade_update_<tabname>
    AFTER UPDATE OF <column> ON <tabname> 
    REFERENCING NEW AS upd OLD AS prev
    FOR EACH ROW
BEGIN
    cascade_update.update_tables('<tabname>',:prev.<column>,:upd.<column>);
END;
--
-- Note how the table name is passed to the procedure, this must be done.

Figure 3: Example trigger utilizing the cascade update procedures.

Summary

Utilizing the procedures and trigger described in this article a DBA can enforce a cascade update against any set of master-dependent tables without the performance hit of searching the data dictionary for the relationship definitions.

分享到:
评论

相关推荐

    ajax+jQuery+ssh+oracle级联实例

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

    js城市级联菜单通用

    js城市级联菜单通用,很好理解!非常好用

    Oracle Adf级联菜单过滤

    这个过程涉及到Oracle ADF的核心概念,如View Object、View Criteria、List of Values和UI Hints,这些都是构建高效、动态的Oracle ADF应用的关键组件。理解并熟练掌握这些技术,对于开发复杂的业务应用至关重要。

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

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

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

    如果在创建表时未设置级联删除,可以后续通过修改表结构来添加。这涉及删除原有的外键约束,然后重新创建带`ON DELETE CASCADE`的约束,例如: ```sql ALTER TABLE "U_WEN_BOOK"."GCHILTAB1" DROP CONSTRAINT "FK_...

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

    "级联失效算法"则是指用于预测和控制级联失效的特定方法,这些算法通常基于数学模型,例如图论、随机过程或动力系统理论。 然而,压缩包内的"update.exe"可能是一个更新程序,用于更新或安装与级联失效模拟相关的...

    级联菜单 级联菜单级联菜单级联菜单

    级联菜单级联菜单级联菜单级联菜单级联菜单级联菜单级联菜单级联菜单级联菜单级联菜单级联菜单级联菜单级联菜单级联菜单级联菜单级联菜单级联菜单级联菜单级联菜单级联菜单级联菜单级联菜单级联菜单级联菜单级联菜单...

    ORACLE 物理备库的配置

    操作系统 centos 4 oracle版本 10.2.0.1.0

    级联字典的构造

    2. **级联过程**:在构建级联字典时,首先,每个单独的过完备字典都会对输入数据进行编码,生成对应的系数向量。然后,这些系数向量会被传递到下一个字典,作为其新的输入。这个过程逐个字典进行,直到所有字典都...

    级联菜单 动态级联菜单

    级联菜单 动态级联菜单 级联菜单是一种常见的Web应用程序用户界面元素,它允许用户从多个选项中选择一个或多个项目。动态级联菜单是指可以根据实际情况动态生成选项的级联菜单。下面将对该技术进行详细的解释。 ...

    STM32 定时器级联

    STM32提供了多种类型的定时器,如基本定时器(TIM1-TIM5)、通用定时器(TIM6/TIM7)和高级定时器(TIM8-TIM17)。其中,基本定时器和高级定时器支持定时器级联功能。 定时器级联的核心是通过连接两个或更多定时器...

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

    在大型数据库系统中,这种功能通常通过外键约束来实现,但在某些情况下,如需要自定义删除逻辑或处理复杂的数据依赖,可能需要编写存储过程来执行级联删除。下面我们将深入探讨如何使用存储过程和游标来实现这一目标...

    Web树形级联菜单,连接oracle,嵌套ajax

    综上所述,"Web树形级联菜单,连接Oracle,嵌套Ajax"的项目涵盖了Web开发中的多个重要技术,包括前后端交互、数据库操作和用户体验优化。通过深入理解并熟练掌握这些技术,可以构建高效、用户友好的Web应用。

    级联菜单修改 js css

    在提供的文件名中,"原始效果.JPG" 和 "改后效果.JPG" 应该是展示级联菜单在修改前后的视觉差异。"menu" 文件可能是CSS样式表或JavaScript脚本,其中包含了实现级联菜单的具体代码。 综上所述,级联菜单的实现涉及...

    JSP、Ajax、Oracle存储过程实现三级动态级联.pdf

    JSP、Ajax、Oracle存储过程实现三级动态级联.pdf

    虚级联和连续级联的中文资料

    虚级联和连续级联是SDH(同步数字体系)网络中用于传输和复用数据的重要技术,这两种方法主要用于在SDH系统中有效地利用传输资源,实现带宽的灵活管理和扩展。在这里,我们将深入探讨这两种级联方式以及它们在SDH...

    SDH相邻级联与虚级联技术

    VC-4 相邻级联和虚级联的实现是基于新版 ITU G.707 协议,图 1 中的 VC-4-4c、VC-4-16c 就是新增的级联业务,下面将详细描述新版 G.707 协议关于级联业务的映射过程。图 2 为 C-4-Xc 的结构图。位于 AU-4 指针内的...

    casForest-master_级联森林_

    在训练过程中,级联森林首先通过一个简单的模型快速筛选掉大部分无用样本,然后在后续阶段使用更复杂的模型处理剩余的有信息量的样本。这种设计有助于减少计算成本,同时保持模型的预测能力。 决策树基础: 决策树...

Global site tag (gtag.js) - Google Analytics