You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

在SQL Server中对比两个表的行值,判断是否存在差异

在SQL Server中对比两个表的行数据差异

嘿,针对你要对比Product1和Product2_Transform两个表任意行任意字段差异的需求,我给你整理了几种实用的SQL Server解决方案:

方法1:使用FULL OUTER JOIN找出所有差异行(含仅单表存在的行)

这种方法会帮你覆盖三种差异场景:

  • 两个表都存在但字段值有差异的行
  • 仅在Product1存在的行
  • 仅在Product2_Transform存在的行
SELECT
    ISNULL(p1.Product_id, p2.Product_id) AS Product_id,
    ISNULL(p1.Product_rev, p2.Product_rev) AS Product_rev,
    -- 标记差异类型
    CASE 
        WHEN p1.Product_id IS NULL THEN '仅存在于Product2_Transform'
        WHEN p2.Product_id IS NULL THEN '仅存在于Product1'
        ELSE '字段值存在差异'
    END AS Difference_Type,
    -- 逐个字段对比,显示具体差异值
    CASE WHEN ISNULL(p1.Product_Name, '') <> ISNULL(p2.Product_Name, '') 
         THEN CONCAT('Product1: ', p1.Product_Name, ' | Product2: ', p2.Product_Name) 
         ELSE NULL END AS Product_Name_Diff,
    CASE WHEN ISNULL(p1.Product_description, '') <> ISNULL(p2.Product_description, '') 
         THEN CONCAT('Product1: ', p1.Product_description, ' | Product2: ', p2.Product_description) 
         ELSE NULL END AS Product_description_Diff,
    CASE WHEN ISNULL(p1.Product_owner, '') <> ISNULL(p2.Product_owner, '') 
         THEN CONCAT('Product1: ', p1.Product_owner, ' | Product2: ', p2.Product_owner) 
         ELSE NULL END AS Product_owner_Diff,
    -- Product2_Transform无这两个字段,对比时用空字符串占位
    CASE WHEN ISNULL(p1.Product_Group, '') <> '' 
         THEN CONCAT('Product1: ', p1.Product_Group, ' | Product2: 无此字段') 
         ELSE NULL END AS Product_Group_Diff,
    CASE WHEN ISNULL(p1.Product_TYPE, '') <> '' 
         THEN CONCAT('Product1: ', p1.Product_TYPE, ' | Product2: 无此字段') 
         ELSE NULL END AS Product_TYPE_Diff
FROM
    Product1 p1
FULL OUTER JOIN
    Product2_Transform p2 ON p1.Product_id = p2.Product_id AND p1.Product_rev = p2.Product_rev
WHERE
    -- 筛选所有存在差异的行
    p1.Product_id IS NULL 
    OR p2.Product_id IS NULL
    OR ISNULL(p1.Product_Name, '') <> ISNULL(p2.Product_Name, '')
    OR ISNULL(p1.Product_description, '') <> ISNULL(p2.Product_description, '')
    OR ISNULL(p1.Product_owner, '') <> ISNULL(p2.Product_owner, '')
    OR ISNULL(p1.Product_Group, '') <> ''
    OR ISNULL(p1.Product_TYPE, '') <> '';

关键说明:

  • ISNULL处理NULL值,避免NULL与非NULL的对比被忽略
  • 每个字段的CASE语句直接展示差异内容,方便快速定位问题
  • 针对Product2_Transform没有的字段,专门标注“无此字段”,避免混淆

方法2:用HASHBYTES快速判断整行差异

如果你只需要快速定位有差异的行,不需要具体哪个字段出问题,哈希值对比的效率更高:

SELECT
    ISNULL(p1.Product_id, p2.Product_id) AS Product_id,
    ISNULL(p1.Product_rev, p2.Product_rev) AS Product_rev,
    CASE 
        WHEN p1.Product_id IS NULL THEN '仅存在于Product2_Transform'
        WHEN p2.Product_id IS NULL THEN '仅存在于Product1'
        ELSE '字段值存在差异'
    END AS Difference_Type
FROM
    Product1 p1
FULL OUTER JOIN
    Product2_Transform p2 ON p1.Product_id = p2.Product_id AND p1.Product_rev = p2.Product_rev
WHERE
    HASHBYTES('SHA2_256', CONCAT(
        ISNULL(p1.Product_Name, ''), '|',
        ISNULL(p1.Product_description, ''), '|',
        ISNULL(p1.Product_owner, ''), '|',
        ISNULL(p1.Product_Group, ''), '|',
        ISNULL(p1.Product_TYPE, '')
    )) <> HASHBYTES('SHA2_256', CONCAT(
        ISNULL(p2.Product_Name, ''), '|',
        ISNULL(p2.Product_description, ''), '|',
        ISNULL(p2.Product_owner, ''), '|',
        '', '|', -- Product2_Transform无Product_Group,用空字符串占位
        ''       -- Product2_Transform无Product_TYPE,用空字符串占位
    ))
    OR p1.Product_id IS NULL
    OR p2.Product_id IS NULL;

关键说明:

  • 选择SHA2_256哈希算法,碰撞概率极低,比CHECKSUM更可靠
  • |作为字段分隔符,避免不同字段的内容拼接后产生歧义

方法3:仅对比两表共有的行

如果你只关心两个表都存在的记录(即Product_id和Product_rev完全匹配的行),可以用INNER JOIN缩小范围:

SELECT
    p1.Product_id,
    p1.Product_rev,
    CASE WHEN ISNULL(p1.Product_Name, '') <> ISNULL(p2.Product_Name, '') 
         THEN CONCAT('Product1: ', p1.Product_Name, ' | Product2: ', p2.Product_Name) 
         ELSE NULL END AS Product_Name_Diff,
    CASE WHEN ISNULL(p1.Product_description, '') <> ISNULL(p2.Product_description, '') 
         THEN CONCAT('Product1: ', p1.Product_description, ' | Product2: ', p2.Product_description) 
         ELSE NULL END AS Product_description_Diff,
    CASE WHEN ISNULL(p1.Product_owner, '') <> ISNULL(p2.Product_owner, '') 
         THEN CONCAT('Product1: ', p1.Product_owner, ' | Product2: ', p2.Product_owner) 
         ELSE NULL END AS Product_owner_Diff,
    CASE WHEN ISNULL(p1.Product_Group, '') <> '' 
         THEN CONCAT('Product1: ', p1.Product_Group, ' | Product2: 无此字段') 
         ELSE NULL END AS Product_Group_Diff,
    CASE WHEN ISNULL(p1.Product_TYPE, '') <> '' 
         THEN CONCAT('Product1: ', p1.Product_TYPE, ' | Product2: 无此字段') 
         ELSE NULL END AS Product_TYPE_Diff
FROM
    Product1 p1
INNER JOIN
    Product2_Transform p2 ON p1.Product_id = p2.Product_id AND p1.Product_rev = p2.Product_rev
WHERE
    ISNULL(p1.Product_Name, '') <> ISNULL(p2.Product_Name, '')
    OR ISNULL(p1.Product_description, '') <> ISNULL(p2.Product_description, '')
    OR ISNULL(p1.Product_owner, '') <> ISNULL(p2.Product_owner, '')
    OR ISNULL(p1.Product_Group, '') <> ''
    OR ISNULL(p1.Product_TYPE, '') <> '';

性能提示:

如果表数据量较大,记得给Product_idProduct_rev建立联合索引,能大幅提升JOIN操作的速度。

内容的提问来源于stack exchange,提问作者badri

火山引擎 最新活动