以下模拟一下CTE出错

/*测试环境
Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (X64) Apr 2 2010 15:48:46 Copyright (c) Microsoft Corporation Developer Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1)
*/

生成表Tab数据:

--> --> (Roy)生成測試數據

if not object_id('Tab') is null
drop table Tab
Go
Create table Tab([Col1] int,[COl2] nvarchar(5))
Insert Tab
select 1,N'a,b,c' union all
select 2,N'd,e' union all
select 3,N'f'
Go

方法1:用CTE引发函数出错

if object_id('Tempdb..#Tab') is not null
drop table #Tab
select top 100 ID=Identity(int,1,1) into #Tab from syscolumns a,syscolumns b declare @Str varchar(10)='a' ;with Cte
as
(
Select
a.Col1,COl2=substring(a.Col2,b.ID,charindex(',',a.Col2+',',b.ID)-b.ID)
from
Tab a,#Tab b
where
charindex(',',','+a.Col2,b.ID)=b.ID --也可用 substring(','+a.COl2,b.ID,1)=','
)
select Col1 from Cte where @str=COl2
/*
消息 537,级别 16,状态 3,第 8 行
传递给 LEFT 或 SUBSTRING 函数的长度参数无效。
*/

方法2:直接用语句时不会报错:

if object_id('Tempdb..#Tab') is not null
drop table #Tab
select top 100 ID=Identity(int,1,1) into #Tab from syscolumns a,syscolumns b declare @Str varchar(10)='a' Select
a.Col1
from
Tab a,#Tab b
where
charindex(',',','+a.Col2,b.ID)=b.ID --也可用 substring(','+a.COl2,b.ID,1)=','
and substring(a.Col2,b.ID,charindex(',',a.Col2+',',b.ID)-b.ID) =@Str /*
Col1
1
*/

方法3:把Where条件换一下顺序也出错

if object_id('Tempdb..#Tab') is not null
drop table #Tab
select top 100 ID=Identity(int,1,1) into #Tab from syscolumns a,syscolumns b
go declare @Str varchar(10)='a' Select
a.Col1
from
Tab a,#Tab b
where
substring(a.Col2,b.ID,charindex(',',a.Col2+',',b.ID)-b.ID) =@Str and charindex(',',','+a.Col2,b.ID)=b.ID --也可用 substring(','+a.COl2,b.ID,1)=','

查原因从执行计划来找

if object_id('Tempdb..#Tab') is not null
drop table #Tab
select top 100 ID=Identity(int,1,1) into #Tab from syscolumns a,syscolumns b
go
SET SHOWPLAN_ALL ON;
go
--a.查看方法1执行计划 declare @Str varchar(10)='a' ;with Cte
as
(
Select
a.Col1,COl2=substring(a.Col2,b.ID,charindex(',',a.Col2+',',b.ID)-b.ID)
from
Tab a,#Tab b
where
charindex(',',','+a.Col2,b.ID)=b.ID --也可用 substring(','+a.COl2,b.ID,1)=','
)
select Col1 from Cte where @str=COl2
go
--b.查看方法2执行计划 declare @Str varchar(10)='a' Select
a.Col1
from
Tab a,#Tab b
where
charindex(',',','+a.Col2,b.ID)=b.ID --也可用 substring(','+a.COl2,b.ID,1)=','
and substring(a.Col2,b.ID,charindex(',',a.Col2+',',b.ID)-b.ID) =@Str go SET SHOWPLAN_ALL off
go

方法1、方法2生成的执行计划图

 
 
注意看以上第4行的运算,再查第3行执行顺序
方法1:可看到语句先执行条件(@str=COl2),再执行(charindex(',',','+a.Col2,b.ID)=b.ID)
方法2:可看到语句先执行条件(charindex(',',','+a.Col2,b.ID)=b.ID),再执行(substring(a.Col2,b.ID,charindex(',',a.Col2+',',b.ID)-b.ID) =@Str)
 
方法3同方法1一样原因,条件的顺序也会引发执行出错
 

