SQL Server中的JSON支持是相当新的。有关更多信息,请参见here。
我们想用它来存储我们的可翻译字段。这意味着在数据库中,我们将不再拥有带有翻译的单独表,而是将它们存储在列本身中。
我们的列值如下所示:
"Name" : {
"en-US" : "Conditioning",
"nl-NL" : "Behandeling",
"fr-FR" : "Traitement",
"de-DE" : "Konditionierung"
}
由于我们仍然有一个包含所有不同区域性的表,所以我仍然想在Name.Key和Culture表之间应用外键关系。
我找不到有关如何将外键约束应用于JSON中的数据的任何信息。有人知道怎么做吗?
我已经尝试了下面的约束进行测试,但这不起作用。 JSON_VALUE
似乎不适用于JSON密钥。而JSON_QUERY
返回的不仅仅是键。
ADD CONSTRAINT
[FK_ItemCulture]
CHECK (JSON_VALUE([Name], '$.Name') IN ('en-US', 'nl-NL', 'fr-FR', 'de-DE'))
答案 0 :(得分:1)
您可以定义将检查单个json的标量函数:
CREATE FUNCTION [dbo].[svf_CheckJsonNames](@json nvarchar(max))
RETURNS bit AS
BEGIN
declare @ok bit
declare @validNames table([name] nvarchar(50))
insert into @validNames values ('en-US'),('nl-NL'),('fr-FR'),('de-DE')
if exists (
select x.[key] , vn.name from OPENJSON (@json)
with (
[Name] nvarchar(max) as json
) t
cross apply
(
select [key] from openjson(t.[Name])
) x
left join @validNames vn
on x.[key] COLLATE DATABASE_DEFAULT = vn.[name] COLLATE DATABASE_DEFAULT
where vn.[name] is null
)
set @ok = 0
else set @ok = 1
RETURN @ok
END
如果所有名称均有效,则该函数返回1,如果一个或多个名称无效,则返回0。
现在您可以在约束中使用此功能:
create table tmp(myId int, [Name] nvarchar(max))
alter table tmp ADD CONSTRAINT [FK_ItemCulture]
CHECK ([dbo].[svf_CheckJsonNames]([Name]) = 1)
如果运行以下插入语句:
insert into tmp values(1, '{"Name" : { "en-US" : "Conditioning", "nl-NL" : "Behandeling", "fr-FR" : "Traitement", "de-DE" : "Konditionierung" }}')
insert into tmp values(2, '{"Name" : { "en-EN" : "Conditioning", "nl-NL" : "Behandeling", "fr-FR" : "Traitement", "de-DE" : "Konditionierung" }}')
第一个将成功,因为所有名称均正确:
,但是第二个将失败,因为名字(“ en-EN”)无效。这是错误: