13

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 = 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?

  • I was looking to write a check constraint that a string was trimmed. I found a workaround which is to check that MyString+'x' = ltrim(rtrim(MyString))+'x' as suggested on this blog – default.kramer Feb 27 '18 at 19:18
15

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:

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

The 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 0

The behavior of the LIKE operator for the ASCII type is SQL Server-specific; for the Unicode type it is ANSI-compliant.

4

SQL was born in an era when most data processing languages used fixed lengths for every field/variable. Automatic padding of text fields with extra spaces was also part of that picture. To line up with that behaviour, the original SQL CHAR type was explicitly defined for its '=' operator to ignore trailing spaces. (If you find that strange, show me a compelling case where trailing spaces appended to a text have actual real business meaning.)

SQL CHAR types have evolved in all sorts of directions since then, but it is not inconceivable that certain more modern data types have still inherited some characteristics from their historical predecessors.

  • "show me a compelling case where trailing spaces appended to a text have actual real business meaning" - storing whitespace-significant data, such as certain raw console output and pre-unsafe XML fragments. – Dai Mar 15 '17 at 4:34
1

In the documentation for LIKE (Transact-SQL), Microsoft writes (emphasis mine):

Pattern Matching by Using LIKE

LIKE supports ASCII pattern matching and Unicode pattern matching. When all arguments ... are ASCII character data types, ASCII pattern matching is performed. If any one of the arguments are of Unicode data type, all arguments are converted to Unicode and Unicode pattern matching is performed. When you use Unicode data ... with LIKE, trailing blanks are significant; however, for non-Unicode data, trailing blanks are not significant. Unicode LIKE is compatible with the ISO standard. ASCII LIKE is compatible with earlier versions of SQL Server.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.