[英]Find out which Record and Column was Updated Between Two Tables
我有两个相似的表(Table_A和Table_B),它们共享相同的唯一标识符(Employee_Number列)。 他们也有类似的数据。
Create table Table_A
(
Employee_Number varchar2(100),
name varchar2(100),
address varchar2(100),
tel_no varchar2(100),
social_sec_no varchar2(100)
);
INSERT INTO Table_A (Employee_Number, name, address, tel_no, social_sec_no) values ('1', 'emp 1', 'home1', '1111', '11111');
INSERT INTO Table_A (Employee_Number, name, address, tel_no, social_sec_no) values ('2', 'emp 2', 'home2', '2222', '22222');
INSERT INTO Table_A (Employee_Number, name, address, tel_no, social_sec_no) values ('3', 'emp 3', 'home3', '3333', '33333');
INSERT INTO Table_A (Employee_Number, name, address, tel_no, social_sec_no) values ('4', 'emp 4', 'home4', '4444', '44444');
INSERT INTO Table_A (Employee_Number, name, address, tel_no, social_sec_no) values ('5', 'emp 5', 'home5', '5555', '55555');
commit;
create table Table_b
as
select *
from Table_A;
但是,表B的记录之一已更改:
update Table_b
set social_sec_no = '99999'
where Employee_Number = '1';
update Table_b
set social_sec_no = 'xxxx'
where Employee_Number = '3';
update Table_b
set address = 'office'
where Employee_Number = '1';
commit;
这是我发现哪些列已更改的操作:
SELECT *
FROM (select AX.Employee_Number
, CASE WHEN AX.name <> bx.NAME THEN 'CHANGED' else 'NO_CHANGE' END name
, CASE WHEN AX.address <> bx.address THEN 'CHANGED' else 'NO_CHANGE' END address
, CASE WHEN AX.tel_no <> bx.tel_no THEN 'CHANGED' else 'NO_CHANGE' END tel_no
, CASE WHEN AX.social_sec_no <> bx.social_sec_no THEN 'CHANGED' else 'NO_CHANGE' END social_sec_no
from Table_A ax
, Table_B bx
where ax.Employee_Number = bx.Employee_Number
and (ax.name <> bx.name
or ax.address <> bx.address
or ax.tel_no <> bx.tel_no
or ax.social_sec_no <> bx.social_sec_no))
WHERE 1=1
AND (name = 'CHANGED'
OR address = 'CHANGED'
OR tel_no = 'CHANGED'
OR social_sec_no = 'CHANGED');
查询结果
Employee_Number NAME ADDRESS TEL_NO SOCIAL_SEC_NO
--------------- --------- --------- --------- --------------
1 NO_CHANGE CHANGED NO_CHANGE CHANGED
3 NO_CHANGE NO_CHANGE NO_CHANGE CHANGED
我想知道是否有更好,更有效的方法来找出在不使用触发器或任何其他DDL和DML的情况下更改了哪个记录和列?
数据库详细信息:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
谢谢!
一个主题的变体...问题在多年前就通过AskTom解决了,这归功于提出了核心思想的Marco Stefanelli。
select *
from (
select source, employee_number, name, address, tel_no, social_sec_no,
count(*) over ( partition by employee_number,
name, address, tel_no, social_sec_no) as cnt
from (
select 'table_a' as source,
employee_number, name, address, tel_no, social_sec_no
from table_a
union all
select 'table_b' as source,
employee_number, name, address, tel_no, social_sec_no
from table_b
)
)
where cnt = 1
order by employee_number, source
;
SOURCE EMPLOYEE_NUMBER NAME ADDRESS TEL_NO SOCIAL_SEC_NO CNT
------- --------------- ---------- ------------ ---------- ------------- ------
table_a 1 emp 1 home1 1111 11111 1
table_b 1 emp 1 office 1111 99999 1
table_a 3 emp 3 home3 3333 33333 1
table_b 3 emp 3 home3 3333 xxxx 1
4 rows selected.
此查询还将识别一个表中在另一表中没有对应项的行(行具有相同的employee_number
)。 它的工作方式是,如果两个表中都存在完全相同的行,则count(*)
为2。
如果要排除一个表中的行而不是另一个表中的行(完全是-表示没有匹配的employee_number
),请在中间select
添加另一个“列”,以使count(*) over (partition by employee_number)
如果一个employee_number
出现在一个表中而不出现在另一个表中,则将为1,因此在外部查询的where
子句中,请将该数字设为= 2
。
一个简单的版本(虽然很难“破解”以排除其他表中没有匹配的employee_number
的行):
select max(source) as source,
employee_number, name, address, tel_no, social_sec_no
from (
select 'table_a' as source,
employee_number, name, address, tel_no, social_sec_no
from table_a
union all
select 'table_b' as source,
employee_number, name, address, tel_no, social_sec_no
from table_b
)
group by employee_number, name, address, tel_no, social_sec_no
having count(*) = 1
order by employee_number, source
;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.