公用表表达式(CTE)引发的改变执行顺序同WHERE条件顺序引发的bug的更多相关文章

  1. T-SQL 公用表表达式(CTE)

    公用表表达式(CTE) 在编写T-SQL代码时,往往需要临时存储某些结果集.前面我们已经广泛使用和介绍了两种临时存储结果集的方法:临时表和表变量.除此之外,还可以使用公用表表达式的方法.公用表表达式( ...

  2. 公用表表达式(CTE)

    在编写T-SQL代码时,往往需要临时存储某些结果集.前面我们已经广泛使用和介绍了两种临时存储结果集的方法:临时表和表变量.除此之外,还可以使用公用表表达式的方法.公用表表达式(Common Table ...

  3. SQL Server 公用表表达式(CTE)实现递归

    公用表表达式简介: 公用表表达式 (CTE) 可以认为是在单个 SELECT.INSERT.UPDATE.DELETE 或 CREATE VIEW 语句的执行范围内定义的临时结果集.CTE 与派生表类 ...

  4. mysql8 公用表表达式CTE的使用

    公用表表达式CTE就是命名的临时结果集,作用范围是当前语句. 说白点你可以理解成一个可以复用的子查询,当然跟子查询还是有点区别的,CTE可以引用其他CTE,但子查询不能引用其他子查询. 一.cte的语 ...

  5. SQL Server 公用表表达式(CTE)实现递归的方法

    公用表表达式简介: 公用表表达式 (CTE) 可以认为是在单个 SELECT.INSERT.UPDATE.DELETE 或 CREATE VIEW 语句的执行范围内定义的临时结果集.CTE 与派生表类 ...

  6. SQL Server温故系列(3):SQL 子查询 & 公用表表达式 CTE

    1.子查询 Subqueries 1.1.单行子查询 1.2.多行子查询 1.3.相关子查询 1.4.嵌套子查询 1.5.子查询小结及性能问题 2.公用表表达式 CTE 2.1.普通公用表表达式 2. ...

  7. 存储过程——公用表表达式(CTE)

    目录 0. 背景说明 1. 定义及语法细节 1.1 基本定义 1.2 基本语法 1.3 多个CTE同时声明 1.4 CTE嵌套使用 2. CTE递归查询 2.1 简介 2.2 准备工作 2.3 计算每 ...

  8. SQL Server中公用表表达式 CTE 递归的生成帮助数据,以及递归的典型应用

    本文出处:http://www.cnblogs.com/wy123/p/5960825.html 我们在做开发的时候,有时候会需要一些帮助数据,必须需要连续的数字,连续间隔的时间点,连续的季度日期等等 ...

  9. 公用表表达式CTE

    公用表表达式CTE表面上和派生表非常相似,看起来只是语义上的区别.但和派生表比较起来,CTE具有几个优势:第一,如果须要在一个CTE中引用另一个CTE,不需要像派生表那样嵌套,相反,只要简单地在同一个 ...

  10. 详解公用表表达式(CTE)

    简介 对于SELECT查询语句来说,通常情况下,为了使T-SQL代码更加简洁和可读,在一个查询中引用另外的结果集都是通过视图而不是子查询来进行分解的.但是,视图是作为系统对象存在数据库中,那对于结果集 ...

随机推荐

  1. Java多线程学习笔记——信号量的使用

    Java中在控制多线程访问资源的时候使用了信号量可以控制多个线程同时访问一个资源. 有两个构造方法: public Semaphore(int permits) public Semaphore(in ...

  2. 通俗易懂的ListView讲解(Adapter、图、实例)

    2016/4/5 17:22] 之前写listview其实写了很多次,但好像还是模模糊糊的感觉,直到今天准备写tab的时候被告诉说原理有像的地方,于是我就先来分析整理一下listview好了   先来 ...

  3. Travis-CI与Latex构建开源中文PDF

    博主有一本开源书籍,用 latex 排版,托管在Github上.但用 latex 不像是 Markdown,当tex文本更新时,用于最终浏览的PDF文件很难得到及时的更新, 所以博主一直想找到一套工具 ...

  4. springMVC注解@initbinder日期类型的属性自动转换

    在实际操作中经常会碰到表单中的日期 字符串和Javabean中的日期类型的属性自动转换, 而springMVC默认不支持这个格式的转换,所以必须要手动配置, 自定义数据类型的绑定才能实现这个功能. 一 ...

  5. Try out the latest C++ compiler toolset without waiting for the next update of Visual Studio

    Updated 22/Apr/2016: The NuGet package is now being uploaded daily. The payload doesn’t change every ...

  6. WPF 程序自删除(自毁)|卸载程序删除

    一般是在MainWindow_Closed 事件中调用批处理命令删除. 在借鉴别人的想法的基础上的算是改进. 自删除步骤: 1.删除文件 2.删除存放文件夹. 实现代码: private static ...

  7. 关于IIS寄宿WCF服务,客户端不能生成代理类

    我在使用VS2010写好WCF的Web服务后,部署在IIS7.0上,可以在IE9上进行访问,并且能显示XML数据,如下图 然后我在项目的客户端进行服务的添加引用,如下图 VS2010自动生成代理类,但 ...

  8. JPA(5)使用二级缓存

    jpa的缓存分为一级缓存和二级缓存,一级缓存值得是会话级别的,而二级缓存是跨会话级别的. 使用二级缓存,使用到了Ehcache,首先第一步需要在配置文件中配置使用了二级缓存 <shared-ca ...

  9. inotify--内核中文件系统的通知机制

    转载:http://www.ibm.com/developerworks/cn/linux/l-inotifynew/index.html 一. 引言 众所周知,Linux 桌面系统与 MAC 或 W ...

  10. 【iOS】Quartz2D截屏

    一.简单说明 在程序开发中,有时候需要截取屏幕上的某一块内容,比如捕鱼达人游戏.如图: 完成截屏功能的核心代码:- (void)renderInContext:(CGContextRef)ctx;调用 ...