Question

I am trying to write a query on SQL Server 2012 that will return varbinary(max) columns that contain a specified byte sequence. I am able to do that with a query that converts the varbinary field to varchar and uses LIKE:

SELECT * FROM foo
WHERE CONVERT(varchar(max), myvarbincolumn) LIKE 
  '%' + CONVERT(varchar(max), 0x626C6168) + '%'

where "0x626C6168" is my target byte sequence. Unfortunately, this works only if the field does not contain any bytes with the value zero (0x00) and those are very common in my data. Is there a different approach I can take that will work with values that contain zero-valued bytes?

Was it helpful?

Solution

If you use a binary collation it should work.

WITH foo(myvarbincolumn) AS
(
SELECT 0x00626C616800
)
SELECT *
FROM   foo
WHERE  CONVERT(VARCHAR(max), myvarbincolumn) COLLATE Latin1_General_100_BIN2 
                    LIKE '%' + CONVERT(VARCHAR(max), 0x626C6168) + '%' 

You might need (say) Latin1_General_BIN if on an older version of SQL Server.

OTHER TIPS

Unfortunately the solution proposed by Martin has a flaw.

In case the binary sequence in the search key contains any 0x25 byte, it will be translated to the % character (according to the ASCII table).

This character is then interpreted as a wildcard in the like clause, causing many unwanted results to show up.

-- A table with a binary column:
DECLARE @foo TABLE(BinCol VARBINARY(MAX));
INSERT INTO @foo (BinCol) VALUES (0x001125), (0x000011), (0x001100), (0x110000);

-- The search key:
DECLARE @key VARBINARY(MAX) = 0x1125; -- 0x25 is '%' in the ASCII table!

-- This returns ALL values from the table, because of the wildcard in the search key:
SELECT * FROM @foo WHERE
    CONVERT(VARCHAR(max), BinCol) COLLATE Latin1_General_100_BIN2
    LIKE ('%' + CONVERT(VARCHAR(max), @key) + '%');

To fix this issue, use the search clause below:

-- This returns just the correct value -> 0x001125
SELECT * FROM @foo WHERE 
    CHARINDEX
    (
        CONVERT(VARCHAR(max), @key),
        CONVERT(VARCHAR(max), BinCol) COLLATE Latin1_General_100_BIN2
    ) > 0;

I just discovered this very simply query

SELECT * FROM foo
WHERE CONVERT(varchar(max), myvarbincolumn,2) LIKE '%626C6168%'
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top