我正在寻找一种方法来检测同一个表的两个版本之间的差异。 让我们说我在两个不同的日子创建了一个活动表的副本:
第1天:
CREATE TABLE table_1 AS SELECT * FROM table
第2天:
CREATE TABLE table_2 AS SELECT * FROM table
该方法应标识在第1天和第2天之间添加,删除或更新的所有行; 如果可能,该方法不应使用特定于RDBMS的功能;
注意:将表格的内容导出为文本文件并比较文本文件很好,但我想要一个特定于SQL的方法。
示例:
create table table_1
(
col1 integer,
col2 char(10)
);
create table table_2
(
col1 integer,
col2 char(10)
);
insert into table_1 values ( 1, 'One' );
insert into table_1 values ( 2, 'Two' );
insert into table_1 values ( 3, 'Three' );
insert into table_2 values ( 1, 'One' );
insert into table_2 values ( 2, 'TWO' );
insert into table_2 values ( 4, 'Four' );
table_1和table_2之间的差异:
答案 0 :(得分:0)
如果你想要两个方向的差异。我假设你有id
,因为你提到"更新"你需要一种方法来识别同一行。这是union all
方法:
select t.id,
(case when sum(case when which = 't2' then 1 else 0 end) = 0
then 'InTable1-only'
when sum(case when which = 't1' then 1 else 0 end) = 0
then 'InTable2-only'
when max(col1) <> min(col1) or max(col2) = min(col2) or . . .
then 'Different'
else 'Same'
end)
from ((select 'table1' as which, t1.*
from table_1 t1
) union all
(select 'table2', t2.*
from table_2 t2
)
) t;
这是标准的SQL。你可以过滤掉&#34;相同的&#34;记录,如果你想。
这假设所有列都具有非NULL值,并且具有给定id的行在每个表中最多出现一次。
答案 1 :(得分:0)
我想我找到了答案 - 可以使用此SQL语句来构建差异列表:
注意:“col1,col2”列表必须包含表格中的所有列
SELECT
MIN(table_name) as table_name, col1, col2
FROM
(
SELECT
'Table_1' as table_name, col1, col2
FROM Table_1 A
UNION ALL
SELECT
'Table_2' as table_name, col1, col2
FROM Table_2 B
)
tmp
GROUP BY col1, col2
HAVING COUNT(*) = 1
+------------+------+------------+
| table_name | col1 | col2 |
+------------+------+------------+
| Table_2 | 2 | TWO |
| Table_1 | 2 | Two |
| Table_1 | 3 | Three |
| Table_2 | 4 | Four |
+------------+------+------------+
在问题中引用的示例中,
答案 2 :(得分:0)
如果您可以认为该表具有唯一的主键,那么以下SQL语句最后会创建三个视图,其中包含已更改的ID,新ID和已删除的ID。
在以下&#34; tbl1 &#34;是旧版本&#34; tbl2 &#34;是新版本(相同的架构)。假设表格中的主键名为&#34; _id &#34;。 中间视图&#34; _NewChanged &#34;将在新版本的表格中包含新的和已更改的ID以及视图&#34; _RemovedChanged &#34;将包含新版本中已删除和已更改的ID。
生成增量SQL语句只需要以编程方式循环各个视图以创建增量集并执行删除,更新,插入将旧版本转换为新版本的状态。
解决方案有三点需要注意:
为了保持代码简洁,没有插入评论。
drop view if exists _NewChanged;
drop view if exists _RemovedChanged;
create view _NewChanged as
select * from tbl2
except
select * from tbl1;
create view _RemovedChanged as
select * from tbl1
except
select * from tbl2;
drop view if exists changed;
drop view if exists new;
drop view if exists deleted;
create view changed as
select _id from _NewChanged
intersect
select _id from _RemovedChanged;
create view new as
select _id from _NewChanged
except
select _id from _RemovedChanged;
create view deleted as
select _id from _RemovedChanged
except
select _id from _NewChanged;