一同事在写脚本时,遇到一个关于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输出结果不一致解惑的更多相关文章

  1. SQL SERVER中LIKE使用变量类型不同输出结果不一致解惑

    一同事在写脚本时,遇到一个关于LIKE里面使用不同的变量类型导致查询结果不一致的问题,因为这个问题被不同的人问过好几次,索性总结一下,免得每次都要解释一遍,直接丢一篇博客岂不是更方便!其实看似有点让人 ...

  2. Sql Server中日期时间格式化为字符串输出

    在SQL Server数据库中,SQL Server日期时间格式转换字符串可以改变SQL Server日期和时间的格式,是每个SQL数据库用户都应该掌握的.本文我们主要就介绍一下SQL Server日 ...

  3. 修改SQL Server中的计算机名

    安装SQL Server之后,如果修改计算机名会导致登录异常,或者某些功能不能用,例如配置Replication时会提示如下错误: SQL Server replication requires th ...

  4. SQL Server中char与varchar数据类型区别

    在SQL Server中char类型的长度是不可变的,而varchar的长度是可变的 . 存入数据时: 如果数据类型为char时,当定义一个字段固定长度时,如果存进去数据长度小于char的长度,那么存 ...

  5. 在SQL SERVER中实现RSA加解密函数(第二版)

    /*************************************************** 作者:herowang(让你望见影子的墙) 日期:2010.1.5 注: 转载请保留此信息 更 ...

  6. SQL Server中易混淆的数据类型

    1)char.varchar.text和nchar.nvarchar.ntextchar和varchar的长度都在1到8000之间,它们的区别在于char是定长字符数据,而varchar是变长字符数据 ...

  7. MS SQL SERVER 中的系统表

    MS SQL SERVER 中的系统表 序号 名称 说明 备注 1 syscolumns 每个表和视图中的每列在表中占一行,存储过程中的每个参数在表中也占一行.   2 syscomments 包含每 ...

  8. 从SQL Server中导入/导出Excel的基本方法(转)

    从sql server中导入/导出 excel 的基本方法 /*=========== 导入/导出 excel 的基本方法 ===========*/ 从excel文档中,导入数据到sql数据库中,很 ...

  9. (转)SQL Server中使用convert进行日期转换

    原文链接:http://www.cnblogs.com/weiqt/articles/1826847.html SQL Server中使用convert进行日期转换 一般存入数据库中的时间格式为yyy ...

随机推荐

  1. 基于MNIST数据集使用TensorFlow训练一个包含一个隐含层的全连接神经网络

    包含一个隐含层的全连接神经网络结构如下: 包含一个隐含层的神经网络结构图 以MNIST数据集为例,以上结构的神经网络训练如下: #coding=utf-8 from tensorflow.exampl ...

  2. FPGA editor 的使用之一 ------ Probe探针

    做FPGA设计经常会用到FPGA editor工具,今天开始总结下使用FPGA editor工具的经验. 1.添加probes 在debug时,经常要分析设计中的某一个信号的状态变化,需要观测这个信号 ...

  3. windows:plsql配置oracle连接

    1.plsql安装 此处省略,后续添加 2.plsql连接oracle: (1) 下载Instant client:http://www.oracle.com/technetwork/cn/topic ...

  4. 面向连接的tcp 编程

    from socket import * serverSocket=socket(AF_INET,SOCK_STREAM) serverSocket.bind(("",8899)) ...

  5. 解决idea创建Maven项目卡在running tmp archetypexxxtmp

    打开IDEA settings 然后在VM Options内添加-DarchetypeCatalog=internal 运行参数

  6. 【Python】pip国内安装源和yum恢复

    豆瓣安装源 pip install packages -i http://pypi.doubanio.com/simple --upgrade --trusted-host pypi.doubanio ...

  7. python_10 迭代器和生成器

    迭代器协议: 1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个Stopiteration异常,以终止迭代(只能往后走不能往前退) 2.可迭代对象:实现 ...

  8. elasticsearch-权威指南笔记-基础部分

    参考这里的文档es权威指南 话说这个坑爹的文档是2.x版本的es,英文版本也是,所以就没啥好抱怨的了. 官方教程中有很多坑 例如,需要启动text上的索引. 还有就是get这个是不能带json的,所以 ...

  9. xtrabackup备份还原MySQL数据库

    mysqldump 备份鉴于其自身的某些特性(锁表,本质上备份出来insert脚本或者文本,不支持差异备份),不太适合对实时性要求比较高的情况Xtrabackup可以解决mysqldump存在的上述的 ...

  10. Lua中面向对象

    一.Lua中类的简单实现: (1)版本——摘自 Cocos2.0中的: --Create an class. function class(classname, super) local superT ...