我要发送的对象带有嵌套数组和数组中的对象。此过程应根据是否存在ID更新表中的数据,如果不存在,则应将其插入表中。执行此过程时,它仅更新外部对象(cases表)和包含caseIdentifierId的标识符数组中的对象。它不会在case_identifiers表中创建新的案例标识符,而应该这样做。标识符数组中的研究者和服务数组应该知道它们属于该标识符,因此已添加了“ importId”。每个标识符对象都有其自己的importId。包含“ seqId”的调查者和服务意味着它们是以前创建的,因此应在表中更新而不是插入。
ALTER PROCEDURE cases_updateAll
@caseObj NVARCHAR(MAX)
/*
DECLARE @caseObj NVARCHAR(MAX) = N'[
{
"caseId": 1010,
"caseName": "Fruit",
"identifiers": [
{
"caseIdentifierId": 1030,
"importId": 2,
"identifierName": "Apple",
"investigators": [
{
"seqId": 50,
"importId": 2,
"investigatorId": 163,
"investigatorTypeCd": "LI"
},
{
"importId": 2,
"investigatorId": 178,
"investigatorTypeCd": "RV"
}
],
"services": [
{
"importId": 2,
"serviceId": 115,
"serviceCatCd": "OTH",
"servicePrice": 2250
},
{
"importId": 2,
"serviceId": 110,
"serviceCatCd": "INTL",
"servicePrice": 900
}
]
},
{
"importId": 3,
"identifierName": "Orange",
"investigators": [
{
"importId": 3,
"investigatorId": 139,
"investigatorTypeCd": "RV"
},
{
"importId": 3,
"investigatorId": 138,
"investigatorTypeCd": "SI"
}
],
"services": [
{
"importId": 3,
"serviceId": 107,
"serviceCatCd": "DD",
"servicePrice": 44550
}
]
}
]
}
]';
EXECUTE cases_updateAll @caseObj=@caseObj
*/
AS
DECLARE @importId INT
SET @importId = 1
BEGIN
----------更新案例表----------
WITH json_data as
(
SELECT *
FROM OPENJSON(@caseObj) A
CROSS APPLY OPENJSON(A.value)
WITH
(
caseId INT,
caseName NVARCHAR(500)
)
)
UPDATE c
SET
date_modified = GETUTCDATE(),
case_name = jd.caseName,
import_id = @importId
FROM
cases AS c
INNER JOIN json_data AS jd ON jd.caseId = c.case_id
WHERE case_id = jd.caseId
----------更新并插入case_identifiers表----------
select B.*
INTO #tmpIdents
FROM OPENJSON(@caseObj)
WITH (
identifiers NVARCHAR(MAX) AS JSON
) AS caseIdents
CROSS APPLY OPENJSON (caseIdents.identifiers)
WITH (
caseIdentifierId INT,
identifierName NVARCHAR(500),
importId INT
) B;
WITH Acte AS
(
SELECT c.*,ci.case_identifier_id AS case_ident_id
FROM #tmpIdents c
INNER JOIN case_identifiers ci ON c.importId=ci.import_id
)
MERGE case_identifiers AS Target
USING (SELECT * FROM Acte) AS SOURCE
ON Target.case_identifier_id = Source.caseIdentifierId
WHEN MATCHED THEN UPDATE SET
date_modified = GETUTCDATE(),
identifier_name = Source.identifierName,
import_id = Source.importId
WHEN NOT MATCHED THEN
INSERT(
identifier_name,
import_id
)
VALUES(
Source.identifierName,
Source.importId
);
----------插入case_to_case_identifier ----------
INSERT INTO case_to_case_identifier
(case_id, case_identifier_id)
SELECT c.case_id, ci.case_identifier_id
FROM #tmpIdents ti
INNER JOIN cases c ON c.import_id=1
INNER JOIN case_identifiers ci ON ci.import_id=ti.importId
----------插入case_identifier_to_investigator表----------
select C.*
INTO #tmpInvs
FROM OPENJSON(@caseObj)
WITH (
identifiers NVARCHAR(MAX) AS JSON
) AS caseIdents
CROSS APPLY OPENJSON (caseIdents.identifiers)
WITH (
investigators NVARCHAR(MAX) AS JSON
) AS caseIdentInvs
CROSS APPLY OPENJSON (caseIdentInvs.investigators)
WITH (
investigatorId INT,
investigatorTypeCd CHAR(5),
importId INT,
seqId INT
) C;
WITH cte AS
(
SELECT c.*,ci.case_identifier_id AS case_ident_id
FROM #tmpInvs c
INNER JOIN case_identifiers ci ON c.importId=ci.import_id
INNER JOIN kdd_investigator_type ki ON c.investigatorTypeCd=ki.investigator_type_cd
)
MERGE case_identifier_to_investigator AS Target
USING (SELECT * FROM cte) AS SOURCE
ON Target.seq_id = Source.seqId
WHEN MATCHED THEN UPDATE SET
investigator_id = Source.investigatorId,
investigator_type_cd = Source.investigatorTypeCd
WHEN NOT MATCHED THEN
INSERT(investigator_id, case_identifier_id, investigator_type_cd)
VALUES(Source.investigatorId, Source.case_ident_id, Source.investigatorTypeCd);
---------- INSERT INTO case_identifier_to_service表----------
select D.*
INTO #tmpServs
FROM OPENJSON(@caseObj)
WITH (
[services] NVARCHAR(MAX) AS JSON
) AS caseIdentServs
CROSS APPLY OPENJSON (caseIdentServs.[services])
WITH (
serviceId INT,
importId INT,
seqId INT,
servPrice DECIMAL
) D;
WITH Scte AS
(
SELECT c.*,ci.case_identifier_id AS case_ident_id
FROM #tmpServs c
INNER JOIN case_identifiers ci ON c.importId=ci.import_id
)
MERGE case_identifier_to_service AS Target
USING (SELECT * FROM Scte) AS SOURCE
ON Target.seq_id = Source.seqId
WHEN MATCHED THEN UPDATE SET
service_id = Source.serviceId
WHEN NOT MATCHED THEN
INSERT(service_id, case_identifier_id, service_price)
VALUES(Source.serviceId, Source.case_ident_id, Source.servPrice);
----------将importId设置为NULL ----------
UPDATE case_identifiers SET import_id = null;
UPDATE cases SET import_id = null;
END
----------表格图----------
Cases
+-------------+---------+
| import_id | case_id |
+-------------+---------+
| NULL | 1008 |
| NULL | 1009 |
| 1 | 1010 | <--- @importId sets this to 1
+-------------+---------+
TmpIdents (c)
+-------------+---------------+
| import_id | case_ident_id |
+-------------+---------------+
| 2 | 1030 |
| 3 | NULL |
+-------------+---------------+
Case Identifiers (ci)
+-------------+---------------+
| import_id | case_ident_id |
+-------------+---------------+
| 2 | 1030 |
| 3 | NULL | <--- will become 1040
+-------------+---------------+
Case to Case Identifiers
+-------------+--------------+---------------+--------+
| import_id | case_id | case_ident_id | seq_id |
+-------------+--------------+---------------+--------+
| 2 | 1010 | 1030 | 50 |
| 3 | 1010 | 1040 | 51 |
+-------------+--------------+---------------+--------+
Case Identifier to Investigator
+-------------+---------+--------------+---------------+--------+
| import_id | inv_id | inv_type_cd | case_ident_id | seq_id |
+-------------+---------+--------------+---------------+--------+
| 2 | 163 | LI | 1030 | 64 |
| 2 | 178 | RV | 1030 | 65 |
| 3 | 139 | RV | 1040 | 66 |
| 3 | 138 | SI | 1040 | 67 |
+-------------+---------+--------------+---------------+--------+
Case Identifier to Service
+-------------+---------+---------------+--------+
| import_id | serv_id | case_ident_id | seq_id |
+-------------+---------+---------------+--------+
| 2 | 115 | 1030 | 23 |
| 2 | 110 | 1030 | 24 |
| 3 | 107 | 1040 | 25 |
+-------------+---------+---------------+--------+
答案 0 :(得分:0)
这个答案来得很晚,希望它还是有帮助的。
您的问题是 TL; TR ,但我想我可以为您指出一种替代方法,该方法使工作更加轻松:尝试将整批商品读取到暂存表中然后从那里继续:
DECLARE @caseObj NVARCHAR(MAX) = N'[
{
"caseId": 1010,
"caseName": "Fruit",
"identifiers": [
{
"caseIdentifierId": 1030,
"importId": 2,
"identifierName": "Apple",
"investigators": [
{
"seqId": 50,
"importId": 2,
"investigatorId": 163,
"investigatorTypeCd": "LI"
},
{
"importId": 2,
"investigatorId": 178,
"investigatorTypeCd": "RV"
}
],
"services": [
{
"importId": 2,
"serviceId": 115,
"serviceCatCd": "OTH",
"servicePrice": 2250
},
{
"importId": 2,
"serviceId": 110,
"serviceCatCd": "INTL",
"servicePrice": 900
}
]
},
{
"importId": 3,
"identifierName": "Orange",
"investigators": [
{
"importId": 3,
"investigatorId": 139,
"investigatorTypeCd": "RV"
},
{
"importId": 3,
"investigatorId": 138,
"investigatorTypeCd": "SI"
}
],
"services": [
{
"importId": 3,
"serviceId": 107,
"serviceCatCd": "DD",
"servicePrice": 44550
}
]
}
]
}
]';
-通过为任何嵌套列表添加APPLY OPENJSON
,查询将越来越深入。
-将结果隐式写入物理表
SELECT A.caseId
,A.caseName
,identif.caseIdentifierId AS identif_caseIdentifier
,identif.importId AS identif_importId
,identif.identifierName AS identif_identifierName
,invest.seqId AS invest_seqId
,invest.importId AS invest_importId
,invest.investigatorId AS invest_investigatorId
,invest.investigatorTypeCd AS invest_investigatorTypeCd
,serv.importId AS serv_importId
,serv.serviceId AS serv_serviceId
,serv.serviceCatCd AS serv_serviceCatCd
,serv.servicePrice AS serv_servicePrice
INTO #tmpStagingTable
FROM OPENJSON(@caseObj)
WITH(caseId INT, caseName NVARCHAR(200)
,identifiers NVARCHAR(MAX) AS JSON) A
OUTER APPLY OPENJSON(A.identifiers)
WITH(caseIdentifierId INT, importId INT, identifierName NVARCHAR(200)
,investigators NVARCHAR(MAX) AS JSON
,[services] NVARCHAR(MAX) AS JSON) identif
OUTER APPLY OPENJSON(identif.investigators)
WITH(seqId INT, importId INT, investigatorId INT, investigatorTypeCd NVARCHAR(100)) invest
OUTER APPLY OPENJSON(identif.[services])
WITH(importId INT,serviceId INT,serviceCatCd NVARCHAR(100),servicePrice DECIMAL(10,4)) serv;
-查看结果
SELECT * FROM #tmpStagingTable;
+--------+----------+------------------------+------------------+------------------------+--------------+-----------------+-----------------------+---------------------------+---------------+----------------+-------------------+-------------------+
| caseId | caseName | identif_caseIdentifier | identif_importId | identif_identifierName | invest_seqId | invest_importId | invest_investigatorId | invest_investigatorTypeCd | serv_importId | serv_serviceId | serv_serviceCatCd | serv_servicePrice |
+--------+----------+------------------------+------------------+------------------------+--------------+-----------------+-----------------------+---------------------------+---------------+----------------+-------------------+-------------------+
| 1010 | Fruit | 1030 | 2 | Apple | 50 | 2 | 163 | LI | 2 | 115 | OTH | 2250.0000 |
+--------+----------+------------------------+------------------+------------------------+--------------+-----------------+-----------------------+---------------------------+---------------+----------------+-------------------+-------------------+
| 1010 | Fruit | 1030 | 2 | Apple | 50 | 2 | 163 | LI | 2 | 110 | INTL | 900.0000 |
+--------+----------+------------------------+------------------+------------------------+--------------+-----------------+-----------------------+---------------------------+---------------+----------------+-------------------+-------------------+
| 1010 | Fruit | 1030 | 2 | Apple | NULL | 2 | 178 | RV | 2 | 115 | OTH | 2250.0000 |
+--------+----------+------------------------+------------------+------------------------+--------------+-----------------+-----------------------+---------------------------+---------------+----------------+-------------------+-------------------+
| 1010 | Fruit | 1030 | 2 | Apple | NULL | 2 | 178 | RV | 2 | 110 | INTL | 900.0000 |
+--------+----------+------------------------+------------------+------------------------+--------------+-----------------+-----------------------+---------------------------+---------------+----------------+-------------------+-------------------+
| 1010 | Fruit | NULL | 3 | Orange | NULL | 3 | 139 | RV | 3 | 107 | DD | 44550.0000 |
+--------+----------+------------------------+------------------+------------------------+--------------+-----------------+-----------------------+---------------------------+---------------+----------------+-------------------+-------------------+
| 1010 | Fruit | NULL | 3 | Orange | NULL | 3 | 138 | SI | 3 | 107 | DD | 44550.0000 |
+--------+----------+------------------------+------------------+------------------------+--------------+-----------------+-----------------------+---------------------------+---------------+----------------+-------------------+-------------------+
由此您可以继续。有多种方法:
MERGE
进行选择,在您的所有表中使用多个GROUP BY
语句。通过这样的操作,我建议始终在两者之间放置一个暂存步骤。