首先,由于数据只是在两个不同的模式中,你确定你真的需要将它从一个复制到另一个吗?如果attendance_database.attendance_table 和payroll_database.payroll_attendance_table 应该具有相同的数据,那么删除一个并在payroll_database 中创建一个指向attendance_database 的同义词会更有意义。
grant select on attendance_database.attendance_table
to payroll_database;
create synonym payroll_database.payroll_attendance_table
for attendance_database.attendance_table;
如果它们不应该具有相同的数据(例如,payroll_database.payroll_attendance_table 表应该具有其他属性),您很可能希望将 payroll_database.payroll_attendance_table 设为子表。类似的东西
grant references on attendance_database.attendance_table
to payroll_database;
create table payroll_database.payroll_attendance_table (
attendance_id integer references attendance_database.attendance_table( attendance_id ),
<<additional attributes>>
);
如果您真的非常想拥有相同数据的两个单独副本并通过触发器来维护它们,您可以执行类似的操作
create or replace trigger trg_pointless_sync
before insert or update or delete on attendance_database.attendance_table
for each row
declare
begin
if inserting
then
insert into payroll_database.payroll_attendance_table( attendance_id,
col1,
col2,
...
colN )
values( :new.attendance_id,
:new.col1,
:new.col2,
...,
:new.colN );
elsif updating
then
update payroll_database.payroll_attendance_table
set col1 = :new.col1,
col2 = :new.col2,
...
colN = :new.colN
where attendance_id = :new.attendance_id;
else
delete from payroll_database.payroll_attendance_table
where attendance_id = :new.attendance_id;
end if;
end;
当然,基于触发器的解决方案通常有些问题。它们可以通过将源表上基于集合的良好、快速的操作转换为递归的逐行操作来施加相当大的性能损失。如果 DBA 想要快速将 attendance_table 恢复到以前的状态,他们可能会产生维护问题,因为有人弄错了一些数据并且没有意识到删除所有数据具有删除所有数据的副作用payroll_database 表。而且它们几乎总是会产生同步问题——例如,如果有人修改了payroll_database 中的某一行会发生什么?或者,如果有人更新了attendance_table 的 PK,我写的触发器不够聪明,无法正确处理(当然,你可以扩展它,但通常这类极端情况比你可能的要多代码),因此这两个表最终将不会完全同步。