列中特殊字符的计数

时间:2019-05-02 05:46:03

标签: sql sql-server tsql

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

此查询需要帮助

PandasProfiling

4 个答案:

答案 0 :(得分:1)

警告::您的问题表明您将密码作为纯文本存储在数据库中。
这是主要安全风险 。密码应存储为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#$^#%

答案 1 :(得分:0)

由于您的问题是如何计算列中的特殊字符?,并且您没有提供正在使用的版本,因此可以使用 TRANSLATE() REPLICATE() REPLACE() 的功能

CREATE TABLE [Login](
  [Password] VARCHAR(45)
);

INSERT INTO [Login] VALUES
('Password'),
('abc@def'),
('a@b@c_d_e/f'),
('Normal');

DECLARE @SC VARCHAR(3) = '@_/';

WITH CTE AS
(
  SELECT *, REPLACE(TRANSLATE([Password], @SC, REPLICATE(' ', LEN(@SC))), ' ', '') Result
  FROM [Login] 
)
SELECT SUM(LEN([Password]) - LEN(Result)) Cnt
FROM CTE;

返回:

+-----+
| Cnt |
+-----+
|   6 |
+-----+

这里是 db<>fiddle

这也是另一种方式

CREATE TABLE [Login](
  [Password] VARCHAR(45)
);

INSERT INTO [Login] VALUES
('Password'),
('abc@def'),
('a@b@c_d_e/f'),
('Normal Words');

WITH Chars AS
(
  SELECT SUBSTRING([Password], Number + 1, 1) Chr
  FROM [Login] CROSS JOIN master..spt_values
  WHERE [Type] = 'P'
)
SELECT COUNT(1) Cnt
FROM Chars
WHERE Chr NOT LIKE '%[A-Za-z0-9]%' AND Chr <> '';

Demo

更新:

  

我想提取包含5个以上特殊字符的所有密码的列表。

CREATE TABLE [Login](
  [Password] VARCHAR(45)
);

INSERT INTO [Login] VALUES
('Password'),
('abc@def'),
('a@b@c_d_e/f$'),
('Normal Words'),
('My_$P@$$word_/');

DECLARE @SC VARCHAR(3) = '$@_/'; --It's just an example
SELECT *
FROM [Login]
WHERE LEN([Password]) - LEN(REPLACE(
                                   TRANSLATE([Password], 
                                             @SC, 
                                             REPLICATE(CHAR(9), LEN(@SC))
                                            ),
                                   CHAR(9), '')) >= 5;

Demo

答案 2 :(得分:0)

根据您的问题,我了解到您在此将nonalphanumberic字符称为特殊字符。如果是这样,您可以通过两种方式实现它。

1)如果您知道列中可能出现的所有特殊字符列表,并且没有权限创建function

SELECT * from test 
WHERE (len(COL)- len(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
       REPLACE(REPLACE(REPLACE(REPLACE(col,
        '!',''),'@',''),'#',''),'$',''),'%',''),
        '^',''),'&',''),'*',''),' ','')) ) >=5;

2)如果可以创建function

Create Function [dbo].[RemoveNonAlphaCharacters](@Temp VarChar(1000))
Returns VarChar(1000)
AS
Begin

    Declare @KeepValues as varchar(50)
    Set @KeepValues = '%[^a-Z0-9]%'
    While PatIndex(@KeepValues, @Temp) > 0
        Set @Temp = Stuff(@Temp, PatIndex(@KeepValues, @Temp), 1, '')

    Return @Temp
End

然后是select。感谢G Mastros提供上述功能

Select * from test where (len(col) - len(dbo.RemoveNonAlphaCharacters(col))) > =5;

DB FIDDLE

答案 3 :(得分:0)

使用NGrams8K,您可以轻松执行以下操作:

ID          SpecialChars
----------- ------------
3           6
4           10

返回:

{{1}}