2012-02-21 4 views
2

Вопрос:SQL: Сравните, если строка MD5 хеш?

Мне нужно СРАВНЕНИЕ, если строка является хешем MD5 в SQL.

Я нашел это PHP-функции:

function isValidMd5($md5) 
{ 
    return !empty($md5) && preg_match('/^[a-f0-9]{32}$/', $md5); 
} 

Поскольку SQL не хватает {32} синтаксис, я просто дублировать [а-f0-9] 32 раз:

IF '200ceb26807d6bf99fd6f4f0d1ca54d4' LIKE '[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]' 
BEGIN 
    PRINT 'YES' 
END 
ELSE 
BEGIN 
    PRINT 'NO' 
END 

Однако, чтобы избегайте возможного столкновения с именем пользователя, состоящим из 32 [af], однако маловероятно, я хочу сделать подобное сравнение в верхнем регистре.

Но если для целей тестирования я:

IF 'E' COLLATE Latin1_General_CS_AS LIKE ('[a-f0-9]' COLLATE Latin1_General_CS_AS) 
BEGIN 
    PRINT 'yes' 
END 
ELSE 
BEGIN 
    PRINT 'no' 
END 

я да, и не нет.
Однако COLLATE Latin1_General_CS_AS должен сделать его чувствительным к регистру ...

Как сделать LIKE в этом случае чувствительным к регистру IF?

ответ

3

Лучше инвертировать проверку и упростить ее работу, проверяя любую вещь, которая заставит ее потерпеть неудачу. Это означает, что вам не нужно повторять [0-9a-f] 32 раз в коде.

IF LEN(@myValue) <> 32 OR LOWER(@myValue) LIKE '%[^0-9a-f]%' 
BEGIN 
    -- No it isn't 
END ELSE BEGIN 
    -- Yes it is 
END 

т.е., если это не 32 символов или содержит символ за пределами установленного шестнадцатеричной, то она не сможет.

+0

В чем смысл ^? Поскольку это не работает с моим SQL-сервером ... –

+0

Инвертировать (т. Е. Сопоставлять любой символ, который * не является * 0-9a-f). Таким образом, он будет соответствовать, например, «z». Кроме того, я только что отредактировал свой ответ, так как шаблон LIKE нуждался в небольшой настройке: теперь он завернут в совпадения «%». –

+0

А теперь я понял. К сожалению, я виноват, я не видел измененного переключения в if. Да, это умнее, с машинисткой перспективы. Но у него все еще есть проблема с чувствительностью к регистру, что является точкой этого сообщения. –

2

Будет ли это работать?

IF myValue LIKE '[a-f0-9][...]' 
and LOWER(myValue) = myValue 
+0

Отлично, это работает (идея мудрая). Вместо этого я использую верхний. Но вы пропускаете COLLATE Latin1_General_CS_AS после myValue –

+1

Проблема заключается в том, что a-f, если я заменил его на abcdef, тогда он отлично работает. Я думаю, что слово дня: Microsoft BUG !!! –

1

OK, после кропотливого изучения проблемы, это самое лучшее решение:

Обратите внимание, что это важно, чтобы написать ABCDEF вместо A-F, так как иначе любая буква между А и F не чувствительны к регистру.

(как для AF: обратите внимание, что немного 'а' является пограничный случай, так как она не находится в этом диапазоне, в отличие от маленьких 'б'.)

DECLARE @myValue varchar(100) 

--SET @myValue = '66B9E31D4C59D3802279515F9B1A6222' 
SET @myValue = '66B9E31D4C59D3802279515F9B1B6222' 


IF LEN(@myValue) <> 32 OR @myValue LIKE '%[^0-9ABCDEF]%' COLLATE Latin1_General_CS_AS 
BEGIN 
    print 'No it isn''t' 
END ELSE BEGIN 
    print 'Yes it is ' 
END 

И как MD5-Checkfunction:

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[fn_IsMd5Hash]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT')) 
DROP FUNCTION [dbo].[fn_IsMd5Hash] 
GO 




-- ======================================================================== 
-- Author: 
-- Create date: 26.04.2012 
-- Last modified: 26.04.2012 
-- Description: Überprüfen ob string ein MD5-Hash ist 
-- ======================================================================== 

-- PRE: varchar(50) 
-- POST: True/False 
-- PRINT dbo.[fn_IsMd5Hash]('66B9E31D4C59D3802279515F9B1B6222') 
CREATE FUNCTION [dbo].fn_IsMd5Hash(@strInputAnything varchar(50)) 
    RETURNS bit 
AS 
BEGIN 
    DECLARE @bIsMd5Hash AS bit 

    SET @bIsMd5Hash = 'false' 

    IF LEN(@strInputAnything) = 32 AND NOT @strInputAnything LIKE '%[^0-9ABCDEF]%' COLLATE Latin1_General_CS_AS 
     SET @bIsMd5Hash = 'true' 

    RETURN @bIsMd5Hash 
END 


GO 
+0

Вам также нужно обрабатывать 'NULL'. он возвращает true. (+1 в любом случае) – zig

+0

@zig: Если strInputAnything равно NULL, он возвращает false. Что вы имеете в виду ? –

+0

Извините. ты прав. мой тест был неправильным. Я протестировал первое опубликованное вами выражение, а не функцию. – zig

Смежные вопросы