Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.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
Json 视图上的过滤器应用于视图中排除的过滤器_Json_Sql Server_Tsql_View - Fatal编程技术网

Json 视图上的过滤器应用于视图中排除的过滤器

Json 视图上的过滤器应用于视图中排除的过滤器,json,sql-server,tsql,view,Json,Sql Server,Tsql,View,我有一个可以在列中包含JSON数据的表。我使用ISJSON函数向表中添加了一个计算列,以标记不包含有效JSON数据的任何行 CREATE TABLE tbl1 (Id INT IDENTITY(1,1) NOT NULL, Content NVARCHAR(MAX), IsJsonRecord AS ISJSON(Content)) GO INSERT INTO tbl1 (Content) VALUES ('a'), ('{"name":"asd"}')

我有一个可以在列中包含JSON数据的表。我使用ISJSON函数向表中添加了一个计算列,以标记不包含有效JSON数据的任何行

CREATE TABLE tbl1 (Id INT IDENTITY(1,1) NOT NULL, Content NVARCHAR(MAX), IsJsonRecord AS ISJSON(Content))
GO
INSERT INTO tbl1 (Content) VALUES ('a'), ('{"name":"asd"}')
GO
现在我有了一个视图,可以将JSON数据解析为更可读的格式,例如

CREATE VIEW vw1
AS
SELECT Id,
    JSON_VALUE(Content, '$."name"') AS Name
FROM tbl1
WHERE IsJsonRecord > 0
当我从视图中选择时,WHERE子句按预期工作

SELECT *
FROM vw1
当我用一个额外的where子句查询视图时,由于格式错误的JSON数据,我得到一个错误,如下所示

SELECT *
FROM vw1
WHERE [Name] LIKE '%a%'
查询WHERE子句似乎应用于不符合视图中已指定WHERE子句的行

SELECT *
FROM vw1
这是预期的行为吗

我知道视图已经优化了,但我希望查询优化器在应用需要函数对数据进行操作的过滤器之前,先对不同的字段应用过滤器。我认为,在某些情况下,逻辑可能具有性能优势

我不太确定如何适应视图上的WHERE子句。我的实际情况比示例要复杂得多,我不确定是否可以在JSON_VALUE语句上使用case语句测试视图中的每一列


有什么建议吗?

就目前的情况来看,没有,您无法告诉编译器按照什么顺序进行过滤,尽管您可以使用一些技巧,通常会强制编译器这样做

问题是您的查询是这样有效地编译的:

挑选* 从…起 选择Id, JSON_VALUEContent,“$.name”作为名称 来自tbl1 其中IsJsonRecord>0 vw1 其中[Name]类似于“%a%” 然后对其进行简单优化,以:

选择Id, JSON_VALUEContent,“$.name”作为名称 来自tbl1 其中IsJsonRecord>0和[Name]类似于“%a%” 此时,编译器将决定首先评估哪个部分。不管出于什么原因,它选择先做类似的事情,这可能是由于一个好的索引

您有许多解决方案:

用例,这是有保证的,除非在某些情况下按顺序进行评估 选择Id, JSON_VALUEContent,“$.name”作为名称 来自tbl1 其中,当IsJsonRecord>0时为CASE,当[Name]如“%a%”时为CASE,则1 END=1 在持久化列上添加索引,该列可以作为前导键,也可以使用筛选后的索引IsJsonRecord>0。 这并不能保证总是有效,但通常是有效的。确保包含所有必要的列

上面的一个变体是向视图添加聚集索引。这样做有很多限制,但它可以很好地工作。确保在查询中添加WITH NOEXPAND提示

一个更可靠的选项是在视图中添加顶部。 这迫使编译器确保首先在逻辑上计算IsJsonRecord>0,这几乎总是意味着它将首先在物理上执行

挑选* 从…起 选择顶部9223372036854775807* 来自vw1 vw1 其中[Name]类似于“%a%”
看起来很奇怪。如果替换json_值,错误就会消失。。。使用交叉应用openjson。。。具有但是我一开始并没有料到会有错误。感谢大家的热烈响应,我将不得不进行实验。我发现的另一种方法是下面。问题是我的观点被用于其他事情,所以我需要确保这些都不会破坏这些案例。将视图[dbo].[vw1]更改为SELECT Id,当IsJsonRecord=0时为大小写,然后将NULL ELSE JSON_VALUEContent,'$.name'作为名称从tbl1结束,其中IsJsonRecord>0