You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过SQL存储过程对比同表中两个ID对应的行并返回JSON格式的差异列数据

解决方案:对比同表两行数据差异并返回指定JSON格式的存储过程

我来给你设计一个规范的存储过程实现方案,完全满足你对比同表两行数据差异、并返回指定JSON格式的需求。

核心思路

  • 先通过两个ID获取目标行的所有数据,避免重复查询
  • 动态读取表的列信息(不用硬编码列名,适配不同表结构)
  • 逐列对比两行的值,专门处理NULL值的特殊差异场景
  • 将差异列和对应值组装成你需要的JSON数组结构

完整存储过程代码

CREATE PROCEDURE CompareTwoRows
    @TableName NVARCHAR(128),
    @IdColumnName NVARCHAR(128),
    @IdValue1 NVARCHAR(128),
    @IdValue2 NVARCHAR(128)
AS
BEGIN
    SET NOCOUNT ON;

    -- 声明变量存储动态SQL和列对比片段
    DECLARE @Sql NVARCHAR(MAX);
    DECLARE @ColumnCompareFragments NVARCHAR(MAX);

    -- 生成每一列的对比逻辑,包含NULL值判断
    SELECT @ColumnCompareFragments = STRING_AGG(
        CONCAT(
            'CASE ',
            'WHEN ', QUOTENAME(c.COLUMN_NAME), ' <> t2.', QUOTENAME(c.COLUMN_NAME), 
            ' OR (', QUOTENAME(c.COLUMN_NAME), ' IS NULL AND t2.', QUOTENAME(c.COLUMN_NAME), ' IS NOT NULL)',
            ' OR (', QUOTENAME(c.COLUMN_NAME), ' IS NOT NULL AND t2.', QUOTENAME(c.COLUMN_NAME), ' IS NULL)',
            ' THEN JSON_OBJECT(''ColumnName'', ''', c.COLUMN_NAME, ''', ''Value1'', ', QUOTENAME(c.COLUMN_NAME), ', ''Value2'', t2.', QUOTENAME(c.COLUMN_NAME), ')',
            ' END'
        ), ','
    )
    FROM INFORMATION_SCHEMA.COLUMNS c
    WHERE c.TABLE_NAME = @TableName
      AND c.COLUMN_NAME <> @IdColumnName; -- 排除ID列本身

    -- 拼接完整的动态SQL语句
    SET @Sql = CONCAT(
        'SELECT JSON_QUERY(''['' + STRING_AGG(diff_item, '','') + '']'') AS DifferenceJson ',
        'FROM (',
        '    SELECT t1.*, t2.* ',
        '    FROM ', QUOTENAME(@TableName), ' t1 ',
        '    CROSS JOIN ', QUOTENAME(@TableName), ' t2 ',
        '    WHERE t1.', QUOTENAME(@IdColumnName), ' = ''', @IdValue1, ''' ',
        '      AND t2.', QUOTENAME(@IdColumnName), ' = ''', @IdValue2, '''',
        ') target_rows ',
        'CROSS APPLY (',
        '    SELECT ', @ColumnCompareFragments, ' AS diff_item ',
        ') diff_items ',
        'WHERE diff_item IS NOT NULL'
    );

    -- 执行动态SQL
    EXEC sp_executesql @Sql;
END

代码说明

参数解释

  • @TableName:需要对比数据的目标表名
  • @IdColumnName:表中作为唯一标识的ID列名称(比如你的示例里是Col1)
  • @IdValue1:第一个待对比的ID值(比如Id-1)
  • @IdValue2:第二个待对比的ID值(比如Id-2)

关键细节

  • NULL值处理:专门判断了"一方为NULL另一方不为NULL"的场景,避免遗漏这种常见的差异
  • 动态列适配:通过INFORMATION_SCHEMA.COLUMNS自动读取表的所有列,不用手动硬编码列名,适配任意表结构
  • JSON合法性:用JSON_OBJECT生成单个差异项的JSON,再用STRING_AGG拼接成数组,最后通过JSON_QUERY确保输出是标准合法的JSON格式

测试示例(匹配你的数据场景)

假设你的表结构和数据如下:

CREATE TABLE TestTable (
    Col1 NVARCHAR(50),
    Col2 NVARCHAR(50),
    Col3 INT,
    Col4 INT,
    Col5 INT
);

INSERT INTO TestTable VALUES
('Id-1', 'ABC', 123, 321, 111),
('Id-2', 'ABC', 333, 321, 123);

调用存储过程:

EXEC CompareTwoRows 'TestTable', 'Col1', 'Id-1', 'Id-2';

返回的JSON结果(和你预期的格式完全一致):

[
 { "ColumnName":"Col3", "Value1":"123", "Value2":"333" },
 { "ColumnName":"Col5", "Value1":"111", "Value2":"123" }
]

注意事项

  • 确保执行存储过程的账号拥有查询INFORMATION_SCHEMA系统视图的权限
  • 如果表中包含特殊数据类型(比如日期、二进制),可以根据需求在JSON_OBJECT中添加类型转换逻辑(比如CONVERT(NVARCHAR(50), 列名))
  • 该存储过程仅查询目标的两行数据,性能表现优秀,适合大表场景

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 06:52:43