在T-SQL中,为什么操作符不适用于变量而是适用于文字?

Cod*_*shi 4 t-sql sql-server

这是脚本:

第一个脚本:

declare @a char(10) = 'AA%'
declare @b char(10) = 'AA001'

if @b LIKE @a 
     print 'Equals' 
else 
begin 
     print 'Not equals' 
end
Run Code Online (Sandbox Code Playgroud)

它打印:

Not Equals
Run Code Online (Sandbox Code Playgroud)

我期待它打印Equals.但是下面的脚本@a在条件中没有使用:

第二个脚本:

declare @a char(10) = 'AA%'
declare @b char(10) = 'AA001'

if @b LIKE 'AA%' 
    print 'Equals' 
else 
begin 
    print 'Not equals' 
end
Run Code Online (Sandbox Code Playgroud)

版画

Equals
Run Code Online (Sandbox Code Playgroud)

那么为什么第一个脚本认为它们不相等但第二个脚本认为它们相等?

Cod*_*shi 7

答案实际上很简单,但这是一个很大的问题:这是因为char类型.

如果我们打印出2个变量:

print @a
print @b
Run Code Online (Sandbox Code Playgroud)

输出将是(点表示空白空间):

AA%.......       
AA001.....   
Run Code Online (Sandbox Code Playgroud)

所以第一个查询like对两个变量进行了处理,并且尾随空白使得它不相等,因为根据MSDN,从逻辑上讲,尾随空格(空格)是重要的:

如果查询中的比较是返回字符串LIKE'abc'(abc没有空格)的所有行,则返回以abc开头且具有零个或多个尾随空格的所有行.+使用包含char和varchar数据的模式的字符串比较可能无法通过LIKE比较,因为数据的存储方式.

第二个查询

第二个查询具有AA%隐式类型的文字,varchar因为AA001(类型char)将是AA%,它打印等于.为了重申文字的类型varchar,我使用了这个查询:

SELECT SQL_VARIANT_PROPERTY('AA%', 'BaseType')
Run Code Online (Sandbox Code Playgroud)

返回varchar.


更多信息

以下是来自MSDN的更多示例,以进一步明确:

以下示例将本地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  
Run Code Online (Sandbox Code Playgroud)

在该FindEmployee过程中,不返回任何行,因为@EmpLName只要名称包含少于20个字符,char变量()就包含尾随空格.因为LastName列是varchar,所以没有尾随空格.此过程失败,因为尾随空白很重要.但是,以下示例成功,因为尾随空格未添加到varchar变量.

- 使用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';  
Run Code Online (Sandbox Code Playgroud)

这是结果集:

FirstName LastName City
---------- -------------------- ---------------
Angela Barbariol Snohomish
David Barber Snohomish
(2 row(s) affected)
Run Code Online (Sandbox Code Playgroud)