IF EXISTS (проверьте, содержит ли объект json уникальный идентификатор), таблицу UPDATE, ELSE INSERT в таблицу - PullRequest
0 голосов
/ 31 октября 2018

Я хочу использовать IF EXISTS в своем запросе, чтобы проверить, содержит ли объект «seqId» или нет. Я пытаюсь обновить или вставить в таблицу из OPENJSON. Этот объект json @identObj имеет массив объектов, некоторые объекты могут иметь «seqId», а некоторые - нет. Те, которые имеют "seqId", должны обновиться в таблице "case_ident_to_inv", если "seqId" не существует, они должны вставить в эту таблицу таблицу "case_ident_to_inv". Результатом вставки в таблицу является уникальный seqId. Я пытался реализовать оператор IF EXISTS и думал, что синтаксис правильный, но я получаю эту ошибку:

Неверный синтаксис рядом с 'IF'.

DECLARE @identObj NVARCHAR(MAX) = N'[
  {  
    "investigators": [
         {"importId": 177, "userId": 120, "invTypeCd": "LI", "seqId": 50}, 
         {"importId": 177, "userId": 124, "invTypeCd": "SI", "seqId": 50}, 
         {"importId": 177, "userId": 120, "invTypeCd": "RV", "seqId": 50}, 
         {"importId": 177, "userId": 123, "invTypeCd": "SI"},
     ]
   }
]';

Данные для таблицы "case_ident_to_inv"

+------------+--------+-------------+---------------+-------+
|  importId  | userId |  invTypeCd  |  caseIdentId  | seqId |
+------------+--------+-------------+---------------+-------+
| 177        | 120    | LI          | 10200         | 50    | 
| 177        | 124    | SI          | 10200         | 51    | 
| 177        | 120    | RV          | 10200         | 52    |
| 177        | 123    | SI          | 10200         |       |<--- seqId OUTPUT AFTER INSERT
+------------+--------+-------------+---------------+-------+

caseIdentId и importId всегда будут одинаковыми, могут быть одинаковые userId и invTypeCd, seqId всегда уникален.

Хранимая процедура

select I.*
INTO #tmpInvs
FROM OPENJSON(@identObj)
WITH (
    invs NVARCHAR(MAX) AS JSON
) AS caseIdentInvs
CROSS APPLY OPENJSON (caseIdentInvs.invs)
WITH (
    userId INT,
    invTypeCd CHAR(5),
    importId INT,
    seqId INT
) I;

WITH cte AS
(
    SELECT i.*,ci.case_ident_id AS case_ident_id, ki.inv_type_name AS inv_type_name
    FROM #tmpInvs i
    INNER JOIN case_idents ci ON i.importId=ci.import_id
    INNER JOIN kdd_inv_type ki ON i.invTypeCd=ki.inv_type_cd
)

IF EXISTS (SELECT i.seqId FROM #tmpInvs i WHERE i.seqId != NULL)
UPDATE T
SET
    inv_id = ct.userId,
    inv_type_cd = ct.invTypeCd,
    inv_type_name = ct.inv_type_name
FROM case_ident_to_inv T
INNER JOIN cte AS ct ON ct.case_ident_id = T.case_ident_id

WHERE seq_id = ct.seqId

ELSE

INSERT INTO case_ident_to_inv(inv_id, case_ident_id, inv_type_cd, inv_type_name)
SELECT userId, case_ident_id, invTypeCd, inv_type_name
FROM cte

Ответы [ 2 ]

0 голосов
/ 31 октября 2018

A CTE необходимо SELECT, INSERT, UPDATE or DELETE. От Документы :

За CTE должен следовать один оператор SELECT, INSERT, UPDATE или DELETE, который ссылается на некоторые или все столбцы CTE. CTE также может быть указан в операторе CREATE VIEW как часть определяющего оператора SELECT представления.

Вы можете переместить IF EXISTS вверх как

   select I.*
    INTO #tmpInvs
    FROM OPENJSON(@identObj)
    WITH (
        invs NVARCHAR(MAX) AS JSON
    ) AS caseIdentInvs
    CROSS APPLY OPENJSON (caseIdentInvs.invs)
    WITH (
        userId INT,
        invTypeCd CHAR(5),
        importId INT,
        seqId INT
    ) I;
    IF EXISTS (SELECT i.seqId FROM #tmpInvs i WHERE i.seqId != NULL)
    WITH cte AS
    (
        SELECT i.*,ci.case_ident_id AS case_ident_id, ki.inv_type_name AS inv_type_name
        FROM #tmpInvs i
        INNER JOIN case_idents ci ON i.importId=ci.import_id
        INNER JOIN kdd_inv_type ki ON i.invTypeCd=ki.inv_type_cd
    )
    UPDATE T
    SET
        inv_id = ct.userId,
        inv_type_cd = ct.invTypeCd,
        inv_type_name = ct.inv_type_name
    FROM case_ident_to_inv T
    INNER JOIN cte AS ct ON ct.case_ident_id = T.case_ident_id

    WHERE seq_id = ct.seqId

    ELSE

    INSERT INTO case_ident_to_inv(inv_id, case_ident_id, inv_type_cd, inv_type_name)
    SELECT userId, case_ident_id, invTypeCd, inv_type_name
    FROM cte
0 голосов
/ 31 октября 2018

Вы не можете поставить IF после объявления cte, потому что следующая команда - та, которая должна использовать cte. Однако вы можете заменить конструкцию if / update / insert одним оператором слияния. Примерно так:

    merge case_ident_to_inv as Target
using (select * from cte) as Source 
on Target.case_ident_id = Source.case_ident_id
when matched then update set
    inv_id = Source.userId,
    inv_type_cd = Source.invTypeCd,
    inv_type_name = Source.inv_type_name
when not matched then
    insert(inv_id, case_ident_id, inv_type_cd, inv_type_name)
    values(Source.userId, Source.case_ident_id, Source.invTypeCd, Source.inv_type_name);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...