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 ...
随机推荐
- 使用css实现时间轴
本文将使用css来实现一个左右交叉布局的时间轴,效果如下: 使用的都是一些常用的css,代码如下: <!DOCTYPE> <html> <head> <tit ...
- atom常用插件
汉化 simplified-chinese-menureact atom-react-snippets-0.5.0polymer atom-polymer-0.13.0polymer Atom-Pol ...
- jsp jstl quote symbol expected
org.apache.jasper.JasperException: /WEB-INF/jsp/user/index.jsp (line: 2, column: 27) quote symbol ex ...
- Vim 命令、操作、快捷键
打开单个文件:vim file 同时打开多个文件:vim file1 file2 file3 ... 在vim窗口中打开一个新文件 : :open file 在新窗口中打开文件: :split fi ...
- js跨域传值,兼容ie8以上
js跨域传值,兼容ie8以上 事先说明,此方法并不支持ie8,如果想要支持ie8的话,需要用这种思路(来自微软): if (window.addEventListener) { window.addE ...
- Centos nginx安装
1.下载nginx http://nginx.org/en/download.html 2.上传到服务器上,并解压: rz 后选择上传的文件 tar -zxvf /fish/download/ngin ...
- Linux Shell 简介
什么是 Shell Shell 是用户和 Linux 内核之间的接口程序,当从 Shell 或其他程序向 Linux 传递命令时,内核会做出相应的反应: Shell 是一个命令语言解释器,它拥有自己内 ...
- 定时器和函数的使用初级------移动一个div元素
在页面的动画效果中,经常有看到某个小块从一个地方移动到另一个地方的现象,现在,我们也来自己做一个这样的小动画,涉及到的基础包括定时器的使用和函数的使用 例如,我们要实现一个小方块从左面移动到右面,然后 ...
- ODPS SQL <for 数据操作语言DML>
基本操作: 查询: SELECT [ALL | DISTINCT] select_expr, select_expr, ... FROM table_reference [WHERE where_co ...
- python学习Day3 变量、格式化输出、注释、基本数据类型、运算符
今天复习内容(7项) 1.语言的分类 -- 机器语言:直接编写0,1指令,直接能被硬件执行 -- 汇编语言:编写助记符(与指令的对应关系),找到对应的指令直接交给硬件执行 -- 高级语言:编写人能识别 ...