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)才走索引查找。








本文转自Jeffcky博客园博客,原文链接:http://www.cnblogs.com/CreateMyself/p/8280460.html,如需转载请自行联系原作者

目录
相关文章
使用^、&(异或、并且)位运算 实现算数加法(+)
用位运算即是计算机的运算规则,而计算机只懂得二进制,所以位运算使用的进制是二进制。
491 0
使用^、&(异或、并且)位运算 实现算数加法(+)
|
5天前
|
人工智能 弹性计算 运维
|
2天前
|
缓存 人工智能 安全
GPT-5.6 Terra与GPT-5.5性能实测:成本减半后的跑分对比与快速迁移指南
GPT-5.6 Terra 的定价为每百万 token 输入 2.50/输出 15。GPT-5.5 则是 5/ 30。Terra 的每一项费率,包括 $0.25/M 的缓存读取,都恰好是 GPT-5.5 的一半,因此在任何工作负载组合下,Terra 都固定 便宜 2.0x。以每天 10 万次请求、3K token 提示词计算,大约是 Terra 每天 2,000,GPT−5.5每天 4,000,即每月约 60,000对 120,000。问题在于:OpenAI 没有发布任何针对 Terra 的编码基准。那个著名的 91.9% Terminal-Bench 数字是 Sol 在 Ul
|
2天前
|
SQL 人工智能 自然语言处理
大模型内容安全实时防护:恶意Prompt注入拦截、越权阻断与熔断机制方案.166
本文系统阐述大模型输入安全防护体系,涵盖提示词注入、恶意Prompt拦截、越权阻断与输入熔断四大核心风险及应对方案。提出四层防护架构(预处理、检测、鉴权、熔断),结合规则引擎、语义识别与RBAC权限控制,实现全链路实时防护,保障业务合规、数据安全与服务稳定。
213 1
|
26天前
|
Linux 程序员 数据格式
【2026最新】Notepad++下载、安装和使用一篇搞定(附中文版安装包)
Notepad++ 是一款免费开源、轻量高效的 Windows 文本编辑器,支持 C/Python/HTML 等 80+ 语言语法高亮、代码折叠、正则替换、编码转换及插件扩展,专为程序员与文本处理用户打造,完美替代系统记事本。(239字)
|
10天前
|
人工智能 编解码 物联网
2026 最新Stable Diffusion 本地部署教程 下载安装使用详细图解(含官网安装包)
Stable Diffusion(SD)是2022年发布的开源文生图模型,由Stability AI等联合开发。支持文生图、图生图、局部重绘等,依托VAE降低算力需求,可在消费级显卡运行。本文提供秋葉aaaki制作的Windows整合包(含图形界面与插件),开箱即用,零配置启动。
|
11天前
|
人工智能 缓存 安全
Claude Code 封号真实原因曝光,这次彻底不装了,直接针对国内开发者的账号下手?
Claude Code 封号潮背后:逆向扒出客户端隐写区域标记,Anthropic 政策收紧叠加 DeepSeek 7 月涨价,国产替代更紧迫。
|
20天前
|
存储 人工智能 监控
QoderWork完全指南:从入门到精通,把“AI实习生”变成你的全能工作搭档
阿里云2026年推出的桌面端AI工作助手QoderWork,不止聊天,更可动手干活:本地运行、安全可控,支持文件整理、数据分析、PPT生成、网页开发等;内置专家套件、多Agent协作与自定义Skills,让AI真正成为你身边的“AI实习生”。
|
16天前
|
人工智能 JSON 自然语言处理
让教学更智慧:用阿里云百炼工作流,自动生成中小学教材内容#小有可为#有温度的AI
通过可视化工作流编排,将大模型推理能力转化为标准化的教学内容生成引擎。教师只需输入教材标题和适用学段,即可自动获得结构完整、符合课程标准的章节内容,大幅降低备课门槛,助力教育资源均衡化。
508 127