【问题标题】:SQl select statement whitespace issueSQL 选择语句空白问题
【发布时间】:2015-09-14 07:03:30
【问题描述】:

SQL 中的值是 USERNAME=ADMIN PASSWORD=ADMIN

SELECT * FROM TBL_USER 
WHERE USERNAME='ADMIN' 
AND PASSWORD COLLATE LATIN1_GENERAL_CS_AS=N'ADMIN'

上述查询工作正常。

2) 如果我在密码前添加一个空格。

SELECT * FROM TBL_USER 
WHERE USERNAME='ADMIN' 
AND PASSWORD COLLATE LATIN1_GENERAL_CS_AS=N'   ADMIN'

这也是正确的,因为它返回了一条提示密码错误的消息。

3) 如果我在密码末尾添加一个空格:

SELECT * FROM TBL_USER 
WHERE USERNAME='ADMIN' 
AND PASSWORD COLLATE LATIN1_GENERAL_CS_AS=N'ADMIN '

这个查询应该失败,但它没有检索数据。

任何人都可以帮我解决这个问题。第三个条件应该失败,因为表中的值是“admin”并且提供的值是“admin”(末尾有空格)。

【问题讨论】:

  • N'ADMIN' ?您使用的是什么 DBMS?
  • 我正在使用 Sql。 'N' 用于 nvarchar 类型列。
  • “SQL”不是 DBMS 产品,它是一种查询语言。

标签: sql sql-server


【解决方案1】:

不要使用 = 运算符,而是使用 LIKE(不带 % 通配符)

SELECT * FROM TBL_USER WHERE USERNAME='ADMIN' 
AND PASSWORD COLLATE LATIN1_GENERAL_CS_AS LIKE N'ADMIN '

原因如下:SQL WHERE clause matching values with trailing spaces

【讨论】:

  • 对于这个特定的场景,like 可以很好地工作。但是,假设存储的密码是 thisismysupersecurepassword 并且有人输入了 % 的密码值 - 这个解决方案将会非常失败。
  • @Barry 感谢您指出这一点。再次通过您的建议。如果输入了“12345”,认为 DATALENGTH 也会失败。似乎没有完美的解决方案来处理这种情况,除了在 GUI 端设置“不允许空格”密码策略。
【解决方案2】:

这是预期的behaviour of trailing spaces

SQL Server 遵循 ANSI/ISO SQL-92 规范(第 8.2 节, , 一般规则 #3) 关于如何比较字符串 带空格。 ANSI 标准要求对字符进行填充 比较中使用的字符串,以便它们的长度在之前匹配 比较它们。填充直接影响 WHERE 的语义 和 HAVING 子句谓词和其他 Transact-SQL 字符串 比较。例如,Transact-SQL 考虑字符串 'abc' 和 'abc' 对于大多数比较操作来说是等价的。

此规则的唯一例外是 LIKE 谓词。当对 LIKE 谓词表达式的一侧具有一个带有尾随的值 空格,SQL Server 不会将两个值填充到相同的长度 在比较发生之前。因为LIKE的目的 根据定义,谓词是为了促进模式搜索而不是 比简单的字符串相等测试,这不违反该部分 前面提到的 ANSI SQL-92 规范。

我建议您在 where 子句中添加另一个条件:

And DATALENGTH(Password) = DATALENGTH(N'ADMIN ')

这将添加另一个检查以确保输入值长度与数据库值相同。

完整示例:

Declare @tblUser table
(
Username nvarchar(50),
Password nvarchar(50)
)
Insert into @tblUser
Values (N'ADMIN',N'ADMIN')


select *
From @tblUser
Where Username = N'ADMIN'
And Password Collate LATIN1_GENERAL_CS_AS = N'ADMIN'

select *
From @tblUser
Where Username = N'ADMIN'
And Password Collate LATIN1_GENERAL_CS_AS = N' ADMIN'

select *
From @tblUser
Where Username = N'ADMIN'
And Password Collate LATIN1_GENERAL_CS_AS = N'ADMIN '
And DATALENGTH(Password) = DATALENGTH(N'ADMIN ')

【讨论】:

  • 为什么不简单地使用 LIKE 运算符。看我的回答。
【解决方案3】:

这对你有用

SELECT * FROM TBL_USER 
WHERE USERNAME='ADMIN' AND PASSWORD COLLATE LATIN1_GENERAL_CS_AS=N'ADMIN ' And LEN(PASSWORD) = LEN(Replace('admin ', ' ' , '_'))

因为如果用户在密码末尾使用空格会失败。

【讨论】:

    【解决方案4】:

    你可以使用修剪功能

    SELECT * FROM TBL_USER WHERE USERNAME=trim('ADMIN') AND PASSWORD COLLATE LATIN1_GENERAL_CS_AS=N trim('ADMIN')
    

    【讨论】:

    • 有修整功能吗?因为我允许用户在前面有 whitesapces 作为密码。
    • 如果您允许 whitesapces 给用户,那么您可以直接检查是否完全匹配
    • 如上所述,第三次查询应该失败,因为sql表中“admin”后面没有空格。但第三个查询检索它。
    • IMO 修整或长度检查不起作用。如果用户在注册时故意在密码中添加了空格后缀怎么办? (我知道这是一个边界条件,大多数网站仍然不允许这样的密码!)。
    【解决方案5】:

    您可以在支票上做正确的修剪。

    SELECT * FROM TBL_USER 
    WHERE USERNAME='ADMIN' AND PASSWORD COLLATE LATIN1_GENERAL_CS_AS=RTRIM(N'ADMIN ')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-10
      • 1970-01-01
      • 2015-03-28
      • 1970-01-01
      • 2011-04-17
      • 2011-06-09
      • 1970-01-01
      相关资源
      最近更新 更多