首页 > 解决方案 > 列中的特殊字符数

问题描述

我有一张表,其中列出了所有可能组合(特殊字符、数字等)的密码。我想提取所有超过 5 个特殊字符的密码列表。

在这个查询上需要一些帮助

Select Password from Login where Password like `%[a-zA-Z0-9]%` and Len(`%[a-zA-Z0-9]%`) >=5

标签: sqlsql-servertsql

解决方案


警告:您的问题表明您将密码作为纯文本存储在数据库中。
这是一个重大的安全隐患。密码应该存储为salted hash,而不是加密,并且永远不要作为纯文本(感谢 Sebastian Brosch 注意到这一点)。

话虽如此,这是您问题的答案:

一种方法是将字符串分解为单个字符,然后简单地使用以下命令进行查询count

DECLARE @str nvarchar(30) = 'shS46@($8jr4';
With N10 AS
(
    SELECT N
    FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9))V(N)
), Tally AS
(
    SELECT TOP(LEN(@str)) ROW_NUMBER() OVER(ORDER BY @@SPID) As N
    FROM N10 ten
    CROSS JOIN N10 hundred 
    -- Passwords are usually 10-20 chars max length. 
    -- If you need more you can add another cross join to get 1000.
), Chars AS
(
    SELECT SUBSTRING(@str, N, 1) As C
    FROM Tally
)

SELECT COUNT(*)
FROM Chars
WHERE C NOT LIKE '%[A-Za-z0-9]%'

当然,如果您已经有一个计数表,则不需要即时创建计数 cte:

With Chars AS
(
    SELECT SUBSTRING(@str, N, 1) As C
    FROM Tally
    WHERE N <= LEN(@str)
)

SELECT COUNT(*)
FROM Chars
WHERE C NOT LIKE '%[A-Za-z0-9]%'

以及使用带有密码列的登录表的完整版本:(以及填充即时计数 cte 的另一种方法)

CREATE TABLE Login
(
    Password nvarchar(20)
);

INSERT INTO Login (Password) VALUES
('n9$%^Usj4jjr'),
('Nehj47$%^$'),
('MNAtokay543^A36#$^#%'),
('(*&^#$^dfh$%&'),
('$%^h345nfs54y');



With Tally AS 
(
    SELECT TOP 20 ROW_NUMBER() OVER(ORDER BY @@SPID) As N
    FROM sys.objects

), Chars AS
(
    SELECT Password, SUBSTRING(Password, N, 1) As C
    FROM Login
    CROSS JOIN Tally 
    WHERE N <= LEN(Password)
)

SELECT Password
FROM Chars
GROUP BY Password
HAVING COUNT(CASE WHEN C NOT LIKE '%[A-Za-z0-9]%' THEN 1 END) > 5

结果:

Password
(*&^#$^dfh$%&
MNAtokay543^A36#$^#%

推荐阅读