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 ...
随机推荐
- ftok()函数深度解析
[转载] 原文链接:https://blog.csdn.net/u013485792/article/details/50764224 关于ftok函数,先不去了解它的作用来先说说为什么要用它,共享内 ...
- mysql-查询存在主表但是不存在副标的数据
A.B两表,找出ID字段中,存在A表,但是不存在B表的数据.A表总共13w数据,去重后大约3W条数据,B表有2W条数据,且B表的ID字段有索引. 方法一 使用 not in ,容易理解,效率低 ~执 ...
- TabLayout+ViewPager 标题不显示问题
第一次用TabLayout+ViewPager 组合在布局中写好了三个标题预览没问题而且也设置了 app:tabIndicatorColor="@color/colorAccent" ...
- web socket client
<!DOCTYPE HTML> <html> <head> <title>My WebSocket</title> </head> ...
- maven构建SSM框架中pom.xml文件配置
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...
- leetcode338
public class Solution { public int[] CountBits(int num) { ]; ; i <= num; i++) { ; var cur = i; do ...
- NetBeans 代码折叠
代码折叠 // <editor-fold> Your code goes here...// </editor-fold> 添加描述 // <editor-fold ...
- cfile fopen fopen_s win10下打开文件失败
vc程序在win10下面使用fopen 打开文件失败,在网上查 了下是因为UAC权限的问题如下: 由于windows vista win7 win8 win 10 添加了UAC权限,所以会导致 在系统 ...
- mvc中view与controll之间传递参数时,可以使用url进行传递
mvc中view与controller之间传递参数时,可以使用url进行传递,但是在url的地址中需要加上“id=123”这样的东西才行. 具体如代码: window.location.href = ...
- byobu 禁止窗口名称随目录变化
It looks like the config set-window-option -g automatic-rename off doesn't work. When I added the fo ...