Sql 在Oracle中保持表同步

Sql 在Oracle中保持表同步,sql,oracle,synchronization,triggers,denormalization,Sql,Oracle,Synchronization,Triggers,Denormalization,我们将运行并行测试,以比较遗留系统和新版本。我们有一个Oracle数据库表A,用于存储遗留系统的数据,还有一个等效表B,用于存储新系统的数据,因此在测试期间,数据库是非规范化的。(同时,旧系统和表A是固定的-不允许更改) 我想做的是允许A上不频繁的DML操作传播到B,反之亦然。我从一对触发器开始这样做,但遇到了一个明显的问题,即当触发器运行时,表会发生变化,并引发异常 是否有处理此问题的标准方法?我读过关于是否使用dbms_调度程序的不同报告 谢谢 安迪 更新: 我最终回避了整个问题,并确保所有

我们将运行并行测试,以比较遗留系统和新版本。我们有一个Oracle数据库表A,用于存储遗留系统的数据,还有一个等效表B,用于存储新系统的数据,因此在测试期间,数据库是非规范化的。(同时,旧系统和表A是固定的-不允许更改)

我想做的是允许A上不频繁的DML操作传播到B,反之亦然。我从一对触发器开始这样做,但遇到了一个明显的问题,即当触发器运行时,表会发生变化,并引发异常

是否有处理此问题的标准方法?我读过关于是否使用dbms_调度程序的不同报告

谢谢

安迪

更新: 我最终回避了整个问题,并确保所有更新A的存储过程也更新B,反之亦然

我已将卡斯努伊的回答标记为已接受,因为如果将来面临同样的问题,我会遵循他的建议


我已经标记了JosephStyon的答案,因为我在表A和B上添加了两个insert/update语句级触发器,然后使用A或B作为主表执行他的合并过程,这取决于运行的触发器(尽管首先我检查了目标表是否会被合并更改,如果没有,则提前退出)

如果查询计划很重要,最好保留表的两个副本:
A_-underful
B_-underful
,并创建如下视图:

CREATE VIEW A
AS
SELECT  *
FROM    A_underlying

CREATE VIEW B
AS
SELECT  *
FROM    B_underlying
谓词将被推送到视图中,实际表和视图的查询计划将是相同的


中,您应该将数据放在两个基础表中,而不是两个视图上的
触发器中。

您真的是指DDL而不是DML吗

使用DML,您可以查看Oracles以保持表同步,也可以查看用于此目的的工具


对于DDL,我知道的唯一解决方案还是。

将以下三条语句放入存储过程中,然后根据需要将其作为计划作业运行:

--Assume that "A" is a master, and "B" needs to be synched

--If no match in "A", delete from "B"
DELETE FROM B
WHERE NOT EXISTS(
                SELECT *
                FROM A
                WHERE A.PRIMARY_KEY = B.PRIMARY_KEY
                );

--If there is a match, but they are different, then update "B"
update 
  (
  select
    a.field1 as new_value1
   ,b.field1 as old_value1
   ,a.field2 as new_value2
   ,b.field2 as old_value2
   ,....
   ,a.fieldN as new_valueN
   ,b.fieldN as old_valueN
  from
    a
   ,b
 where a.primary_key = b.primary_key
 )
set
  old_value1 = new_value1
 ,old_value2 = new_value2
 ,....
 ,old_valueN = new_valueN;


--if the record is new to "A", then insert it into "B"
INSERT INTO B
SELECT *
FROM A 
WHERE NOT EXISTS(
                SELECT *
                FROM B 
                WHERE B.PRIMARY_KEY = A.PRIMARY_KEY
                );

Oracle 10g及更高版本已将更改通知作为一个异步过程实施。它是自动的,并且该软件包包含在Oracle 10g及更高版本的服务器安装中


你可以查看一些信息。

这实际上是一个非常好的主意。不幸的是,遗留应用程序和数据库模式是固定的。我更新了问题以反映这一点。谢谢。对于外部世界,数据库模式将保持不变。您甚至可以在另一个模式中创建基础表。通过创建触发器,您对模式的更改不亚于通过在基础表上创建视图。true。更具体地说:我可以在不影响遗留系统的情况下添加触发器。如果我想在单个统一表AB上创建一个视图,我必须修改旧的应用程序以利用它上的视图。@Andy:您可以将旧表a重命名为一个_基础(甚至是备份_schema.a_基础),然后创建一个名称相同的视图a,该视图只从一个_基础中选择所有内容。你的旧版应用程序不会注意到任何东西。我明白你的意思-很好!不幸的是,我太胆小了,不能这么做-遗留系统的代码库太复杂了,它可能会直接插入表A。。。如果其他一切都失败了,我会沿着这条路走下去。谢谢:)嗨,约瑟夫。表之间没有主/从关系。对A的更改应该传播到B,反之亦然。我想我可以在代码中添加一个时间戳来实现这一点,因为更改是由用户发起的,并发性问题不太可能发生。谢谢。@Andy:如果您的遗留应用程序使用存储过程来更新表,那么看在上帝的份上,只需将您的逻辑放入这些过程中,因为这正是它应该做的。我的建议仅适用于开发较差的应用程序,这些应用程序发出DML语句(而不是调用过程)来更新数据。