SQL Server-聚焦WHERE Column=@Param OR @Param IS NULL有问题?
前言
上一篇我们讲完SQL动态查询,本节我们继续来讲解SQL动态查询中存在的问题。
SQL动态查询条件筛选过滤
当我们创建存储过程调用存储过程时,若筛选条件有值则过滤,没有值则返回所行记录,类似如下查询:
WHERE (SomeColumn=@col OR @col IS NULL)
这样查询会存在什么问题呢?性能会不会有问题呢,这个是我们本节需要深入探讨的问题。
接下来我们创建如下测试表并插入测试数据,如下:
CREATE TABLE Test
(
SomeCol1 INT NOT NULL ,
Somecol2 INT NOT NULL
)
INSERT Test
SELECT number ,
low
FROM master..spt_values
WHERE TYPE = 'p'
CREATE INDEX ix_col2 ON Test(Somecol2)
GO
对于动态SQL条件筛选过滤我们利用WHERE 1 = 1来拼接。接下来我们使用一般SQL语句和动态查询并比较其IO,如下:
SET STATISTICS IO ON
GO
DECLARE @col INT
SELECT @col = 1
SELECT SomeCol2
FROM Test
WHERE 1 =1
AND (SomeCol2=@col OR @col IS NULL)
GO
DECLARE @col INT
SELECT @col = 1
DECLARE @SQL NVARCHAR(4000)
SET @SQL = 'SELECT SomeCol2
FROM Test
WHERE 1 =1'
IF @col IS NOT NULL
SET @SQL = @SQL + ' AND SomeCol2=@InnerParamcol '
EXEC sp_executesql @SQL,N'@InnerParamcol INT',@col
SET STATISTICS IO OFF
GO


我们能够看到动态SQL查询逻辑读取只读取2次,而另外一般SQL语句查询逻辑读取7次,同时我们看到SQL动态查询计划执行的是索引查找,而一般SQL语句则是索引扫描。
看来执行一般SQL语句不会走索引查找,将导致性能问题,在开头我们就讲过筛选条件有值则过滤,无值则查询所有数据,那么我们完全可以借助ISNULL来查询,下面我们用ISNULL来改变一般语句筛选条件,看看是否会走索引查找呢?
SET STATISTICS IO ON
GO
DECLARE @col INT
SELECT @col = 1
SELECT SomeCol2
FROM dbo.Test
WHERE 1 = 1
AND SomeCol2 = ISNULL(@col,SomeCol2)


我们看到结果依然是走索引扫描,没有任何改变。是不是就没有解决之道了呢?我们来改变一般SQL语句查询方式,如下:
DECLARE @col INT
SELECT @col = 1
IF @Col IS NULL
SELECT SomeCol2
FROM Test
WHERE 1 = 1
ELSE
SELECT SomeCol2
FROM dbo.Test
WHERE 1 = 1
AND SomeCol2 = @col
GO
如上只能是勉勉强强解决了问题,因为只是针对一个参数,如果有多个参数要进行IF...ELSE..,那可就傻逼了。从本质上解决这个问题我们需要利用可选项重新编译。如下:
SET STATISTICS IO ON
GO
DECLARE @col INT
SELECT @col = 1
SELECT SomeCol2
FROM dbo.Test
WHERE 1 =1
AND (SomeCol2 = @col OR @col IS NULL)
OPTION(RECOMPILE)
GO
DECLARE @col INT
SELECT @col = 1
DECLARE @SQL NVARCHAR(4000)
SET @SQL = 'SELECT SomeCol2
FROM dbo.Test
WHERE 1 =1'
IF @col IS NOT NULL
SET @SQL = @SQL + ' AND SomeCol2 = @InnerParamcol '
EXEC sp_executesql @SQL,N'@InnerParamcol INT',@col
SET STATISTICS IO OFF
GO


