前言

上一篇我们讲完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有问题?的更多相关文章

  1. SQL Server的非聚集索引中会存储NULL吗?

    原文:SQL Server的非聚集索引中会存储NULL吗? SQL Server的非聚集索引中会存储NULL吗? 这是个很有意思的问题,下面通过如下的代码,来说明,到底会不会存储NULL. --1.建 ...

  2. 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 ...

  3. 将Excel导入SQL Server 只能导入数字,其他数据变为NULL怎么解决?

    先新建一个TXT文件,把数据粘贴进去 再新建一个Excel文件,在菜单栏中选Data再选From Text 找到txt文件,点import 一定要选Text 点Finish,点OK. 接下来在往数据库 ...

  4. 如何查詢 SQL Server 資料庫中欄位值為 NULL 的資料(转)

    最近使用mssql的时候对于未null的字段查询不到 http://blogs.msdn.com/b/jchiou/archive/2008/05/01/sql-server-null.aspx 先建 ...

  5. [小问题笔记(十一)] SQL SERVER 将可空字段改为 NOT NULL不可为空的两个方法

    一个字段里面有一些数据是NULL是很讨厌的,写查询麻烦不说,最重要的is null  或者is not null都是不能命中索引的,会导致全表扫描啊. 所以对于一个已经存在NULL的字段,有时间的话最 ...

  6. 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 ...

  7. sql server 导出的datetime结果 CAST(0x00009E0E0095524F AS DateTime) 如何向mysql,oracle等数据库进行转换

    1. 处理 sql server 导出的 datetime 类型的字段 在进行sql server向mysql等其他数据进行迁移数据时,会发现使用sql server导出的datetime类型的结果是 ...

  8. PCB SQL SERVER 枚举分割函数(枚举值分解函数)

    在SQL SERVER字段采用枚举值作为字段后,如果直接查看字段的值是很难判断这个字段的带表什么意思, 在这里介绍如用函数的方法实现枚举值分割,只有分割后才很方便知道枚举值的意思. 一.问题说明 1. ...

  9. Distributed3:SQL Server 创建分布式数据库

    分布式数据库的优势是将IO分散在不同的Physical Disk上,每次查询都由多台Server的CPU,I/O共同负载,通过各节点并行处理数据来提高性能,劣势是消耗大量的网络带宽资源,管理难度大.在 ...

  10. SQL Server时间粒度系列----第7节日历数据表详解

    本文目录列表: 1.时间粒度有关描述 2.时间维度有关功能函数3.日历数据表 4.日历数据表数据填充 5.总结语 6.参考清单列表   时间粒度有关描述   将该系列涉及到的时间粒度以及分钟以下的粒度 ...

随机推荐

  1. libmemcached的安装及測试

    1.安装memcached ~$ wget http://memcached.googlecode.com/files/memcached-1.2.8.tar.gz. $ tar xvzf lmemc ...

  2. Tkinter界面编程(一)----函数分析

    Tkinter模块是python比较常用的GUI界面设计模块,首先对相关的函数进行分析. 一 .创建根窗口相关的函数说明 import tkinter as tk top = tk.Tk() # 创建 ...

  3. Intellij IDEA 使用小结

    快捷键 核心快捷键 IntelliJ IDEA 作为一个以快捷键为中心的 IDE,为大多数操作建议了键盘快捷键.在这个主题中,您可以找到最不可缺少的列表,使 IntelliJ IDEA 轻松实现第一步 ...

  4. java集合框架(Collections Framework)

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  5. WebApi的多版本管理

    1.多版本管理概念 什么是API的多版本问题?Android等App存在着多版本客户端共存的问题:由于早期没有内置升级机制,用户不会升级,拒绝升级等原因,造成了许多软件的旧版本App也在运行.开发新版 ...

  6. spring cloud ribbon和fegin

    一开始接触spring cloud的时候,还没有听说过微服务这个概念,对于服务直接的沟通是什么个情况,怎么组成微服务的完全懵逼,看到网上的教程都是用ribbong和fegin来调用接口,然后官网也给的 ...

  7. 对Java中堆栈的解析

    Java把内存分为两种:一种是栈内存,一种是堆内存 栈内存:在函数中定义的一些基本类型的变量和对象的引用变量,当超过变量的作用域之后,Java自动释放该变量内存 堆内存:存放new创建的对象和数组,由 ...

  8. 代码生成利器:IDEA 强大的 Live Templates(转)

    代码生成利器:IDEA 强大的 Live Templates - 文章 - 伯乐在线http://blog.jobbole.com/110607/ 前言 Java 开发过程经常需要编写有固定格式的代码 ...

  9. Bash shell命令记录和CentOS的一些技巧

    ①CentOS的实用技巧: 一.按下ctrl+alt+F2可由图形界面切换至命令行(shell窗口),按下ctrl+alt+F1可由命令行切换至图形界面(前提是安装CentOS时软件选择项选择安装了图 ...

  10. HDU4992 求所有原根

    Primitive Roots Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...