OPENJSON 语法错误

OPENJSON syntax error

我在使用以下内容时遇到问题

ALTER PROCEDURE [SaveGlobalFines]
@JSON NVARCHAR(MAX)
AS
BEGIN
  DECLARE @ChargeID       INT
  DECLARE @FineTypeID       INT
  DECLARE @AmountDB       MONEY
  DECLARE @AmountJSON     MONEY
  DECLARE @userID       INT
  DECLARE @Counter      INT


SELECT @ChargeID=Fine.Charge_Id, @FineTypeID=Fine.FineType_Id, @AmountDB = Fine.Amount , @AmountJSON = JSON.Amount, @userID = JSON.user_id
   FROM Fine  
   CROSS APPLY OPENJSON(@JSON,'$.amounts') 
   WITH(Charge_Id int, Amount money, FineType_Id int, user_id int)AS JSON
   WHERE Fine.Charge_Id =JSON.Charge_Id and Fine.FineType_Id= JSON.FineType_Id and Fine.DateExpired IS NULL


     IF @ChargeID IS NULL AND @FineTypeID IS NULL  --if fine type and charge id are returned null insert new row
     BEGIN
       INSERT INTO  Fine (Charge_Id,Amount,FineType_Id,user_id)
       SELECT *
       FROM OPENJSON(@JSON,'$.amounts') 
       WITH(Charge_Id int , Amount money, FineType_Id int, user_id int )AS JSON
     END 
    ELSE-- Check if amount is the same if yes do not update current record and enter a new one
      IF @AmountDB <> @AmountJSON
       BEGIN
          UPDATE Fine set DateExpired= GETDATE(), ExpiryDescription ='Updated by'+ CONVERT(NVARCHAR(10), JSON.user_id)
            FROM OPENJSON(@JSON,'$.amounts') 
            WITH(Charge_Id int , Amount money, FineType_Id int, user_id int )AS JSON
            WHERE Fine.Charge_Id =JSON.Charge_Id and Fine.FineType_Id=JSON.FineType_Id

            INSERT INTO  Fine (Charge_Id,Amount,FineType_Id,user_id)
            SELECT *
            FROM OPENJSON(@JSON,'$.amounts') 
            WITH(Charge_Id int, Amount money, FineType_Id int, user_id int)AS JSON
     END
END  

显然变量示例@chargeID 被json 文件中的最后一个元素覆盖。这有效

SELECT *
FROM OPENJSON(@JSON,'$.amounts[0]') 
WITH(Charge_Id int, Amount money, FineType_Id int, user_id int)AS JSON

我想做类似下面的事情,但用一个计数器代替,因为 JSON 文件并不总是相同的。它可能只有一个元素,上面的内容可以正常工作,但如果它有 4 个元素,它就不起作用

SELECT *
FROM OPENJSON(@JSON,'$.amounts[+'@Counter'+]') 
WITH(Charge_Id int, Amount money, FineType_Id int, user_id int)AS JSON

但这会引发错误。 JSON 被传递如下

>  "amounts": [
>     {
>       "Charge_Id": "368",
>       "Amount": "800",
>       "FineType_Id": 3,
>       "user_id": 2
>     },
>     {
>       "Charge_Id": "368",
>       "Amount": "600",
>       "FineType_Id": 4,
>       "user_id": 2
>     }   ]

请帮忙

如果我对您的评论理解正确,您实际上并不想从 json 中提取特定项目,而是想对 returned 的每条记录做一些事情。

如果这是正确的,您只需按照其设计的基于集合的方式使用 SQL。例如,此脚本 return 是一个附加列,用于检查 Amount 列中的值是否小于 700

declare @JSON nvarchar(max)
declare @counter int

set @JSON ='{ 
     "amounts": [
 {
  "Charge_Id": "368",
  "Amount": "800",
  "FineType_Id": 3,
  "user_id": 2
 },
{
  "Charge_Id": "368",
  "Amount": "400",
  "FineType_Id": 4,
  "user_id": 2
 }
 ] 
}';

select j.*
        ,case when j.Amount < 700
                then 'Less than £700'
                else 'Not less than £700'
                end as col
from openjson(@JSON,'$.amounts') with (Charge_Id int, Amount money, FineType_Id int, user_id int) as j;

输出:

+-----------+--------+-------------+---------+-------------------+
| Charge_Id | Amount | FineType_Id | user_id |        col        |
+-----------+--------+-------------+---------+-------------------+
|       368 | 800.00 |           3 |       2 | Not less than 700 |
|       368 | 400.00 |           4 |       2 | Less than 700     |
+-----------+--------+-------------+---------+-------------------+

如果您希望根据 json 数据进行一些 updateinsertdelete 操作,您也可以在正常 SQL 设置基础方式。


如果您需要对 json 数据进行一些额外的过滤,您可以像任何其他查询一样放入 where 子句。将您的脚本更改为以下内容只会 return 一行 FineType_id3 的记录:

select j.*
        ,case when j.Amount < 700
                then 'Less than 700'
                else 'Not less than 700'
                end as col
from openjson(@JSON,'$.amounts') with (Charge_Id int, Amount money, FineType_Id int, user_id int) as j
where j.FineType_id = 3;