You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JSON数组插入SQL表存储过程报错:无效对象名#SubJsonRequest

JSON数组插入SQL表的正确方案

表结构回顾

  • Doc表:Id(主键)、Name、Desc、RefName、IsActive
  • Con表:Id(主键)、Field、Criter、DId(外键关联Doc.Id)、Conjunction、IsActive

错误原因分析

提示“Invalid object name '#SubJsonRequest'”,大概率是临时表#SubJsonRequest的作用域问题:要么没在循环外提前创建,要么在循环过程中被意外销毁。另外,用WHILE循环处理JSON数组本身就不是SQL Server的最优实践,推荐用基于集合的操作替代循环,效率更高且不易出错。

推荐方案:用OPENJSON批量插入(无循环)

以下是优化后的SaveDoc存储过程,直接解析JSON数组批量插入两张表:

示例输入JSON

{
  "Docs": [
    {
      "Name": "文档1",
      "Desc": "描述1",
      "RefName": "REF001",
      "IsActive": 1,
      "Conditions": [
        {
          "Field": "字段A",
          "Criter": "条件1",
          "Conjunction": "AND",
          "IsActive": 1
        },
        {
          "Field": "字段B",
          "Criter": "条件2",
          "Conjunction": "OR",
          "IsActive": 1
        }
      ]
    },
    {
      "Name": "文档2",
      "Desc": "描述2",
      "RefName": "REF002",
      "IsActive": 1,
      "Conditions": [
        {
          "Field": "字段C",
          "Criter": "条件3",
          "Conjunction": "AND",
          "IsActive": 1
        }
      ]
    }
  ]
}

优化后的存储过程

CREATE PROCEDURE SaveDoc
    @Json NVARCHAR(MAX)
AS
BEGIN
    SET NOCOUNT ON;

    -- 临时表存储插入的Doc ID及对应的Conditions数组
    DECLARE @InsertedDocs TABLE (
        DocId INT,
        Conditions NVARCHAR(MAX)
    );

    -- 插入Doc表,同时捕获ID和关联的Conditions
    INSERT INTO Doc (Name, [Desc], RefName, IsActive)
    OUTPUT inserted.Id, JSON_QUERY(j.Conditions) INTO @InsertedDocs(DocId, Conditions)
    SELECT 
        j.Name,
        j.[Desc],
        j.RefName,
        j.IsActive
    FROM OPENJSON(@Json, '$.Docs')
    WITH (
        Name NVARCHAR(100),
        [Desc] NVARCHAR(MAX),
        RefName NVARCHAR(50),
        IsActive BIT,
        Conditions NVARCHAR(MAX) AS JSON -- 标记为JSON类型,保留数组结构
    ) j;

    -- 批量插入Con表,通过CROSS APPLY展开Conditions数组
    INSERT INTO Con (Field, Criter, DId, Conjunction, IsActive)
    SELECT
        c.Field,
        c.Criter,
        d.DocId,
        c.Conjunction,
        c.IsActive
    FROM @InsertedDocs d
    CROSS APPLY OPENJSON(d.Conditions)
    WITH (
        Field NVARCHAR(100),
        Criter NVARCHAR(MAX),
        Conjunction NVARCHAR(10),
        IsActive BIT
    ) c;
END

若坚持用循环处理(不推荐)

如果一定要用WHILE循环,需确保临时表在循环外创建,避免作用域问题:

CREATE PROCEDURE SaveDoc
    @Json NVARCHAR(MAX)
AS
BEGIN
    SET NOCOUNT ON;

    -- 提前解析所有Doc数据到临时表
    CREATE TABLE #Docs (
        RowId INT IDENTITY(1,1),
        Name NVARCHAR(100),
        [Desc] NVARCHAR(MAX),
        RefName NVARCHAR(50),
        IsActive BIT,
        Conditions NVARCHAR(MAX) AS JSON
    );

    INSERT INTO #Docs (Name, [Desc], RefName, IsActive, Conditions)
    SELECT 
        Name, [Desc], RefName, IsActive, Conditions
    FROM OPENJSON(@Json, '$.Docs')
    WITH (
        Name NVARCHAR(100),
        [Desc] NVARCHAR(MAX),
        RefName NVARCHAR(50),
        IsActive BIT,
        Conditions NVARCHAR(MAX) AS JSON
    );

    DECLARE @CurrentRow INT = 1;
    DECLARE @TotalRows INT = (SELECT COUNT(*) FROM #Docs);
    DECLARE @DocId INT;
    DECLARE @Name NVARCHAR(100);
    DECLARE @Desc NVARCHAR(MAX);
    DECLARE @RefName NVARCHAR(50);
    DECLARE @IsActive BIT;
    DECLARE @Conditions NVARCHAR(MAX);

    WHILE @CurrentRow <= @TotalRows
    BEGIN
        -- 获取当前行的Doc数据
        SELECT 
            @Name = Name,
            @Desc = [Desc],
            @RefName = RefName,
            @IsActive = IsActive,
            @Conditions = Conditions
        FROM #Docs WHERE RowId = @CurrentRow;

        -- 插入Doc表并获取自增ID
        INSERT INTO Doc (Name, [Desc], RefName, IsActive)
        VALUES (@Name, @Desc, @RefName, @IsActive);
        SET @DocId = SCOPE_IDENTITY();

        -- 插入关联的Conditions到Con表
        INSERT INTO Con (Field, Criter, DId, Conjunction, IsActive)
        SELECT
            Field, Criter, @DocId, Conjunction, IsActive
        FROM OPENJSON(@Conditions)
        WITH (
            Field NVARCHAR(100),
            Criter NVARCHAR(MAX),
            Conjunction NVARCHAR(10),
            IsActive BIT
        );

        SET @CurrentRow = @CurrentRow + 1;
    END

    DROP TABLE #Docs;
END

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 11:13:27