Sql 在INSERT查询中将JSON键映射为列名

Sql 在INSERT查询中将JSON键映射为列名,sql,json,sql-server,stored-procedures,Sql,Json,Sql Server,Stored Procedures,我正在编写一个存储过程来将这些值插入表中。始终我的表列名将是键,列数据将是JSON中的值 DECLARE @json NVARCHAR(MAX) = N'[ { "name": "abcd", "id": 12, "feelings": { "happy": 0,

我正在编写一个存储过程来将这些值插入表中。始终我的表列名将是键,列数据将是JSON中的值

DECLARE @json NVARCHAR(MAX) = N'[
          {
            "name": "abcd",
            "id": 12,
            "feelings": {
              "happy": 0,
              "angry": 1,
              "sad": 1
            }
          },
          {
            "name": "abcdf",
            "id": 14,
            "feelings": {
              "happy": 0,
              "angry": 1,
              "sad": 1
            }
          }
        ]'

DECLARE @id INT;
DECLARE @last_name NVARCHAR(50);
SET @id =10;
SET @last_name = 'Mike'
    
例如:

INSERT INTO Table([name],[id],[lastname],[happy],[angry],[sad]) 
VALUES ("abcd",@id,@last_name,0,1,1)


How can I achieve this for any JSON format? Always the JSON key should be mapped to the column name. The insert statement should be able to insert all the entries from the JSON. Only the key inside the feelings will change. All others remain the same.
我需要在insert查询中包含来自JSON的数据以及静态声明的数据。OPENJSON是否允许在中包含静态数据


请帮我解决这个问题。

我认为动态声明应该是您的第一选择:

JSON:

声明:

DECLARE @stm nvarchar(max)
DECLARE @columns nvarchar(max)
DECLARE @schema nvarchar(max)

DECLARE @id int
SET @id = 10

SELECT 
   @columns = STRING_AGG(QUOTENAME([key]), N','),
   @schema = STRING_AGG(CONCAT(QUOTENAME([key]), N' int ''$.feelings."', [key], '"'''), N',')
FROM OPENJSON(@json, '$[0].feelings')

SELECT @stm = CONCAT(
   N'INSERT INTO InputTable ([id],[name],',
   @columns,
   N') SELECT @id,[name],',
   @columns,
   N' FROM OPENJSON(@json) WITH ([name] varchar(100) ''$."name"'',',
   @schema,
   N')'
)

PRINT @stm
EXEC sp_executesql @stm, N'@json nvarchar(max), @id int', @json, @id
生成的动态语句:

INSERT INTO InputTable ([id],[name],[happy],[angry],[sad]) 
SELECT @id,[name],[happy],[angry],[sad] 
FROM OPENJSON(@json) WITH (
   [name] varchar(100) '$."name"',
   [happy] int '$.feelings."happy"',
   [angry] int '$.feelings."angry"',
   [sad] int '$.feelings."sad"'
)

我想你在找这样的东西。这将打开并展平JSON

declare
  @json         nvarchar(max)=N'[
      {
        "name": "abcd",
        "id": 12,
        "feelings": {
          "happy": 0,
          "angry": 1,
          "sad": 1
        }
      },
      {
        "name": "abcdf",
        "id": 14,
        "feelings": {
          "happy": 0,
          "angry": 1,
          "sad": 1
        }
      }
    ]';

INSERT INTO Table([name],[happy],[angry],[sad])
select oj.[name], f.*
from openjson(@json) with (name        nvarchar(4000),
                           id          int,
                           feelings    nvarchar(max) as json) oj
cross apply
  openjson(oj.feelings) with (happy     int,
                              angry     int,
                              sad       int) f;
结果

name    id  happy   angry   sad
abcd    12  0       1       1
abcdf   14  0       1       1

不确定我是否正确回答了您的问题,但若您需要根据表中存在的列(您希望通过名称传递)从JSON中获取数据,那个么您需要使用动态sql。下面是一个示例,说明如何使用view进行此操作:


我不知道您使用的是哪个版本的Sql Server,所以我不确定您是否可以使用系统函数,所以我使用了非常标准的技巧将列名聚合到字符串中。

表中是否总是有这两列?需要注意的是,输入JSON[{key1:name1,key2,:name2}]在key2.INSERT语句必须定义好之后无效。实际上,您不能有一个语句说将元素的值插入到相同的命名列中;SQL不是这样工作的。您需要为每个读取相应JSON的表编写SQL。否则,您需要使用动态SQL,我不建议不熟悉SQL,也不了解使用动态语句时的注意事项的人使用动态SQL。您已经咨询过了吗?你自己试过什么?另外,问题中的JSON数据和SQL代码目前都没有有效的语法。feeling对象中的关键字段是否更改?如果是,请将其更改为数组。其他列与JSON文档字段名匹配,因此它们应该转换为由OPENJSONI的WITH子句定义的列。我不知道列定义。列定义可以更改,JSON也会随之更改。是否有任何方法从JSON获取存储过程的键名?版本12.0。这是Microsoft Azure SQL数据库[{姓名:3,id:4393,感觉:{快乐:0,愤怒:1,悲伤:1},{},{}]在这个JSON中,只有feeling JSON条目会更改,insert语句应该只包含name和feeling。例如:insert into table name,happy,angryvaluesabcd,yes,yes,yes,yes。@Zhorov。如何排除一些键?完成。请帮助我了解sameIs是否可以在WITH of中包含来自OPENJSON的静态值?我有一个变量值设置@var1=20。我还需要在insert语句中将其作为一列包含在内
name    id  happy   angry   sad
abcd    12  0       1       1
abcdf   14  0       1       1
drop table if exists dbo.temp_data
create table dbo.temp_data (name nvarchar(128), happy bit, angry bit, sad bit);

----------------------------------------------------------------------------------------------------
declare @table_name nvarchar(256) = 'dbo.temp_data'
declare @data nvarchar(max) = '[
      {
        "name": "abcd",
        "id": 12,
        "feelings": {
          "happy": 0,
          "angry": 1,
          "sad": 1
        }
      },
      {
        "name": "abcdf",
        "id": 14,
        "feelings": {
          "happy": 0,
          "angry": 1,
          "sad": 1
        }
      }
    ]';

declare @stmt nvarchar(max);
declare @stmt_part1 nvarchar(max);
declare @stmt_part2 nvarchar(max);

select
    @stmt_part1 = concat(isnull(@stmt_part1 + ',', ''),c.name),
    @stmt_part2 = concat(isnull(@stmt_part2 + ',', ''),'json_value(o.value, ''$.feelings.',c.name,''')')
from sys.columns as c
where
    c.object_id = object_id(@table_name) and
    c.name <> 'name'

set @stmt = concat('
    insert into ',@table_name,' (name,',@stmt_part1,')
    select
        json_value(o.value, ''$.name'') as name,',@stmt_part2,'
    from openjson(@data) as o
');

exec sys.sp_executesql
    @stmt,
    N'@data nvarchar(max)',
    @data = @data;

----------------------------------------------------------------------------------------------------
select * from dbo.temp_data