You need to enable JavaScript to run this app. SQL Server存储过程使用JSON入参执行出现格式报错的排查
优惠活动
大模型
产品
解决方案
定价
更多

SQL Server存储过程使用JSON入参执行出现格式报错的排查

关于SQL Server存储过程接收JSON入参的问题解答

核心疑问确认

SQL Server 完全支持 将NVARCHAR(MAX)类型存储的JSON格式字符串作为存储过程输入参数,该用法是SQL Server 2016及以上版本内置JSON解析能力(OPENJSON、ISJSON等函数)的官方推荐实现方式,不存在参数类型不兼容的问题。

报错根因拆解

本次遇到的JSON格式解析错误、存储过程执行报错,是两部分问题叠加导致的:

1. 传入的JSON字符串本身格式非法(直接触发JSON解析报错)

报错提示的"Unexpected character '.' is found at position 480"是典型的JSON结构错位导致的偏移计算错误,并非真的在第480个字符位置存在非法点号:

  • JSON结构中混入了多余的单引号:你编写的JSON闭合位置写为}''},SQL解析器会把单引号识别为T-SQL字符串的边界,提前截断JSON内容,剩余零散字符被当成JSON的一部分继续解析,最终位置偏移后碰到点号就抛出错误。
  • JSON嵌套对象的结构不匹配:data字段对应的对象大括号没有和外层结构正确配对,中途换行时的引号书写不规范,导致解析器无法正确识别对象层级。
  • 部分字段值本身不合法:比如DueDate字段写了月份为13的日期值,就算JSON格式正确,后续类型转换也会失败。

2. 存储过程本身存在语法错误

就算JSON入参格式正确,原存储过程的写法也无法正常执行,存在多处语法漏洞:

  • OPENJSON的WITH子句中,RegionCode字段定义后漏写了列分隔的逗号,直接衔接了DueDate的定义。
  • MERGE语句的UPDATE分支中,TARGET.[RegionCode]赋值语句多写了左括号未闭合。
  • 存储过程命名前后不一致:创建语句中写的存储过程名是[warm].[stored _table](中间还带了多余空格),但实际调用时用的是[warm].[usp_upsert_warm_table],名称不匹配会导致存储过程找不到。

正确实现方案

1. 修正后的存储过程代码

-- 统一存储过程命名,和调用语句保持一致
CREATE PROCEDURE [warm].[usp_upsert_warm_table]  
(
  @Json NVARCHAR(MAX)
)
AS
BEGIN
  SET NOCOUNT ON;
  BEGIN TRY
    -- 入参校验:提前判断JSON格式,抛出清晰错误
    IF ISJSON(@Json) <> 1
    BEGIN
      THROW 50001, '传入的JSON字符串格式非法,请检查结构', 1;
    END

    WITH JsonToTable AS 
    (
        SELECT * FROM OPENJSON (@Json) 
        WITH (
            [type] [nvarchar](100), 
            [source] [nvarchar](38), 
            [time] [nvarchar](28), 
            [ID] [varchar](50) '$.data.ID',
            [RegionCode] [varchar](10) '$.data.RegionCode', -- 补全漏写的逗号
            [DueDate] [datetime2](7) '$.data.DueDate',
            [SchedulStartDate] [datetime2](7) '$.data.SchedulStartDate'
        )
    )
    MERGE [warm].[table] AS TARGET 
    USING JsonToTable AS SOURCE 
    ON (TARGET.ID = SOURCE.ID)
    WHEN MATCHED THEN
     UPDATE SET 
        -- 移除多余的左括号
        TARGET.[RegionCode] = SOURCE.[RegionCode],
        TARGET.[DueDate] = [dbo].[ufn_cast_string_to_date](SOURCE.[DueDate]),
        TARGET.[SchedulStartDate] = [dbo].[ufn_cast_string_to_date](SOURCE.[SchedulStartDate])
    WHEN NOT MATCHED THEN
        INSERT 
            (
             [SourceID]
            ,[ID]
            ,[RegionCode]
            ,[DueDate]
            ,[SchedulStartDate])
        VALUES
            (
             1
            ,SOURCE.[ID]
            ,SOURCE.[RegionCode]
            ,[dbo].[ufn_cast_string_to_date](SOURCE.[DueDate])
            ,[dbo].[ufn_cast_string_to_date](SOURCE.[SchedulStartDate])
    );                 
  END TRY
  BEGIN CATCH
    -- 捕获错误并抛出,避免静默失败
    THROW;
  END CATCH
END

2. 修正后的存储过程调用代码

严格按照标准JSON规范编写入参,所有结构边界用双引号包裹、大括号成对闭合,避免混入单引号、多余符号:

DECLARE @return_value int
EXEC    @return_value = [warm].[usp_upsert_warm_table]
@Json = N'{
  "type" : "table",
  "source" : "informations",
  "time" : "2018-04-05T17:31:00Z",
  "id" : "A11-111-111",
  "data" : {
    "ID":"123-56",
    "RegionCode":"2",
    "DueDate":"2020-12-14T10:54:00",
    "SchedulStartDate":"2020-12-14T10:54:00" 
  }
}'

内容的提问来源于stack exchange,提问作者nada

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.02 14:27:01