这是脚本:
第一个脚本:
declare @a char(10) = 'AA%'
declare @b char(10) = 'AA001'
if @b LIKE @a
print 'Equals'
else
begin
print 'Not equals'
end
打印:
Not Equals
我原以为要打印Equals
。但是下面的脚本在条件中不使用@a
:
第二个脚本:
declare @a char(10) = 'AA%'
declare @b char(10) = 'AA001'
if @b LIKE 'AA%'
print 'Equals'
else
begin
print 'Not equals'
end
打印
Equals
那么为什么第一个脚本认为它们不相等但第二个脚本认为它们相等?
答案 0 :(得分:7)
答案实际上很简单,但这是 big gotcha :这是因为char
类型。
如果我们打印出2个变量:
print @a
print @b
输出将是(点表示空白空间):
AA%.......
AA001.....
因此第一个查询对两个变量执行like
,并且尾随空白使它不相等,因为根据MSDN,从逻辑上讲,尾随空格(空格)是重要的:< / p>
如果查询中的比较是使用字符串LIKE&#39; abc&#39;返回所有行。 (abc没有空格),返回以abc开头且具有零个或多个尾随空格的所有行。 + 使用包含char和varchar数据的模式的字符串比较可能无法通过LIKE比较,因为数据的存储方式。
第二次查询
第二个查询的文字AA%
的隐式类型为varchar
,而AA001
(其类型为char
)将类似于AA%
,它打印等于。为了重申文字的类型是varchar
,我使用了这个查询:
SELECT SQL_VARIANT_PROPERTY('AA%', 'BaseType')
返回 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
在FindEmployee
过程中,不返回任何行,因为只要名称包含少于20个字符,char变量(@EmpLName
)就包含尾随空格。因为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';
以下是结果集:
FirstName LastName City
---------- -------------------- ---------------
Angela Barbariol Snohomish
David Barber Snohomish
(2 row(s) affected)