【问题标题】:Query JSON for a given property without knowing the position of the property在不知道属性位置的情况下查询给定属性的 JSON
【发布时间】:2021-03-22 02:56:26
【问题描述】:

我的数据库中有不同的 JSON。

所有结构都不同。

例子:

{
"DefinitionKey": "DocumentRelease",
"variables": {
    "isError": false,
    "ProcessItem": {
        "NamedValues": {
            "{|CompanyNumber|}": "90077"
        },
        "Department": null,
        "Tester": null,
        "ResponsibleAgents": "netCo.Demo\\CGiesen"
    }
}

{
"DefinitionKey": "DocumentRelease",
"{|CompanyNumber|}": "90077",
"variables": {
    "isError": false,
    "ProcessItem": {
        "NamedValues": {},
        "Department": null,
        "Tester": null,
        "ResponsibleAgents": "netCo.Demo\\CGiesen"
    }
}

}

现在我想搜索 {|CompanyNumber|},例如,我想获取 CompanyNumber 可能为 90077 的所有行。

我知道使用Json_Value 进行查询,但在这里我必须知道我的 JSON 结构中的位置。

Newtonsoft.Json 给我这样的东西

processInstanceExtendedVariables.SelectToken($"$..{pattern}");

SQL Server 中有类似的东西吗?

【问题讨论】:

标签: json sql-server


【解决方案1】:

它们都是完全随机的 :( 通常我不知道在哪里可以找到令牌

灵活性的代价有时是地狱

【讨论】:

    【解决方案2】:

    您的 JSON 在这两个示例之间是一致的,还是它们都是完全随机的?

    如果您有两种不同的 JSON 结构,您可以在 WHERE 子句中使用 JSON_VALUEOR

    您可以在 SSMS 中运行以下示例:

    DECLARE @Data table ( id int, jsn nvarchar(MAX) );
    INSERT INTO @Data VALUES
        ( 1, '{"DefinitionKey": "DocumentRelease","variables": {"isError": false,"ProcessItem": {"NamedValues":{"{|CompanyNumber|}": "90077"},"Department": null,"Tester": null,"ResponsibleAgents": "netCo.Demo\\CGiesen"}}}' ),
        ( 2, '{"DefinitionKey": "DocumentRelease","{|CompanyNumber|}": "90077","variables":{"isError": false,"ProcessItem":{"NamedValues": {},"Department": null,"Tester": null,"ResponsibleAgents": "netCo.Demo\\CGiesen"}}}' );
    
    SELECT
        jsn
    FROM @Data
    WHERE
        JSON_VALUE ( jsn, '$."{|CompanyNumber|}"' ) = '90077'
        OR
        JSON_VALUE ( jsn, '$.variables.ProcessItem.NamedValues."{|CompanyNumber|}"' ) = '90077';
    

    返回

    +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    |                                                                                                       jsn                                                                                                       |
    +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | {"DefinitionKey": "DocumentRelease","variables": {"isError": false,"ProcessItem": {"NamedValues":{"{|CompanyNumber|}": "90077"},"Department": null,"Tester": null,"ResponsibleAgents": "netCo.Demo\\CGiesen"}}} |
    | {"DefinitionKey": "DocumentRelease","{|CompanyNumber|}": "90077","variables":{"isError": false,"ProcessItem":{"NamedValues": {},"Department": null,"Tester": null,"ResponsibleAgents": "netCo.Demo\\CGiesen"}}} |
    +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    

    更新:

    “它们都是完全随机的……”

    在这种情况下,我(个人)会使用内联表值函数进行字符串解析。

    这是我为内联 TVF 编写的代码:

    CREATE FUNCTION dbo.GetValue (  
        @json nvarchar(MAX),
        @key  nvarchar(255)
    )
    RETURNS TABLE 
    AS
    RETURN (
    
        SELECT
            REPLACE ( key_value, '"', '' ) AS key_value --strip double quotes.
        FROM (
    
            -- Get the initial part of @key's string
            SELECT SUBSTRING (
                @json,
                CHARINDEX ( @key, @json ) + LEN ( @key ),
                LEN ( @json )
            ) AS key_string
    
        ) AS x
        CROSS APPLY (
    
            -- Get @key's value from [key_string] (expects a quoted value)
            SELECT SUBSTRING (
                x.key_string,
                CHARINDEX ( '"', x.key_string),
                CHARINDEX ( '"', x.key_string, CHARINDEX ( '"', x.key_string ) + 1 ) - 1
            ) AS key_value
    
        ) AS n
    
    );
    

    您可以针对我的示例(更新)@Data 表调用此内联 TVF,如下所示:

    SELECT
        id, key_value
    FROM @Data
    OUTER APPLY dbo.GetValue( jsn, '"{|CompanyNumber|}":' ) AS x
    WHERE
        key_value = '90077';
    

    返回:

    +----+-----------+
    | id | key_value |
    +----+-----------+
    |  1 |     90077 |
    |  2 |     90077 |
    +----+-----------+
    

    (排除列jsn以节省空间)

    请注意,键名作为'"{|CompanyNumber|}":' 传递,这是完整键名,包括引号和冒号

    我提供的内联 TVF 期望返回值 @key 被引用。

    【讨论】:

      【解决方案3】:

      你把我带到了正确的道路上。这就是我现在的解决方案:

       CRAETE FUNCTION [dbo].[GetValue] (  
          @json nvarchar(MAX),
          @key  nvarchar(255)
      )
      RETURNS NVARCHAR(MAX) 
      AS
      -- Returns Value
      BEGIN
      RETURN 
      
      REPLACE(
      SUBSTRING (
                 @json,
                  CHARINDEX ( @key, @json ) + (LEN (@key ) + 3),
                 (CHARINDEX ( ',', @json  , CHARINDEX ( @key, @json ) + (LEN ( @key ) + 3 ))) - ( CHARINDEX ( @key, @json ) + (LEN ( @key ) + 3))
                 ),
                 '"','');
      END
      

      【讨论】:

        猜你喜欢
        • 2017-01-24
        • 1970-01-01
        • 2013-05-10
        • 2012-10-16
        • 1970-01-01
        • 1970-01-01
        • 2023-03-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多