patternsqlModerate
SQL Server auto-trim of varchar value in equal comparison but not like comparison
Viewed 0 times
trimsqlautoequalbutvarcharvaluecomparisonlikeserver
Problem
I came across some interesting behaviour on SQL Server (observed in 2005 and 2012) today that I was hoping someone could explain.
A query doing a comparison using
Consider this SQL Fiddle: http://sqlfiddle.com/#!6/72262/4
Note that the
Bonus points: I am unable to replicate this on a VARCHAR field, I would have thought that a space would be handled in the same way in both data types - is this true?
A query doing a comparison using
= on an NVARCHAR field ignored the trailing space in the string (or auto-trimmed the value before comparison) but the same query using the like operator did not ignore the space. Collation being used is Latin1_General_CI_AS in 2012.Consider this SQL Fiddle: http://sqlfiddle.com/#!6/72262/4
Note that the
like operator does not return a result for the trailing space string, but the = operator does. Why is this? Bonus points: I am unable to replicate this on a VARCHAR field, I would have thought that a space would be handled in the same way in both data types - is this true?
Solution
My initial answer suggested that the ANSI_PADDING flag set to OFF may be to blame for the difference in behavior. However, this is incorrect; this flag only has an effect on storage, but not equality comparison.
The difference stems from Microsoft's implementation of the SQL standard. The standard states that when checking for equality, both strings left and right of the equality operator have to be padded to have the same length. This explains the following results:
The LIKE operator does not pad its operands. It also behaves differently for
The behavior of the LIKE operator for the ASCII type is SQL Server-specific; for the Unicode type it is ANSI-compliant.
The difference stems from Microsoft's implementation of the SQL standard. The standard states that when checking for equality, both strings left and right of the equality operator have to be padded to have the same length. This explains the following results:
insert into test_padding (varchar_clmn, nvarchar_clmn) values ('space ', 'nspace ')
go
-- equality for varchar column
select count(*) from test_padding where varchar_clmn = 'space' -- returns 1
select count(*) from test_padding where varchar_clmn = 'space ' -- returns 1
select count(*) from test_padding where varchar_clmn = 'space ' --returns 1
-- equality for nvarchar column
select count(*) from test_padding where nvarchar_clmn = 'nspace' -- returns 1
select count(*) from test_padding where nvarchar_clmn = 'nspace ' -- returns 1
select count(*) from test_padding where nvarchar_clmn = 'nspace ' --returns 1The LIKE operator does not pad its operands. It also behaves differently for
VARCHAR and NVARCHAR column types:-- likeness for varchar column
select count(*) from test_padding where varchar_clmn like 'space' -- returns 1
select count(*) from test_padding where varchar_clmn like 'space ' -- returns 1
select count(*) from test_padding where varchar_clmn like 'space ' -- returns 0
-- likeness for nvarchar column
select count(*) from test_padding where nvarchar_clmn like 'nspace' -- returns 0
select count(*) from test_padding where nvarchar_clmn like 'nspace ' -- returns 1
select count(*) from test_padding where nvarchar_clmn like 'nspace ' -- returns 0The behavior of the LIKE operator for the ASCII type is SQL Server-specific; for the Unicode type it is ANSI-compliant.
Code Snippets
insert into test_padding (varchar_clmn, nvarchar_clmn) values ('space ', 'nspace ')
go
-- equality for varchar column
select count(*) from test_padding where varchar_clmn = 'space' -- returns 1
select count(*) from test_padding where varchar_clmn = 'space ' -- returns 1
select count(*) from test_padding where varchar_clmn = 'space ' --returns 1
-- equality for nvarchar column
select count(*) from test_padding where nvarchar_clmn = 'nspace' -- returns 1
select count(*) from test_padding where nvarchar_clmn = 'nspace ' -- returns 1
select count(*) from test_padding where nvarchar_clmn = 'nspace ' --returns 1-- likeness for varchar column
select count(*) from test_padding where varchar_clmn like 'space' -- returns 1
select count(*) from test_padding where varchar_clmn like 'space ' -- returns 1
select count(*) from test_padding where varchar_clmn like 'space ' -- returns 0
-- likeness for nvarchar column
select count(*) from test_padding where nvarchar_clmn like 'nspace' -- returns 0
select count(*) from test_padding where nvarchar_clmn like 'nspace ' -- returns 1
select count(*) from test_padding where nvarchar_clmn like 'nspace ' -- returns 0Context
StackExchange Database Administrators Q#56876, answer score: 19
Revisions (0)
No revisions yet.