Sql server 比较两个具有相同架构的表的数据差异
我正在处理一个典型的问题,需要比较两个模式完全相同的表的数据差异。 假设数据库为MS SQL或ORACLE 更确切地说,这是我试图实现的目标:Sql server 比较两个具有相同架构的表的数据差异,sql-server,oracle,compare,schema,Sql Server,Oracle,Compare,Schema,我正在处理一个典型的问题,需要比较两个模式完全相同的表的数据差异。 假设数据库为MS SQL或ORACLE 更确切地说,这是我试图实现的目标: 我有一个带有一些数据的表格 我正在创建表ORG的副本作为备份 现在我想更新ORG表中某些特定行中的某些特定列 找出备份表和组织表之间区别的最简单、最有效的方法是什么 我看不到像使用联合、枢轴、取消PIVOT等这样的选项。。但我感到困惑,需要一些关于最佳方式的指导 谢谢,试试这个 -- compare tables data and data2 with
-- compare tables data and data2
with data as
(select 1 as id, 'A' as val
from dual
union
select 2, 'B' from dual),
data2 as
(select 1 as id, 'A' as val
from dual
union
select 2, 'BC' from dual)
-- data not in data2 and data2 not in data:
(select *
from data2
minus
select * from data) union all
(select *
from data
minus
select * from data2);
您可以使用集合运算符
减号/相交
,具体取决于所需内容、两个表中行之间的差异或匹配
要获得差值,请使用减号:
SELECT <here_goes_your_column_list> FROM org
MINUS
SELECT <here_goes_your_column_list> FROM backup
SELECT <here_goes_your_column_list> FROM org
INTERSECT
SELECT <here_goes_your_column_list> FROM backup
从组织中选择
减
从备份中选择
要获得匹配,请使用相交:
SELECT <here_goes_your_column_list> FROM org
MINUS
SELECT <here_goes_your_column_list> FROM backup
SELECT <here_goes_your_column_list> FROM org
INTERSECT
SELECT <here_goes_your_column_list> FROM backup
从组织中选择
横断
从备份中选择
如果问题是检查两个表的标识,请参见。,即答案是
是
-表中包含
相同的数据或否-存在差异,存在另一种方法,在关系数据库中不太常见,
但最先进的文件
这与检查下载文件的“正确性”(即与原始文件的标识)的方法相同
使用哈希代码。如果您看到相同的哈希代码,答案是yes
您拥有正确的文件
如何将这种方法转换为关系数据库
Oracle提供了为字符串计算MD5
哈希代码的函数
select standard_hash('foo bar', 'MD5') hash_code from dual;
HASH_CODE
--------------------------------
327B6F07435811239BC47E1544353273
因此,您可以比较列值。
函数standard_hash
也与CLOB
s一起工作,因此(理论上)您可以连接
并计算整个表的哈希代码。但这不是正确的方法,记得吗
文件的哈希代码是通过组合行的哈希代码以增量方式计算的
下面演示如何使用Java类Java.security.MessageDigest
我使用的是Groovy脚本,不幸的是,这在PL/SQL中是不可能的
MessageDigest digest = MessageDigest.getInstance("MD5")
byte[] md5hash
groovyCon.eachRow ('select txt from MY_TABLE order by id')
{
digest.update(it.txt.getBytes(StandardCharsets.UTF_8))
}
md5hash = digest.digest();
println md5hash.encodeHex().toString()
脚本启动散列代码,然后遍历行并更新散列代码,最后
将其预设为字符串。这是处理文件时的典型方法,其中行的顺序很重要。在关系表中
订单未定义。您认为与(a,b,c)和(c,b,a)表相同。
请参阅如何使用XOR
将散列码以顺序无关的方式组合的讨论
下面是两个字符串的哈希代码组合的示例
select UTL_RAW.BIT_XOR(standard_hash('foo', 'MD5'), standard_hash('bar', 'MD5')) hash_code from dual;
HASH_CODE
--------------------------------
9B0805C206B7EBB8B6B9931D83E9F52A
这种方法有一个很大的优点,就是可以使用PL/SQL实现。看这里的例子
PL/SQL计算的一个实现,为整个表提供了一个MD5哈希代码
select MD5_XOR(txt) hash_code, count(*) cnt
from MY_TABLE;
HASH_CODE CNT
-------------------------------- -------
173F1F8F85F1A154044B7629A23E949C 102
当然,您可以连接参数来计算整个表的哈希代码
select MD5_XOR(to_char(id)||COL_TXT|| to_char(COL_DATE,'dd.mm.yyyy hh24:mi:ss')) md5 from MY_TABLE;
或者,您可以使用分组方式
查看表格的各个部分,看看哪些组相同,哪些不同
更好的是,如果这个聚合函数是由Oracle本机实现的,那么性能将会非常出色,而且会更好
使用基于集合的SQL比较操作(需要对表进行排序)。XOR
联合收割机不需要
排序和排序具有O(N)
复杂性,但用户实现受到上下文切换的影响
请参阅将其作为Oracle本机实现的想法 您是否正在尝试生成差异报告?或者从源表更新目标表?您实际使用的是这两个数据库中的哪一个?SQL可能会有所不同。
update
将完全不同。如果表具有主键或唯一键约束,则会有所帮助。您好,表没有任何主键。我尝试使用JOIN,它似乎涵盖了我感兴趣的大多数场景。。这就是我在p.city=q.cityi上从ORG x internal JOIN BACKUP q中选择count(*)时所做的。如果表没有任何主键,那么您也应该注意重复的行。使用internal JOIN
进行的选择仅按列city
进行比较。其他栏目的差异如何?如果更新了多个专栏,您将如何加入?谢谢。我试着加入,但似乎奏效了。我将探索您提供的选项,以备进一步完善。@Krishna没问题。如果答案有帮助,请将其标记为已回答,这也会帮助其他人!我在MSSQL上尝试过这个解决方案,得到Oracle上的负号与MSSQL上的负号相同。我需要具有不同数据的列,与上面提到的相同。这可以在MSSQL上实现吗?谢谢。我试着加入,但似乎奏效了。我将探讨您提供的选项,以备进一步改进。