有没有办法参数化openjson的第二个参数

Is there a way to parameterize the second argument of openjson

我的 json 数据如下:

SET @json='{
    "_id": "4erutit8979044kd5",
    "ADDRESSES": {
        "1": {
            "VALIDATED": "",
            "TYPE": "billing",
            "RESIDENTIAL": "",
            "REGION": "ON",
            "POSTAL": "L6789W",
            "PO": 0,
            "PHONE": "222222",
            "NAME_2": "Kapil",
            "NAME_1": "Kaushal",
            "LINE_2": "",
            "LINE_1": "215 Wards Ct.",
            "EMAIL": "kapilk@gmail.com",
            "COUNTRY": "IN",
            "CITY": "Jodhpur",
            "LAST_USED": 1435590000.0
        },
        "2": {
            "TYPE": "billing",
            "RESIDENTIAL": "",
            "REGION": "JD",
            "POSTAL": "2222",
            "PO": 0,
            "PHONE": "",
            "NAME_2": "Salman",
            "NAME_1": "Kursheed",
            "LINE_2": "",
            "LINE_1": "1459 Thomas Street",
            "EMAIL": "salmank@gmail.com",
            "COUNTRY": "IN",
            "CITY": "Jodhpur",
            "LAST_USED": 1436460000.0,
            "VALIDATED": "dirty"
        },
        "3": {
            "VALIDATED": "clean",
            "TYPE": "shipping",
            "CITY": "Jaisalmer",
            "COUNTRY": "IN",
            "EMAIL": "rajk@gmail.com",
            "LINE_1": "1020 Carripa Enclave",
            "LINE_2": "",
            "NAME_1": "Raj",
            "NAME_2": "Kumar",
            "PO": 0,
            "POSTAL": "222234",
            "REGION": "JS",
            "LAST_VALIDATED": "2015-07-14T16:20:42.242Z",
            "LAST_USED": 1436460000.0
        }
    }, ...
and so on

我想实现这样的目标:

WHILE @cnt < 3
BEGIN
   --insert into dummy_table
   select *   
   from   openjson (@json,'$.ADDRESSES."@cnt"')
   SET @cnt = @cnt + 1;
END;

线路工作正常:

select *   from   openjson (@json,'$.ADDRESSES."1"')
select *   from   openjson (@json,'$.ADDRESSES."1"')

但不使用变量 @cnt,即使我将 @cnt 定义为 char = '1'

请帮我实现同样的目标。地址的数量可能不同,所以我想让它动态化。

试试这个:

DECLARE @json NVARCHAR(MAX);

SET @json='{
    "_id": "4erutit8979044kd5",
    "ADDRESSES": {
        "1": {
            "VALIDATED": "",
            "TYPE": "billing",
            "RESIDENTIAL": "",
            "REGION": "ON",
            "POSTAL": "L6789W",
            "PO": 0,
            "PHONE": "222222",
            "NAME_2": "Kapil",
            "NAME_1": "Kaushal",
            "LINE_2": "",
            "LINE_1": "215 Wards Ct.",
            "EMAIL": "kapilk@gmail.com",
            "COUNTRY": "IN",
            "CITY": "Jodhpur",
            "LAST_USED": 1435590000.0
        },
        "2": {
            "TYPE": "billing",
            "RESIDENTIAL": "",
            "REGION": "JD",
            "POSTAL": "2222",
            "PO": 0,
            "PHONE": "",
            "NAME_2": "Salman",
            "NAME_1": "Kursheed",
            "LINE_2": "",
            "LINE_1": "1459 Thomas Street",
            "EMAIL": "salmank@gmail.com",
            "COUNTRY": "IN",
            "CITY": "Jodhpur",
            "LAST_USED": 1436460000.0,
            "VALIDATED": "dirty"
        },
        "3": {
            "VALIDATED": "clean",
            "TYPE": "shipping",
            "CITY": "Jaisalmer",
            "COUNTRY": "IN",
            "EMAIL": "rajk@gmail.com",
            "LINE_1": "1020 Carripa Enclave",
            "LINE_2": "",
            "NAME_1": "Raj",
            "NAME_2": "Kumar",
            "PO": 0,
            "POSTAL": "222234",
            "REGION": "JS",
            "LAST_VALIDATED": "2015-07-14T16:20:42.242Z",
            "LAST_USED": 1436460000.0
        }
    }'


DECLARE @cnt INT = 1;
DECLARE @query NVARCHAR(128);

WHILE @cnt <= 3
BEGIN
--insert into dummy_table

SET @query = '$.ADDRESSES."' + CAST(@cnt AS VARCHAR(4)) + '"'

select *   
from   openjson (@json,@query)
SET @cnt = @cnt + 1;
END;

只需将第二个参数构建为字符串并传递即可。

确切答案是是的,但这取决于SQL服务器版本。您有以下选项:

对于SQL Server 2017+,您可以提供一个变量作为path的值。注意,当键名以美元符号开头或包含空格、数字等特殊字符时,需要用引号括起来。

DECLARE @cnt int
SET @cnt = 1

--INSERT INTO dummy_table
SELECT *
FROM OPENJSON(@json, CONCAT('$.ADDRESSES."', @cnt, '"'))

对于 SQL Server 2016+,您需要使用 OPENJSON() 和默认模式解析输入 JSON。结果是包含 keyvaluetype.

列的 table
DECLARE @cnt int
SET @cnt = 1

--INSERT INTO dummy_table
SELECT j2.*
FROM OPENJSON(@json, '$.ADDRESSES') j1
CROSS APPLY OPENJSON(j1.[value]) j2
WHERE j1.[key] = @cnt

结果:

key        value         type
VALIDATED                   1
TYPE       billing          1
RESIDENTIAL                 1
REGION     ON               1
POSTAL     L6789W           1
PO         0                2
PHONE      222222           1
NAME_2     Kapil            1
NAME_1     Kaushal          1
LINE_2                      1
LINE_1     215 Wards Ct.    1
EMAIL      kapilk@gmail.com 1
COUNTRY    IN               1
CITY       Jodhpur          1
LAST_USED  1435590000.0     2

作为附加选项,您不需要 WHILE 循环来从输入 JSON 中获取特定值。以下语句解析 $.ADDRESSES.1$.ADDRESSES.2$.ADDRESSES.3 键的值。

--INSERT INTO dummy_table
SELECT j2.*
FROM (VALUES (1), (2), (3)) v(cnt)
JOIN OPENJSON(@json, '$.ADDRESSES') j1 ON CONVERT(int, j1.[key]) = v.cnt
CROSS APPLY OPENJSON(j1.[value]) j2