2012-02-21 78 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