OPENJSON语法错误

时间:2017-05-17 09:37:59

标签: json sql-server-2016

使用以下

时出现问题
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  

显然,vailarables示例@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
>     }   ]

请帮忙

1 个答案:

答案 0 :(得分:1)

如果我正确理解您的评论,您实际上并不想从json中提取特定项目,而是希望对返回的每条记录执行某些操作。

如果这是正确的,您只需要在设计的基础上使用SQL。例如,此脚本返回一个附加列,用于检查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     |
+-----------+--------+-------------+---------+-------------------+

如果您希望基于update数据执行某些insertdeletejson操作,您还可以在基于正常SQL集的方式中执行这些操作

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

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;