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 ...
随机推荐
- 基于MNIST数据集使用TensorFlow训练一个包含一个隐含层的全连接神经网络
包含一个隐含层的全连接神经网络结构如下: 包含一个隐含层的神经网络结构图 以MNIST数据集为例,以上结构的神经网络训练如下: #coding=utf-8 from tensorflow.exampl ...
- FPGA editor 的使用之一 ------ Probe探针
做FPGA设计经常会用到FPGA editor工具,今天开始总结下使用FPGA editor工具的经验. 1.添加probes 在debug时,经常要分析设计中的某一个信号的状态变化,需要观测这个信号 ...
- windows:plsql配置oracle连接
1.plsql安装 此处省略,后续添加 2.plsql连接oracle: (1) 下载Instant client:http://www.oracle.com/technetwork/cn/topic ...
- 面向连接的tcp 编程
from socket import * serverSocket=socket(AF_INET,SOCK_STREAM) serverSocket.bind(("",8899)) ...
- 解决idea创建Maven项目卡在running tmp archetypexxxtmp
打开IDEA settings 然后在VM Options内添加-DarchetypeCatalog=internal 运行参数
- 【Python】pip国内安装源和yum恢复
豆瓣安装源 pip install packages -i http://pypi.doubanio.com/simple --upgrade --trusted-host pypi.doubanio ...
- python_10 迭代器和生成器
迭代器协议: 1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个Stopiteration异常,以终止迭代(只能往后走不能往前退) 2.可迭代对象:实现 ...
- elasticsearch-权威指南笔记-基础部分
参考这里的文档es权威指南 话说这个坑爹的文档是2.x版本的es,英文版本也是,所以就没啥好抱怨的了. 官方教程中有很多坑 例如,需要启动text上的索引. 还有就是get这个是不能带json的,所以 ...
- xtrabackup备份还原MySQL数据库
mysqldump 备份鉴于其自身的某些特性(锁表,本质上备份出来insert脚本或者文本,不支持差异备份),不太适合对实时性要求比较高的情况Xtrabackup可以解决mysqldump存在的上述的 ...
- Lua中面向对象
一.Lua中类的简单实现: (1)版本——摘自 Cocos2.0中的: --Create an class. function class(classname, super) local superT ...