Как я могу искать последовательность байтов в поле varbinary(max) SQL Server?

Я пытаюсь написать запрос на SQL Server 2012, который будет возвращать столбцы varbinary(max), содержащие указанную последовательность байтов. Я могу сделать это с помощью запроса, который преобразует поле varbinary в varchar и использует LIKE:

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

где «0x626C6168» — моя целевая последовательность байтов. К сожалению, это работает только в том случае, если поле не содержит байтов со значением 0 (0x00), а это очень часто встречается в моих данных. Есть ли другой подход, который я могу использовать, который будет работать со значениями, содержащими байты с нулевым значением?


person Dan Hermann    schedule 31.10.2013    source источник


Ответы (3)


Если вы используете двоичную сортировку, она должна работать.

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

Вам может понадобиться (скажем) Latin1_General_BIN, если вы используете более старую версию SQL Server.

person Martin Smith    schedule 31.10.2013

К сожалению, решение, предложенное Мартином, имеет изъян.

Если двоичная последовательность в ключе поиска содержит 0x25 байт, она будет преобразована в % символ (согласно ASCII< /а> таблица).

Затем этот символ интерпретируется как подстановочный знак в предложении like, что приводит к появлению многих нежелательных результатов.

-- 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) + '%');

Чтобы решить эту проблему, используйте пункт поиска ниже:

-- 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;
person sɐunıɔןɐqɐp    schedule 18.04.2018

Я только что обнаружил этот очень простой запрос

SELECT * FROM foo
WHERE CONVERT(varchar(max), myvarbincolumn,2) LIKE '%626C6168%'
person Michael Riley - AKA Gunny    schedule 27.07.2020