【问题标题】:Node-Red, SQL Server INSERT INTO (columns...) SELECT Columns... FROM OPENJSON({{{payload}}}) WITHNode-Red, SQL Server INSERT INTO (columns...) SELECT Columns... FROM OPENJSON({{{payload}}}) WITH
【发布时间】:2021-11-17 15:22:09
【问题描述】:

我正在尝试从公共 APE 获取一些 JSON 数据并将记录插入到我的 SQL Azure 数据库中。 API 请求正在工作,JSON 节点中的转换为对象也是如此,但我无法缝合以获取 OPENJSON() 函数来正确解析 json 数据对象。我收到此错误:

RequestError:JSON 文本格式不正确。在位置 1 发现了意外的字符“o”。

从api获取的json数据为:

{ 
  "data":[{ 
    "from": "2021-09-22T23:00Z",
    "to": "2021-09-22T23:30Z",
    "intensity": {
      "forecast": 105,
      "actual": 91,
      "index": "low"
    }
  },
  { 
    "from": "2021-09-22T23:30Z",
    "to": "2021-09-23T00:00Z",
    "intensity": {
      "forecast": 92,
      "actual": 80,
      "index": "low"
    }
  },
  { 
    "from": "2021-09-23T22:00Z",
    "to": "2021-09-23T22:30Z",
    "intensity": {
      "forecast": 153,
      "actual": null, 
      "index": "low"
    }
  },
  { 
    "from": "2021-09-23T22:30Z",
    "to": "2021-09-23T23:00Z",
    "intensity": {
      "forecast": 150,
      "actual": null, 
      "index": "low"
    }
  }]
}

SQL Azure 节点代码如下:

DECLARE @data NVARCHAR(MAX) = N'{{{payload}}}';

INSERT INTO TCarbonIntensity ([from], [to], [forecast], [actual], [index])
    SELECT [from], [to], [forecast], [actual], [index]
    FROM OPENJSON(@data)
    WITH (
        [from] datetime '$.from',
        [to] datetime '$.to',
        [forecast] int '$.intensity.forecast',
        [actual] int '$.intensity.actual',
        [index] nvarchar(5) '$.intensity.index'
    );

【问题讨论】:

  • 你能提供一个minimal reproducible example吗?您的问题中的 JSON is 有效(尽管查询不返回任何结果,这是该 JSON 所期望的):db<>fiddle
  • 对于给定的 JSON,您可能需要 FROM OPENJSON(@data, '$.data'),但您将遇到的下一个问题是 fromto 属性的无效日期格式。
  • 感谢@AlwaysLearning 的建议,这是我已经尝试过的选项之一。感谢您的意见。

标签: json sql-server node-red


【解决方案1】:

请尝试以下解决方案。

正如@AlwaysLearning 在 cmets 中已经提到的,JSON 的日期时间值格式有问题。这就是为什么需要轻微按摩的原因。

另外,我使用DATETIMEOFFSET(3) 数据类型来保留时区。

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY,
        [from] DATETIMEOFFSET(3),
        [to] DATETIMEOFFSET(3),
        [forecast] int,
        [actual] int,
        [index] nvarchar(5)
);
-- DDL and sample data population, end

DECLARE @data NVARCHAR(MAX) =
N'{
    "data": [
        {
            "from": "2021-09-22T23:00Z",
            "to": "2021-09-22T23:30Z",
            "intensity": {
                "forecast": 105,
                "actual": 91,
                "index": "low"
            }
        },
        {
            "from": "2021-09-22T23:30Z",
            "to": "2021-09-23T00:00Z",
            "intensity": {
                "forecast": 92,
                "actual": 80,
                "index": "low"
            }
        },
        {
            "from": "2021-09-23T22:00Z",
            "to": "2021-09-23T22:30Z",
            "intensity": {
                "forecast": 153,
                "actual": null,
                "index": "low"
            }
        },
        {
            "from": "2021-09-23T22:30Z",
            "to": "2021-09-23T23:00Z",
            "intensity": {
                "forecast": 150,
                "actual": null,
                "index": "low"
            }
        }
    ]
}';

INSERT INTO @tbl ([from], [to], [forecast], [actual], [index])
SELECT LEFT([from],16) + ':00Z', LEFT([to],16) + ':00Z', [forecast], [actual], [index]
FROM OPENJSON(@data, '$.data')
WITH (
    [from] VARCHAR(30) '$.from',
    [to] VARCHAR(30) '$.to',
    [forecast] int '$.intensity.forecast',
    [actual] int '$.intensity.actual',
    [index] nvarchar(5) '$.intensity.index'
);

-- test
SELECT * FROM @tbl;

输出

+----+--------------------------------+--------------------------------+----------+--------+-------+
| ID |              from              |               to               | forecast | actual | index |
+----+--------------------------------+--------------------------------+----------+--------+-------+
|  1 | 2021-09-22 23:00:00.000 +00:00 | 2021-09-22 23:30:00.000 +00:00 |      105 | 91     | low   |
|  2 | 2021-09-22 23:30:00.000 +00:00 | 2021-09-23 00:00:00.000 +00:00 |       92 | 80     | low   |
|  3 | 2021-09-23 22:00:00.000 +00:00 | 2021-09-23 22:30:00.000 +00:00 |      153 | NULL   | low   |
|  4 | 2021-09-23 22:30:00.000 +00:00 | 2021-09-23 23:00:00.000 +00:00 |      150 | NULL   | low   |
+----+--------------------------------+--------------------------------+----------+--------+-------+

【讨论】:

  • 感谢 Yitzhak,这也确实有帮助,并且在您提交的示例中有效,但是一旦我尝试将您的代码转换为从 Node-Red JSON 有效负载接收 JSON,我就回来了平方一个!声明 \@data NVARCHAR(MAX) = N'{{{payload}}}'; RequestError:JSON 文本格式不正确。在位置 1 发现意外字符“o”。
  • JSON 只是一个文本。您可以检查它,并在 T-SQL 中使用它之前以编程方式删除任何“坏”字符。
  • 谢谢 Yitzhak,我明白了,但我认为我们在这个线程上建立的是,当我们将原始 JSON 文本嵌入到 SQLServer 节点时,这个工作的 SQL 端,所以问题在于处理从 API 接收到的 JSON 文本,使其以可接受的方式插入 SQL 节点。
  • 感谢大家的帮助。我现在将重点放在 Node-Red 上。
  • 此外,您可以随时通过 T-SQL 检查 JSON 是否合法:SELECT ISJSON(@json)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-04
  • 2013-06-21
  • 2012-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多