Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.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-查询短路?_Sql_Sql Server - Fatal编程技术网

SQL Server-查询短路?

SQL Server-查询短路?,sql,sql-server,Sql,Sql Server,SQL Server中的T-SQL查询是否支持短路 例如,我有两个数据库,我比较两个表之间的数据以匹配和复制一些信息。在一个表中,“ID”字段始终有前导零(例如“00000000 1234”),而在另一个表中,ID字段可能有前导零,也可能没有前导零(可能是“00000000 1234”或“1234”) 因此,我的查询与这两个匹配如下: 从table1中选择*,其中table1.ID类似于“%1234” 为了加快速度,我想在前面添加一个OR,就像上面说的: 表1.ID=表2.ID 处理两个ID都有

SQL Server中的T-SQL查询是否支持短路

例如,我有两个数据库,我比较两个表之间的数据以匹配和复制一些信息。在一个表中,“ID”字段始终有前导零(例如“00000000 1234”),而在另一个表中,ID字段可能有前导零,也可能没有前导零(可能是“00000000 1234”或“1234”)

因此,我的查询与这两个匹配如下: 从table1中选择*,其中table1.ID类似于“%1234”

为了加快速度,我想在前面添加一个OR,就像上面说的: 表1.ID=表2.ID 处理两个ID都有填充零且相等的情况


这样做是否会通过匹配“=”上的项目而不是为每一行计算类似项来加快查询速度(是否会短路并跳过类似项)?

修复数据库以保持一致性

select * from table1 where table1.ID LIKE '%1234'
将匹配“1234”、“01234”、“0000000000 1234”,但也将匹配“99991234”。使用LIKE几乎可以保证索引扫描(假设table1.ID已被索引!)。清理数据将显著提高性能

如果无法清除数据,请编写一个用户定义函数(UDF)以去除前导零,例如

select * from table1 where dbo.udfStripLeadingZeros(table1.ID) = '1234'
这可能不会提高性能(因为必须为每一行运行函数),但会消除错误匹配,并使查询的意图更加明显


编辑:如果可能的话,Tom H建议强制转换为整数是最好的。

如果ID是纯数字的(如您的示例),我建议(如果可能的话)将该字段改为数字类型。如果数据库在使用中已准备就绪,则可能很难更改类型

您希望确保至少有一个表正在为ID使用其实际数据类型,并且如果可能,它可以使用索引查找。这取决于查询的选择性和匹配率,以确定哪一个应转换为另一个。如果您知道必须扫描整个第一个表,那么无论如何都不能使用seek,您应该将该ID转换为另一个表的数据类型

为了确保可以使用索引,还要避免使用LIKE。例如,最好有:

WHERE
     T1.ID = CAST(T2.ID AS VARCHAR) OR
     T1.ID = RIGHT('0000000000' + CAST(T2.ID AS VARCHAR), 10)
比:

正如Steven A.Lowe提到的,第二个查询也可能不准确

如果要使用T1中的所有行(换句话说,是一个到T2的左外部连接),那么最好使用:

WHERE
     CAST(T1.ID AS INT) = T2.ID
如果您不确定每个方法,请执行一些查询计划,看看哪种方法最有效


绝对最好的方法是按照其他人的建议,如果可能的话,将表的数据类型更改为匹配。即使你不能在项目到期前完成,也要把它放在你的“待办事项”列表中,以便在不久的将来完成。

你可以在表格中添加一个计算列。然后,索引计算列并在联接中使用该列

例:

那么你的问题是

select * from table1 where table1.PaddedID ='000000001234'
这将使用刚刚创建的索引快速返回行。

如何

table1WithZero.ID = REPLICATE('0', 12-len(table2.ID))+table2.ID

在这种情况下,它应该能够使用表1中的索引,SQL Server DosNOT短路条件。
它不能,因为它是一个基于成本的系统:。

只是为了以防万一,正如Mladen Prajdic的anwer中的链接页面所解释的那样,case子句是经过短路评估的。

那么table1.ID(如“%1234”)会与“31234”匹配吗?好的,搜索过滤器会更像“%00001234”-仍然有一些前导零。很好。没有ORs,没有在线UDF,可索引等。请记住,这将导致插入和更新受到(希望较小)影响。好主意,只要这不是问题。如果您无法修复数据以使其一致,这是下一个最好的解决方案like不保证像“%1234”这样的表扫描是表扫描。就像“1234%”不是表扫描,假设列被索引,它将使用索引来查找1234…@Josh:我说的是“索引扫描”,而不是“表扫描”。@Steven是的,我不知道为什么,但当我第一次读它时,我可以发誓它说的是表…我想我老了;-)但不管怎样,我认为用通配符作为前缀会导致表扫描maybee,这就是为什么我把它们弄糊涂了。是的,我不能更改源表。
select * from table1 where table1.PaddedID ='000000001234'
table1WithZero.ID = REPLICATE('0', 12-len(table2.ID))+table2.ID