将 JSON KEY 映射为 INSERT QUERY 中的列名
Map JSON KEY as column names in INSERT QUERY
我正在编写一个存储过程以将这些值插入 table。始终我的 table 列名将是键,列数据将是 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.
我需要在插入中包含来自 JSON 的数据以及静态声明的数据 query.Does OPENJSON 允许在 WITH() 中包含静态数据。
请帮我解决这个问题。
我认为动态语句应该是您的首选:
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 @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
不确定我是否正确回答了你的问题,但如果你需要根据 table 中存在的列从 JSON 获取数据,你想按名称传递这些列,那么你需要有动态 sql。下面是一个如何使用 sys.columns
视图来完成此操作的示例:
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
我不知道你使用的是哪个版本的 Sql 服务器,所以我不确定你是否可以使用 string_agg
系统函数,所以我使用了非常标准的技巧来聚合列名转换为字符串。
我正在编写一个存储过程以将这些值插入 table。始终我的 table 列名将是键,列数据将是 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.
我需要在插入中包含来自 JSON 的数据以及静态声明的数据 query.Does OPENJSON 允许在 WITH() 中包含静态数据。
请帮我解决这个问题。
我认为动态语句应该是您的首选:
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 @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
不确定我是否正确回答了你的问题,但如果你需要根据 table 中存在的列从 JSON 获取数据,你想按名称传递这些列,那么你需要有动态 sql。下面是一个如何使用 sys.columns
视图来完成此操作的示例:
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
我不知道你使用的是哪个版本的 Sql 服务器,所以我不确定你是否可以使用 string_agg
系统函数,所以我使用了非常标准的技巧来聚合列名转换为字符串。