SQL SERVER中LIKE在Char和nChar输出结果不一致解惑
一同事在写脚本时,遇到一个关于LIKE里面使用不同的变量类型导致查询结果不一致的问题,因为这个问题被不同的人问过好几次,索性总结一下,免得每次都要解释一遍,直接丢一篇博客岂不是更方便!其实看似有点让人不解的现象背后实质跟数据类型的实现有关。
下面我们构造这样一个类似的简单案例。如下所,
- CREATE TABLE TEST
- (ID INT IDENTITY(1,1),
- NAME VARCHAR(32)
- )
- INSERT INTO dbo.test
- SELECT 'abc32'
- INSERT INTO dbo.test
- SELECT 'abd32'
- INSERT INTO dbo.test
- SELECT 'abe32'
- DECLARE @name VARCHAR(32);
- SET @name='ab%';
- SELECT * FROM TEST WHERE NAME LIKE @name;
- DECLARE @name1 CHAR(32);
- SET @name1='ab%';
- SELECT * FROM dbo.TEST WHERE NAME LIKE @name1;
如上截图所示,当变量使用VARCHAR类型与CHAR类型时,两种的输出结果完全不一样。如果对SQL SERVER数据类型了解不透彻的话,估计真的对这个问题感到相当困惑。但是对SQL Server数据类型了解比较深入的人来说,这真的是一个简单到不能再简单的问题。
如下所示,我们在SQL语句中加入两句SQL,用DATALENGTH返回任何表达式的字节数,你会发现VARCHAR类型的变量返回的字节数为3,但是CHAR类型的变量的字节数为32,其实原因就在于CHAR类型是定长的,也就是当你输入的字符小于你指定的数目时,例如char(32),你输入的字符小于32时,它会在后面补空值。当你输入的字符大于指定的数时,它会截取超出的字符. 所以下面两种LIKE的逻辑意义不一样。LIKE 'ab%' 与 LIKE 'abc% '的逻辑完全不同。
其实你想从侧面印证一下也很简单,如下脚本对比所示,仔细理解一下,也许你就想明白了!
- DECLARE @name CHAR(32);
- SET @name='ab%';
- SELECT * FROM TEST WHERE NAME LIKE @name;
- DECLARE @name1 CHAR(3);
- SET @name1='ab%';
- SELECT * FROM dbo.TEST WHERE NAME LIKE @name1;
如果使用 LIKE 执行字符串比较,则模式字符串中的所有字符都有意义。 这包括前导或尾随空格。 如果查询中的比较要返回包含 "abc "(abc 后有一个空格)的所有行,则不会返回包含 "abc"(abc 后没有空格)的列所在行。 但是可以忽略模式所要匹配的表达式中的尾随空格。 如果查询中的比较要返回包含 "abc"(abc 后没有空格)的所有行,则返回以 "abc" 开始并且具有零个或多个尾随空格的所有行。
由于数据存储方式的原因,使用包含 char 和 varchar 数据的模式的字符串比较可能无法通过 LIKE 比较。 您应当了解每种数据类型的存储方式以及导致 LIKE 比较失败的原因。 以下示例将本地 char 变量传递给存储过程,然后使用模式匹配来查找其姓氏以一组指定的字符开始的所有雇员。
- -- Uses AdventureWorks
- CREATE PROCEDURE FindEmployee @EmpLName char(20)
- AS
- SELECT @EmpLName = RTRIM(@EmpLName) + '%';
- SELECT p.FirstName, p.LastName, a.City
- FROM Person.Person p JOIN Person.Address a ON p.BusinessEntityID = a.AddressID
- WHERE p.LastName LIKE @EmpLName;
- GO
- EXEC FindEmployee @EmpLName = 'Barb';
- GO
当名字中包含的字符数小于 20 时,char 变量 (@EmpLName
) 将包含尾随空格,这导致 FindEmployee
过程中没有行返回。 由于 LastName
列为 varchar 类型,因此没有尾随空格。 因为尾随空格是有意义的,所以此过程失败。
但以下示例会成功,因为没有向 varchar 变量中添加尾随空格。
- -- Uses AdventureWorks
- CREATE PROCEDURE FindEmployee @EmpLName varchar(20)
- AS
- SELECT @EmpLName = RTRIM(@EmpLName) + '%';
- SELECT p.FirstName, p.LastName, a.City
- FROM Person.Person p JOIN Person.Address a ON p.BusinessEntityID = a.AddressID
- WHERE p.LastName LIKE @EmpLName;
- GO
- EXEC FindEmployee @EmpLName = 'Barb';
- FirstName LastName City
- ---------- -------------------- ---------------
- Angela Barbariol Snohomish
- David Barber Snohomish
- (2 row(s) affected)
https://www.cnblogs.com/kerrycode/p/9069910.html
https://docs.microsoft.com/zh-cn/sql/t-sql/language-elements/like-transact-sql?view=sql-server-2017
SQL SERVER中LIKE在Char和nChar输出结果不一致解惑的更多相关文章
- SQL SERVER中LIKE使用变量类型不同输出结果不一致解惑
一同事在写脚本时,遇到一个关于LIKE里面使用不同的变量类型导致查询结果不一致的问题,因为这个问题被不同的人问过好几次,索性总结一下,免得每次都要解释一遍,直接丢一篇博客岂不是更方便!其实看似有点让人 ...
- Sql Server中日期时间格式化为字符串输出
在SQL Server数据库中,SQL Server日期时间格式转换字符串可以改变SQL Server日期和时间的格式,是每个SQL数据库用户都应该掌握的.本文我们主要就介绍一下SQL Server日 ...
- 修改SQL Server中的计算机名
安装SQL Server之后,如果修改计算机名会导致登录异常,或者某些功能不能用,例如配置Replication时会提示如下错误: SQL Server replication requires th ...
- SQL Server中char与varchar数据类型区别
在SQL Server中char类型的长度是不可变的,而varchar的长度是可变的 . 存入数据时: 如果数据类型为char时,当定义一个字段固定长度时,如果存进去数据长度小于char的长度,那么存 ...
- 在SQL SERVER中实现RSA加解密函数(第二版)
/*************************************************** 作者:herowang(让你望见影子的墙) 日期:2010.1.5 注: 转载请保留此信息 更 ...
- SQL Server中易混淆的数据类型
1)char.varchar.text和nchar.nvarchar.ntextchar和varchar的长度都在1到8000之间,它们的区别在于char是定长字符数据,而varchar是变长字符数据 ...
- MS SQL SERVER 中的系统表
MS SQL SERVER 中的系统表 序号 名称 说明 备注 1 syscolumns 每个表和视图中的每列在表中占一行,存储过程中的每个参数在表中也占一行. 2 syscomments 包含每 ...
- 从SQL Server中导入/导出Excel的基本方法(转)
从sql server中导入/导出 excel 的基本方法 /*=========== 导入/导出 excel 的基本方法 ===========*/ 从excel文档中,导入数据到sql数据库中,很 ...
- (转)SQL Server中使用convert进行日期转换
原文链接:http://www.cnblogs.com/weiqt/articles/1826847.html SQL Server中使用convert进行日期转换 一般存入数据库中的时间格式为yyy ...
随机推荐
- 软件-集成开发环境:IDEA(Java 语言开发的集成环境)
ylbtech-软件-集成开发环境:IDEA(Java 语言开发的集成环境) IDEA 全称IntelliJ IDEA,是用于java语言开发的集成环境(也可用于其他开发语言),IntelliJ在业界 ...
- hash 在 perl 中的用法(转载)
Perl的数据结构中最有趣的一个特性是哈希(hash),它使得在数据片段之间建立键-值(key-value)关联成为可能.虽然这些哈希要远远比普通系统中以数字索引的数组用途更广,但是往往也会使初学者不 ...
- linux拷贝文件夹cp
方法就是: cp -r dir dir 如果只是拷贝文件的话直接cp即可
- Python2.x 与 Python3.x 共存
一.Python2.x 安装 说明:我们先安装python2.x,默认C盘安装即可. 链接: https://pan.baidu.com/s/1yfsVNKmeOR-2C0fK0rPh4A 密码: x ...
- Webform(条件查询)
<html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> &l ...
- Centos nginx安装
1.下载nginx http://nginx.org/en/download.html 2.上传到服务器上,并解压: rz 后选择上传的文件 tar -zxvf /fish/download/ngin ...
- python——vs2017安装python库时,提示pip指令问题。
需要跟新pip指令 方法: 第一步:打开vs2017 后新建一个python 文件 后面如图 点击红色部分 2.在框中输入pip之后更新即可 如图 3.问题解决 倘若还有问题 欢迎分享
- js day03
一)jQuery常用AJAX-API 目的:简化客户端与服务端进行局部刷新的异步通讯 (1)取得服务端当前时间 简单形式:jQuery对象.load(url) 返回结果自动添加到jQuery对象代表的 ...
- Controller层aop
利用@Around通知修改Controller的返回值 自定义一个注解@OperationBtn 在切入点Controller上加上自定义注解 接下来就是重点了,AspectJ写切面类,对该Contr ...
- 2019/1/15 python基础学习
一.列表切片a.快捷方式:spam[:3] ----表示从列表开始到3位置结束:拿到的内容是0,1,2没有3位置上的数字.spam[3:]b.列表的拼接.复制: 拼接:使用 + [1,2,3]+['A ...