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

发布于 2025-01-07 16:34:50 字数 988 浏览 0 评论 0原文

问题:

我需要比较一个字符串是否是 SQL 中的 MD5 哈希值。

我发现了这个 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 区分大小写?

Question:

I need to COMPARE if a string is a MD5 Hash in SQL.

I found this PHP-function:

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

Since SQL lacks the {32} syntax, I just duplicate [a-f0-9] 32 times:

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 

However, to avoid a possible collision with a username consisting of 32 [a-f], however unlikely, I want to do the like comparison uppercase.

But if for testing purposes I do:

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 

I get yes, and not no.
However COLLATE Latin1_General_CS_AS should make it case-sensitive...

How can a make the LIKE in this IF case-sensitive ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

怪我入戏太深 2025-01-14 16:34:50

最好通过检查任何导致检查失败的单一因素来反转检查并使其更易于维护。这意味着您不必在代码中重复 [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 个字符或者它包含十六进制集之外的字符,那么它会失败。

Better to invert the check and make it simpler to maintain by checking for any single thing that will make it fail. This means you don't have to repeat [0-9a-f] 32 times in the code.

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

i.e., if it's not 32 chars OR it contains a character outside the hexadecimal set then it fails.

转身泪倾城 2025-01-14 16:34:50

这行得通吗?

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

Will this work?

IF myValue LIKE '[a-f0-9][...]' 
and LOWER(myValue) = myValue
半岛未凉 2025-01-14 16:34:50

好的,经过仔细检查问题,这是最好的解决方案:

请注意,重要的是要写 ABCDEF 而不是 AF,因为否则 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-Check 函数:

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

OK, after painstaking examination of the problem, this is the best solution:

Note that it's important to write ABCDEF instead of A-F, because else any letter in between A and F is not case-sensitive.

(as for A-F: note that little 'a' is a border-case, as it isn't in this range, unlike little '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 

And as 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文