2012-02-21 77 views
2

问题:SQL:比较字符串是否是MD5哈希?

我需要COMPARE如果一个字符串是一个MD5哈希在SQL中。

我发现这个PHP-功能:

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

由于SQL缺乏{32}语法,我只复制[A-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应该区分大小写...

如何在这种IF区分大小写的情况下使LIKE变为大写?

回答

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-Server ... – 2012-02-21 17:05:54

+0

反转(即,匹配*不是* 0-9a-f的任何字符)。所以它会匹配'z'。另外,我刚刚编辑了我的答案,因为LIKE模式需要一些小小的调整:现在它已被包装在'%'匹配中。 – 2012-02-21 17:19:15

+0

啊,现在我明白了。对不起,我的错,我没有看到如果改变了开关。是的,从打字员的角度来看,这更聪明。但它仍然有区分大小写的问题,这是本文的重点。 – 2012-02-21 17:35:20

2

这项工作?

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

大,这个工程(想法明智的)。我用upper代替。但是你错过COLLATE Latin1_General_CS_AS后myValue – 2012-02-21 17:06:41

+1

问题似乎是a-f,如果我用abcdef替换它,那么它工作正常。我认为当天的话是:微软的BUG! – 2012-02-21 18:50:46

1

OK,问题细致检查后,这是最好的解决办法:

注意它来写ABCDEF,而不是A-F的,因为在A和F之间的其他任何字母不区分大小写是很重要的。

(作为AF:注意那个小 'a' 是边界的情况下,因为它不在此范围内,不像小 'B'。)

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 2017-09-11 09:07:15

+0

@zig:如果strInputAnything为NULL,则返回false。你什么意思 ? – 2017-09-11 09:26:48

+0

对不起。你是对的。我的测试不正确。我测试了你发布的第一个表达式,而不是函数。 – zig 2017-09-11 11:05:39