views:

66

answers:

5

If I deliberately store trailing spaces in a VARCHAR column, how can I force SQL Server to see the data as mismatch?

SELECT 'foo' WHERE 'bar' = 'bar    '

I have tried:

SELECT 'foo' WHERE LEN('bar') = LEN('bar    ')

One method I've seen floated is to append a specific character to the end of every string then strip it back out for my presentation... but this seems pretty silly.

Is there a method I've overlooked?

I've noticed that it does not apply to leading spaces so perhaps I run a function which inverts the character order before the compare.... problem is that this makes the query unSARGable....

+1  A: 

ansi padding http://msdn.microsoft.com/en-us/library/ms187403.aspx

jms
I cannot use `CHAR` because I cannot have trailing spaces where they are unintended.
Matthew PK
@Mat realized that as soon as I hit enter. Let me know if Ansi padding worked for you. Good luck.
jms
How does ANSI_PADDING, controlling the way how values are STORED, relate to or answer this question?
vgv8
"The SET ANSI_PADDING setting does not affect whether SQL Server pads strings before it compares them. SET ANSI_PADDING only affects whether trailing blanks are trimmed from values being inserted into a table, so it affects storage but not comparisons" http://support.microsoft.com/kb/316626
vgv8
+3  A: 

Like you said, I don't think there are many options. The only two I could come up with were these:

DECLARE @x nvarchar(50)
DECLARE @y nvarchar(50)
SET @x = 'CAT     '
SET @y = 'CAT'

SELECT 1 WHERE len(@x + '_') = len(@y + '_')

SELECT 1 WHERE reverse(@x) = reverse(@y)

EDIT

Thought of a third:

SELECT 1 WHERE REPLACE(@x, ' ', '_') = REPLACE(@y, ' ', '_')

And a fourth, assuming you're on SQL 2005+

SELECT 1 WHERE QUOTENAME(@x) = QUOTENAME(@y)

Personally, I like the reverse idea the best, but it all depends on which one performs best for you.

LittleBobbyTables
+1 for the REVERSE, but the LEN(foo + some char) would likely be the most performant!
p.campbell
@p.campbell - interesting, thanks for pointing that out!
LittleBobbyTables
All of them suck speed wise. There simply is no good solution.
TomTom
reverse() is out for foolproof string comparison, since it fails on strings with leading spaces. For exmpl, 'CAT' will be "equal" to '....CAT' (I could not insert spaces, read dot as space)
vgv8
@vgv8 - That's a good point
LittleBobbyTables
+2  A: 

SQL Server sees them differently.

LEN (Transact-SQL)
Returns the number of characters of the specified string expression, excluding trailing blanks.
To return the number of bytes used to represent an expression, use the DATALENGTH function

Also you better be aware that SQL Server follows ANSI/ISO SQL-92 padding the character strings used in comparisons so that their lengths match before comparing them.

Update (later):
I deleted my code using LIKE (which does not pad spaces during comparison) and DATALENGTH() since there engagement is not foolprof comparison of strings.

Anyway, this question is duplicate of a few previous ones in SO, containing answers, for ex., this one. And there are others (I did not read out them for exhaystive answers) this , this, and others. The search finds dozens in SO and zillions in internet. I dunno how it was possible to miss the answer.

vgv8
I think `DATALENGTH` will work well for me here, or storing a calculated `DATALENGTH` in a column to make it faster at the expense of a byte.
Matthew PK
A: 

I've only really got two suggestions. One would be to revisit the design that requires you to store trailing spaces - they're always a pain to deal with in SQL.

The second (given your SARG-able comments) would be to add acomputed column to the table that stores the length, and add this column to appropriate indexes. That way, at least, the length comparison should be SARG-able.

Damien_The_Unbeliever
This question should have been closed as dupe. It was exhaustively and repeatedly answered in SO before, including design (truncating trailing spaces), I had given in my update, http://stackoverflow.com/questions/1146280/is-it-good-practice-to-trim-whitespace-leading-and-trailing-when-selecting-inse
vgv8
@vgv8 - I think this one is subtly different, in that the OP seems to be saying that they have to store the trailing whitespace, and that it's significant.
Damien_The_Unbeliever
+2  A: 

you could try somethign like this:

declare @a varchar(10), @b varchar(10)
set @a='foo'
set @b='foo   '

select @a, @b, DATALENGTH(@a), DATALENGTH(@b)
DForck42
Yep. `SELECT * FROM YourTable WHERE col = @searchterm and DATALENGTH(col) = DATALENGTH(@searchterm)` should still be reasonably sargable.
Martin Smith
that's awesome martin, i was trying to think of a way to do that.
DForck42