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

SQL Server未知嵌套JSON列的WHERE子句查询难题

未知结构嵌套JSON的SQL查询方案

核心问题原因

JSON_VALUE()必须指定明确的JSON路径才能取值,而你的JSON结构未知、层级不确定,所以直接写固定路径$.kref自然找不到结果。下面是几个可行的查询方案:


方案1:递归遍历所有键值对(推荐)

利用OPENJSON的递归特性,把整个JSON拆解为所有层级的键值对,再筛选目标条件,这是最可靠的方法。

单条件查询(找值为'12345'的记录)

SELECT *
FROM YourTable
WHERE EXISTS (
    SELECT 1
    -- 第一层解析
    FROM OPENJSON(YourTable.JSONUDFS)
    WITH (
        Value NVARCHAR(MAX) '$.Value' AS JSON,
        KeyName NVARCHAR(100) '$.Key'
    ) AS j1
    -- 递归处理所有嵌套层级
    CROSS APPLY (
        SELECT [Key], Value FROM OPENJSON(j1.Value)
        UNION ALL
        SELECT j2.[Key], j2.Value
        FROM OPENJSON(j1.Value)
        CROSS APPLY OPENJSON(Value) j2
    ) AS j2
    -- 匹配目标值,如需指定键名则加 j2.[Key] = 'kref'
    WHERE j2.Value = '12345'
)

多条件AND查询(同时满足kref='12345'和status='active')

SELECT *
FROM YourTable
-- 第一个条件:存在kref=12345
WHERE EXISTS (
    SELECT 1
    FROM OPENJSON(YourTable.JSONUDFS)
    WITH (
        Value NVARCHAR(MAX) '$.Value' AS JSON,
        KeyName NVARCHAR(100) '$.Key'
    ) AS j1
    CROSS APPLY (
        SELECT [Key], Value FROM OPENJSON(j1.Value)
        UNION ALL
        SELECT j2.[Key], j2.Value
        FROM OPENJSON(j1.Value)
        CROSS APPLY OPENJSON(Value) j2
    ) AS j2
    WHERE j2.[Key] = 'kref' AND j2.Value = '12345'
)
-- 第二个条件:存在status=active
AND EXISTS (
    SELECT 1
    FROM OPENJSON(YourTable.JSONUDFS)
    WITH (
        Value NVARCHAR(MAX) '$.Value' AS JSON,
        KeyName NVARCHAR(100) '$.Key'
    ) AS j1
    CROSS APPLY (
        SELECT [Key], Value FROM OPENJSON(j1.Value)
        UNION ALL
        SELECT j2.[Key], j2.Value
        FROM OPENJSON(j1.Value)
        CROSS APPLY OPENJSON(Value) j2
    ) AS j2
    WHERE j2.[Key] = 'status' AND j2.Value = 'active'
)

多条件OR查询(满足kref='12345'或status='active')

把两个条件放在同一个EXISTS的WHERE子句里用OR连接即可:

SELECT *
FROM YourTable
WHERE EXISTS (
    SELECT 1
    FROM OPENJSON(YourTable.JSONUDFS)
    WITH (
        Value NVARCHAR(MAX) '$.Value' AS JSON,
        KeyName NVARCHAR(100) '$.Key'
    ) AS j1
    CROSS APPLY (
        SELECT [Key], Value FROM OPENJSON(j1.Value)
        UNION ALL
        SELECT j2.[Key], j2.Value
        FROM OPENJSON(j1.Value)
        CROSS APPLY OPENJSON(Value) j2
    ) AS j2
    WHERE (j2.[Key] = 'kref' AND j2.Value = '12345')
       OR (j2.[Key] = 'status' AND j2.Value = 'active')
)

方案2:字符串模糊匹配(临时排查用)

如果JSON结构不复杂,且目标值不会和其他键名/值混淆,可以直接用字符串匹配,缺点是容易误判:

-- 找包含值12345的记录
SELECT *
FROM YourTable
WHERE JSONUDFS LIKE '%12345%'

-- 更精准:找包含"kref":"12345"的键值对
SELECT *
FROM YourTable
WHERE JSONUDFS LIKE '"kref":%12345%'

方案3:自定义递归函数(小数据集用)

创建一个标量函数递归遍历所有层级的键值对,返回拼接后的字符串,再基于这个函数查询:

CREATE FUNCTION dbo.GetAllJsonKeyValuePairs(@json NVARCHAR(MAX))
RETURNS NVARCHAR(MAX)
AS
BEGIN
    DECLARE @result NVARCHAR(MAX) = ''
    DECLARE @key NVARCHAR(100), @value NVARCHAR(MAX), @isJson BIT

    DECLARE jsonCursor CURSOR FOR
    SELECT [Key], Value, ISJSON(Value) AS IsJson
    FROM OPENJSON(@json)

    OPEN jsonCursor
    FETCH NEXT FROM jsonCursor INTO @key, @value, @isJson

    WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @result += @key + ':' + @value + ';'
        -- 如果当前值是JSON,递归处理
        IF @isJson = 1
        BEGIN
            SET @result += dbo.GetAllJsonKeyValuePairs(@value)
        END
        FETCH NEXT FROM jsonCursor INTO @key, @value, @isJson
    END

    CLOSE jsonCursor
    DEALLOCATE jsonCursor

    RETURN @result
END
GO

-- 使用函数查询包含kref:12345的记录
SELECT *
FROM YourTable
WHERE dbo.GetAllJsonKeyValuePairs(JSONUDFS) LIKE '%kref:12345%'

注意:标量函数在大数据量下性能较差,仅适合小数据集使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 11:33:13