末尾有空格的 Varchar 的行为

AMH*_*AMH 16 sql-server stored-procedures

当我使用带有空格的 Varchar 时,它会忽略末尾的空格。

前任:

declare @X varchar(50)
Run Code Online (Sandbox Code Playgroud)

这个...

set  @X= 'John'
Run Code Online (Sandbox Code Playgroud)

...是相同的...

set @X= 'John           '
Run Code Online (Sandbox Code Playgroud)

它认为这些是相等的。我怎样才能让系统将这些识别为不同的?

Ole*_*Dok 25

一切都只是根据ANSI标准:

尾随空格解释

SQL Server 遵循有关如何比较字符串与空格的 ANSI/ISO SQL-92 规范(第 8.2 节,一般规则 #3)。ANSI 标准要求对比较中使用的字符串进行填充,以便在比较它们之前它们的长度匹配。填充直接影响 WHERE 和 HAVING 子句谓词以及其他 Transact-SQL 字符串比较的语义。例如,Transact-SQL 认为字符串 'abc' 和 'abc ' 对于大多数比较操作是等效的。

此规则的唯一例外是 LIKE 谓词。当 LIKE 谓词表达式的右侧包含一个带有尾随空格的值时,SQL Server 在进行比较之前不会将这两个值填充到相同的长度。因为根据定义,LIKE 谓词的目的是促进模式搜索而不是简单的字符串相等性测试,所以这不违反前面提到的 ANSI SQL-92 规范部分。

这是上述所有案例的一个众所周知的例子:

DECLARE @a VARCHAR(10)
DECLARE @b varchar(10)

SET @a = '1'
SET @b = '1 ' --with trailing blank

SELECT 1
WHERE 
    @a = @b 
AND @a NOT LIKE @b
AND @b LIKE @a
Run Code Online (Sandbox Code Playgroud)

这里有一些关于尾随空格和LIKE子句的更多细节。

但是如果你想区分它们 - 你可以决定使用DATALENGTHfunction 而不是LEN,因为

SELECT 1 WHERE LEN('John ') = LEN('John')
Run Code Online (Sandbox Code Playgroud)

会给你 1 而不是

SELECT 1 WHERE DATALENGTH('John ') = DATALENGTH('John')
Run Code Online (Sandbox Code Playgroud)

解决办法

  • 使用 DATALENGTH 函数区分字符串
  • 将字符串转换为 NVARCHAR 类型 - 最好将此类型声明为 SP 的参数