Есть ли способ параметризации второго аргумента openjson? - PullRequest
1 голос
/ 21 апреля 2020

Мои 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'.

Пожалуйста, помогите мне добиться того же. Количество адресов может отличаться, поэтому я хочу, чтобы оно было динамическим c.

Ответы [ 2 ]

1 голос
/ 21 апреля 2020

Точный ответ: Да, но это зависит от 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+ необходимо выполнить синтаксический анализ вход JSON с OPENJSON() и схема по умолчанию. В результате получается таблица со столбцами key, value и type.

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 l oop для получения указанных c значений из входа 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
1 голос
/ 21 апреля 2020

Попробуйте:

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;

Просто создайте второй параметр как строку и передайте его.

...