想象一下,您有两个不同的表/查询,它们应该具有/返回相同的数据。你想验证这一点。什么是显示每个表中任何不匹配行的简单方法,就像下面的示例一样,比较每一列?假设表中有 30 列,其中许多列可以为 NULL。
当没有 PK 或每个 PK 可能有重复项时,仅加入 PK 列是不够的,并且必须使用 30 个正确处理 NULL 的连接条件以及令人讨厌的 WHERE 条件进行 FULL JOIN 将是一场灾难排除匹配的行。
通常,当我针对未清理或未完全理解的数据编写新查询时,问题最严重,并且 PK 在逻辑上可用的可能性极低。我设计了两种不同的方法来解决问题,然后比较它们的结果,这些差异突出了我不知道的数据中的特殊情况。
结果需要如下所示:
Which Col1 Col2 Col3 ... Col30
------ ------ ------ ------ ------
TableA Cat 27 86 -- mismatch
TableB Cat 27 105 -- mismatch
TableB Cat 27 87 -- mismatch 2
TableA Cat 128 92 -- no corresponding row
TableB Lizard 83 NULL -- no corresponding row
如果[Col1, Col2]
确实是一个复合键,并且我们在最终结果中按它们排序,那么我们可以很容易地看到 A 和 B 有一行不同但应该是相同的,并且每一行都有另一行不存在。
在上面的示例中,不希望看到第一行两次。
这是用于设置示例表和数据的 DDL 和 DML:
CREATE TABLE dbo.TableA (
Col1 varchar(10),
Col2 int,
Col3 int,
Col4 varchar(10),
Col5 varchar(10),
Col6 varchar(10),
Col7 varchar(10),
Col8 varchar(10),
Col9 varchar(10),
Col10 varchar(10),
Col11 varchar(10),
Col12 varchar(10),
Col13 varchar(10),
Col14 varchar(10),
Col15 varchar(10),
Col16 varchar(10),
Col17 varchar(10),
Col18 varchar(10),
Col19 varchar(10),
Col20 varchar(10),
Col21 varchar(10),
Col22 varchar(10),
Col23 varchar(10),
Col24 varchar(10),
Col25 varchar(10),
Col26 varchar(10),
Col27 varchar(10),
Col28 varchar(10),
Col29 varchar(10),
Col30 varchar(10)
);
CREATE TABLE dbo.TableB (
Col1 varchar(10),
Col2 int,
Col3 int,
Col4 varchar(10),
Col5 varchar(10),
Col6 varchar(10),
Col7 varchar(10),
Col8 varchar(10),
Col9 varchar(10),
Col10 varchar(10),
Col11 varchar(10),
Col12 varchar(10),
Col13 varchar(10),
Col14 varchar(10),
Col15 varchar(10),
Col16 varchar(10),
Col17 varchar(10),
Col18 varchar(10),
Col19 varchar(10),
Col20 varchar(10),
Col21 varchar(10),
Col22 varchar(10),
Col23 varchar(10),
Col24 varchar(10),
Col25 varchar(10),
Col26 varchar(10),
Col27 varchar(10),
Col28 varchar(10),
Col29 varchar(10),
Col30 varchar(10)
);
INSERT dbo.TableA (Col1, Col2, Col3, Col4, Col5, Col6, Col7, Col8, Col9, Col10, Col11, Col12, Col13, Col14, Col15, Col16, Col17, Col18, Col19, Col20, Col21, Col22, Col23, Col24, Col25, Col26, Col27, Col28, Col29, Col30)
VALUES
('Cat', 27, 86, 'a', 'b', 'c', 'd', 'e', 'f', 'g',' h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0'),
('Cat', 128, 92, 'a', 'b', 'c', 'd', 'e', 'f', 'g',' h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0'),
('Porcupine', NULL, 42, 'a', 'b', 'c', 'd', 'e', 'f', 'g',' h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0'),
('Tapir', NULL, NULL, 'a', 'b', 'c', 'd', 'e', 'f', 'g',' h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0')
;
INSERT dbo.TableB (Col1, Col2, Col3, Col4, Col5, Col6, Col7, Col8, Col9, Col10, Col11, Col12, Col13, Col14, Col15, Col16, Col17, Col18, Col19, Col20, Col21, Col22, Col23, Col24, Col25, Col26, Col27, Col28, Col29, Col30)
VALUES
('Cat', 27, 105, 'a', 'b', 'c', 'd', 'e', 'f', 'g',' h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0'),
('Cat', 27, 87, 'a', 'b', 'c', 'd', 'e', 'f', 'g',' h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0'),
('Lizard', 83, NULL, 'a', 'b', 'c', 'd', 'e', 'f', 'g',' h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0'),
('Porcupine', NULL, 42, 'a', 'b', 'c', 'd', 'e', 'f', 'g',' h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0'),
('Tapir', NULL, NULL, 'a', 'b', 'c', 'd', 'e', 'f', 'g',' h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0');
这可以使用 EXCEPT 和/或 INTERSECT 来处理。 http://msdn.microsoft.com/en-us/library/ms188055.aspx
首先查找表 1 中所有不在表 2 中的记录,然后查找表 2 中所有不在表 1 中的记录。
毫无疑问,有一种更有效的方法可以做到这一点,但这是我脑海中第一个“快速而肮脏”的解决方案。另外,我不建议使用 * 通配符,但为了简洁起见,它适合这里。
或者,您可以使用 INTERSECT 运算符并从中排除所有结果。
这里不需要 30 个加入条件
FULL OUTER JOIN
。您可以只在 PK 上进行完全外连接,保留至少有一个差异的行,
WHERE EXISTS (SELECT A.* EXCEPT SELECT B.*)
并用于CROSS APPLY (SELECT A.* UNION ALL SELECT B.*)
将 ed 行的两侧反旋转JOIN
成单独的行。给
或处理移动球门柱的版本。
对于具有许多列的表,仍然很难识别不同的特定列。为此,您可以使用以下内容。
(虽然只是在相对较小的表上,否则这种方法可能不会有足够的性能)
使用 Data Compare 之类的第三方工具很容易完成,或者只是在客户端上完成。在单元测试存储过程的上下文中,我们只是编写了一些 C# 代码。
这是我们正在使用的 C# 代码,引用自一篇旧文章:关闭那些漏洞 - 测试存储过程
这是一种显示所要求内容的方法: