Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 在对象数组中创建特定JSON值的索引_Sql Server_Tsql - Fatal编程技术网

Sql server 在对象数组中创建特定JSON值的索引

Sql server 在对象数组中创建特定JSON值的索引,sql-server,tsql,Sql Server,Tsql,假设表中有一个varchar列,其结构如下: { "Response":{ "DataArray":[ { "Type":"Address", "Value":"123 Fake St" }, { "Type":"Name", "Value":"John Doe" } ] } } 我想在“Da

假设表中有一个varchar列,其结构如下:

{
   "Response":{
      "DataArray":[
         {
            "Type":"Address",
            "Value":"123 Fake St"
         },
         {
            "Type":"Name",
            "Value":"John Doe"
         }
      ]
   }
}
我想在“DataArray”数组元素的“Value”字段上创建一个持久化的计算列,该字段包含一个等于“Name”的类型字段。(我希望我正确地解释了这一点。基本上,我想在该结构上索引人名)

问题是,与其他json对象不同,我不能以简单的方式使用
json\u VALUE
函数来提取所述值。我不知道这是否可以做到,我已经涉猎了
JSON\u QUERY
,但到目前为止我不知道该怎么做


任何想法和帮助都将不胜感激。谢谢

您可以使用带有PATINDEX和索引的计算列:

CREATE TABLE foo (a varchar(4000), a_ax AS (IIF(PATINDEX('%bar%', a) > 0, SUBSTRING(a, PATINDEX('%bar%', a), 42), '')))

CREATE INDEX foo_x ON foo(a_ax)

您可以使用以下功能实现:

CREATE FUNCTION dbo.my_func(@s NVARCHAR(MAX))
RETURNS NVARCHAR(100)
WITH SCHEMABINDING
AS
BEGIN
   DECLARE @r NVARCHAR(100);

   SELECT @r = Value 
   FROM OPENJSON(@s,'$.Response.DataArray')  
   WITH ([Type] NVARCHAR(100) '$.Type', [Value] NVARCHAR(100) '$.Value')
   WHERE [Type] = 'Name';

   RETURN @r;
END;
定义表:

CREATE TABLE tab(
  val NVARCHAR(MAX) CHECK (ISJSON(val) = 1),
  col1 AS dbo.my_func(val) PERSISTED        -- calculated column
);
样本数据:

INSERT INTO tab(val) VALUES (N'{
   "Response":{
      "DataArray":[
         {
            "Type":"Address",
            "Value":"123 Fake St"
         },
         {
            "Type":"Name",
            "Value":"John Doe"
         }
      ]
   }
}');

CREATE INDEX idx ON tab(col1);   -- creating index on calculated column

SELECT * FROM tab;

您可以使用@Lukasz Szozda发布的标量函数-这是一个很好的解决方案。 然而,计算列中的T-SQL标量UDF的问题是,它们破坏了表所涉及的任何查询的性能。数据修改(插入、更新、删除)不仅会减慢速度,而且涉及该表的查询的任何执行计划都无法利用并行执行计划即使查询中未引用计算列,也会出现这种情况。甚至索引构建也失去了利用并行执行计划的能力。请注意本文:作者Erik Darling

这不是很好,但是,如果性能比这更重要,那么这将在不存在标量UDF缺点的情况下获得所需的结果

CREATE TABLE dbo.jsonStrings
(
  jsonString VARCHAR(8000) NOT NULL, 
  nameTxt AS (
    SUBSTRING(
      SUBSTRING(jsonString,
        CHARINDEX('"Value":"',jsonString,
          CHARINDEX('"Type":"Name",',jsonString,
            CHARINDEX('"DataArray":[',jsonString)+12))+9,8000),1,
      CHARINDEX('"', 
        SUBSTRING(jsonString,
          CHARINDEX('"Value":"',jsonString,
            CHARINDEX('"Type":"Name",',jsonString,
              CHARINDEX('"DataArray":[',jsonString)+12))+9,8000))-1)) PERSISTED
);

INSERT dbo.jsonStrings(jsonString)
VALUES
('{
   "Response":{
      "DataArray":[
         {
            "Type":"Address",
            "Value":"123 Fake St"
         },
         {
            "Type":"Name",
            "Value":"John Doe"
         }
      ]
   }
}');
请注意,这对于您发布的结构非常有效。它可能需要根据JSON的功能和外观进行调整


第二个(更好但更复杂的)解决方案是从Lukasz Szozda的标量UDF中获取json路径逻辑,并将其放入CLR。正确编写T-SQL标量UDF时,不会出现T-SQL标量UDF所遇到的上述问题

是否有任何方法可以预先处理应用程序代码中的JSON以提取值?是的。不幸的是,应用层基本上不使用json,而是插入它,如果可能的话,人们希望保持这种方式。我不知道这是否可能,所以我必须先做研究。这不是我的要求,也不是重新构造json(因为类型总是相同的,我们应该将它们作为字段,而不是使用这种奇怪的数组数据结构)。你也可以使用
CHARINDEX
来破解一些东西。@Dai没有必要使用CHARINDEX进行字符串处理。SQLServer完全能够处理JSON。是的,就是这个。我对每个人的答案都投了赞成票,但我用的是这个。谢谢。我从这篇文章中学到了很多。这是一篇非常完整的文章。非常感谢。我会记住并行执行的缺点。我对此无能为力,但很高兴知道这一点。如果这在将来再次困扰我,我将尝试你建议的优化。如果可以的话,我会投你10票。