总结
当利用条件筛选过滤数据时,如果条件有值则过滤,否则返回所有行记录。如果执行一般SQL语句和动态SQL,那么动态SQL会走索引查找,而一般SQL语句将导致索引扫描,此时需要加上OPTION(RECOMPILE)才走索引查找。
SQL Server-聚焦WHERE Column=@Param OR @Param IS NULL有问题?的更多相关文章
- SQL Server的非聚集索引中会存储NULL吗?
原文:SQL Server的非聚集索引中会存储NULL吗? SQL Server的非聚集索引中会存储NULL吗? 这是个很有意思的问题,下面通过如下的代码,来说明,到底会不会存储NULL. --1.建 ...
- Invalid column name on sql server update after column create
问题:新建一个测试表xx as code into xx select * from xx 给这个表添加一个列val, val列不允许为空,将表中已有的数据val值更新为1 alter table x ...
- 将Excel导入SQL Server 只能导入数字,其他数据变为NULL怎么解决?
先新建一个TXT文件,把数据粘贴进去 再新建一个Excel文件,在菜单栏中选Data再选From Text 找到txt文件,点import 一定要选Text 点Finish,点OK. 接下来在往数据库 ...
- 如何查詢 SQL Server 資料庫中欄位值為 NULL 的資料(转)
最近使用mssql的时候对于未null的字段查询不到 http://blogs.msdn.com/b/jchiou/archive/2008/05/01/sql-server-null.aspx 先建 ...
- [小问题笔记(十一)] SQL SERVER 将可空字段改为 NOT NULL不可为空的两个方法
一个字段里面有一些数据是NULL是很讨厌的,写查询麻烦不说,最重要的is null 或者is not null都是不能命中索引的,会导致全表扫描啊. 所以对于一个已经存在NULL的字段,有时间的话最 ...
- Part 4 Identity Column in SQL Server
Identity Column in SQL Server If a column is marked as an identity column, then the values for this ...
- sql server 导出的datetime结果 CAST(0x00009E0E0095524F AS DateTime) 如何向mysql,oracle等数据库进行转换
1. 处理 sql server 导出的 datetime 类型的字段 在进行sql server向mysql等其他数据进行迁移数据时,会发现使用sql server导出的datetime类型的结果是 ...
- PCB SQL SERVER 枚举分割函数(枚举值分解函数)
在SQL SERVER字段采用枚举值作为字段后,如果直接查看字段的值是很难判断这个字段的带表什么意思, 在这里介绍如用函数的方法实现枚举值分割,只有分割后才很方便知道枚举值的意思. 一.问题说明 1. ...
- Distributed3:SQL Server 创建分布式数据库
分布式数据库的优势是将IO分散在不同的Physical Disk上,每次查询都由多台Server的CPU,I/O共同负载,通过各节点并行处理数据来提高性能,劣势是消耗大量的网络带宽资源,管理难度大.在 ...
- SQL Server时间粒度系列----第7节日历数据表详解
本文目录列表: 1.时间粒度有关描述 2.时间维度有关功能函数3.日历数据表 4.日历数据表数据填充 5.总结语 6.参考清单列表 时间粒度有关描述 将该系列涉及到的时间粒度以及分钟以下的粒度 ...
随机推荐
- 【quickhybrid】JSBridge的实现
前言 本文介绍quick hybrid框架的核心JSBridge的实现 由于在最新版本中,已经没有考虑iOS7等低版本,因此在选用方案时没有采用url scheme方式,而是直接基于WKWebView ...
- this的指向问题
在 ES5 中,其实 this 的指向,始终坚持一个原理:this 永远指向最后调用它的那个对象. 例 1: var name = "windowsName"; function ...
- urllib2的基本使用
urlopen 1 import urllib2 2 3 # 向指定的url发送请求,并返回服务器响应的类文件对象 4 response = urllib2.urlopen("http:// ...
- SpringBoot里mybatis查询结果为null的列不返回问题的解决方案
对于mybatis里查询结果为null的列不返回的问题解决方案 在配置文件application.properties里增加 Mybatis.configuration.call-setters-on ...
- Java IO学习要点导图
Java IO的一些基础知识: 导图源文件保存地址:https://github.com/wanghaoxi3000/xmind
- 函数PYXX_READ_PAYROLL_RESULT的dump问题
发现有两个HR的后台定时任务出现dump,日志表示,是PYXX_READ_PAYROLL_RESULT产生了类型冲突的异常CX_SY_DYN_CALL_ILLEGAL_TYPE. 日志标题部分: 类别 ...
- php面向对象4
成员属性 基本介绍 成员属性是类的一个组成部分,一般是基本数据类型,也可以是复合类型,资源类型.比如 public $age;就是成员属性 说明 ①成员属性可以是php的任何数据类型(int, flo ...
- [置顶]
xamarin android 布局尺寸了解
为了使UI界面在不同大小的移动端显示器上能够正常显示,大家可能都知道使用sp作为字体大小的单位,dp作为其他元素长度的单位. 前几天看了一篇文章关于 App设计规范的,文章用心写的非常好,这里是链接 ...
- 历年NOIP选题题解汇总
联赛前上vijos板刷往年联赛题,使用在线编辑编写代码,祝我rp++. 废话不多说,挑比较有意思的记一下. 题目是按照年份排序的,最早只到了03年. 有些题目因为 我还没写/很早之前写的忘了 所以就没 ...
- 防盗链与token运用
为什么要防盗链? 例如手机/PC应用,如果有人知道你的api地址,和应用格式,那么他人就可以利用这个接口进行盗链:盗取/盗用里面的数据. 防盗链特性: 1.因为是非开放性的,所以所有的接口都是封闭的, ...