使用OPENJSON函数时如何处理T-SQL缺失列?

时间:2017-03-20 23:30:37

标签: sql-server json tsql

考虑以下三种T-SQL场景:

-- scenario 1: SSN is specified with a value
DECLARE @Json_Array nvarchar(max) = '[{"Employee_ID":123,"Employee_Name":"John Doe","SSN":123456789}]';
SELECT *
FROM OPENJSON(@Json_Array) 
WITH (Employee_ID int, Employee_Name nvarchar(60), SSN int)

-- scenario 2: SSN is specified with null for the value
SET @Json_Array = '[{"Employee_ID":123,"Employee_Name":"John Doe","SSN":null}]';
SELECT *
FROM OPENJSON(@Json_Array) 
WITH (Employee_ID int, Employee_Name nvarchar(60), SSN int)

-- scenario 3: SSN is not specified
SET @Json_Array = '[{"Employee_ID":123,"Employee_Name":"John Doe"}]';
SELECT *
FROM OPENJSON(@Json_Array) 
WITH (Employee_ID int, Employee_Name nvarchar(60), SSN int)

方案2和3都为SSN返回NULL值。

如何判断SSN是否未包含在@Json_Array中?我需要这样做的原因是,如果SSN未包含在JSON中,则避免将员工的SSN更新为NULL。

1 个答案:

答案 0 :(得分:0)

答案是从OPENJSON(@json_item)中选择[value],其中[key] ='Column_Name'。以下是一个完整的例子。

-- create table of original data that will be modified
DECLARE @Json_Array_Original nvarchar(max) = '[
{"Employee_ID":123,"Employee_Name":"John Doe","SSN":123456789},
{"Employee_ID":124,"Employee_Name":"John Smith","SSN":343434343},
{"Employee_ID":125,"Employee_Name":"Jim Doe","SSN":515151515}
]';
declare @Original_Data table (Employee_ID int, Employee_Name nvarchar(20), SSN int);
insert into @Original_Data
select * from openjson(@Json_Array_Original)
with (Employee_ID int, Employee_Name nvarchar(20), SSN int)
select * from @Original_Data

-- create table of data changes that will be applied
DECLARE @Json_Array_Changes nvarchar(max) = '[
{"Employee_ID":123,"Employee_Name":"Jon Doe","SSN":null},
{"Employee_ID":124,"Employee_Name":"John Smythe"},
{"Employee_ID":125,"SSN":555151515}
]';
declare @Data_Changes table (Employee_ID int, Employee_Name nvarchar(20), SSN int);
insert into @Data_Changes
select * from openjson(@Json_Array_Changes)
with (Employee_ID int, Employee_Name nvarchar(20), SSN int)
select * from @Data_Changes

-- create table containing json records of data changes
declare @Json_Items table ([key] int, [value] nvarchar(max), type int);
insert into @Json_Items
select * from openjson(@Json_Array_Changes)

-- create table that specifies with a 1 the columns (properties) of each json record that have new values provided
declare @Json_Keys table (Employee_ID int, Employee_Name bit, SSN bit);
insert into @Json_Keys
select 
  json_value([value], '$.Employee_ID'),
  (select 1 from openjson([value]) where [key]='Employee_Name'),
  (select 1 from openjson([value]) where [key]='SSN')
from @Json_Items
select * from @Json_Keys

-- apply new values only for columns (properties) that have values specified
update od
set
  od.Employee_Name = iif(jk.Employee_Name = 1, dc.Employee_Name, od.Employee_Name),
  od.SSN = iif(jk.SSN = 1, dc.SSN, od.SSN)
from @Original_Data od
inner join @Data_Changes dc on od.Employee_ID = dc.Employee_ID
inner join @Json_Keys jk on dc.Employee_ID = jk.Employee_ID
select * from @Original_Data