【问题标题】:"Could not convert variant of type (Null) into type (OleStr)" when using numbers in SQL query在 SQL 查询中使用数字时,“无法将类型 (Null) 的变体转换为类型 (OleStr)”
【发布时间】:2014-08-20 15:23:15
【问题描述】:

我正在尝试使用 SQL 检查数据库 (Access) 中是否存在特定用户名。如果我只使用字母或字符串字符,则代码可以正常工作,但是当我使用下面示例中的数字时,即使我将它们作为字符串插入,我也会收到错误:

“无法将类型(Null)的变体转换为类型(OleStr)”

  DataModule.Query.Active := False;
  sQuery := 'SELECT * FROM Login WHERE Username = "31"';
  DataModule.Query.SQL.Text := sQuery;
  DataModule.Query.Active := True;

我不知道我做错了什么。

编辑:

调试器在以下代码中的 if 行之后给出错误

 if UpperCase(DataModule.Query['Username']) = sUsername then
  begin
    if DataModule.Query['Password'] = sPassword then
    begin
      bPass := True;
    end

[已解决]

感谢大家的建议,我让它工作了!

【问题讨论】:

  • 使用参数化查询!这就是他们的目的。作为替代使用单引号。
  • Uwe Raabe 所说的。但请在您的代码中准确显示错误发生的位置。
  • 我更改了我的主要帖子以显示错误发生的位置
  • 确保在读取任何值之前检查 BOF/EOF,并在比较值之前检查 NULL 值。但是,当查询已经为您进行了比较时,您为什么还要手动比较用户名呢?为什么不把密码也放在查询中呢?您还应该考虑使用COUNT() 而不是*,除非您计划从找到的记录中读取其他值。查询您不会使用的值是一种浪费。
  • 我不知道Query是哪个组件类型,但您可能想试试:Query.FieldByName('Username').AsString。这将消除 NULL 问题。在实际测试字段之前检查Query.IsEmpty 也是一个好主意。

标签: sql database delphi


【解决方案1】:

您应该使用Query.FieldByName('Password').AsString(与用户名字段相同)来消除任何 NULL 问题。 .AsString 将 db NULL 转换为 Delphi 空字符串 ''

打开查询后,您需要在实际测试用户名/密码逻辑之前测试是否有任何记录。

注意:您不需要再次检查用户名,因为如果查询返回的结果匹配并且该用户存在于您的表中:

bPass := False;
if not DataModule.Query.IsEmpty then
  if DataModule.Query.FieldByName('Password').AsString = sPassword then
    begin
      bPass := True;
    end

如前所述,您最好使用参数化查询。或者至少使用QuotedStr 来避免SQL 注入。例如:

sQuery := 'SELECT * FROM Login WHERE Username = ' + QuotedStr('31');

参数化查询应如下所示:

sQuery := 'SELECT * FROM Login WHERE Username = :Username';
DataModule.Query.SQL.Text := sQuery;
DataModule.Query.ParamByName('Username').Value := '31';

【讨论】:

  • SELECT * FROM Login WHERE UserName = :UserName AND Password = :Password 以及随后检查数据集记录计数也是一个选项。
  • @TLama:没有记录计数。坏的! :-) 使用IsEmpty,它不需要检索所有数据,因此速度更快(并且养成更好的习惯)。
  • @TLama,关于检查UserName AND Password,然后检查记录集是否不为空的选项是正确的。 但是这取决于您需要向最终用户显示的提示。例如您可能想告诉他UserName 不存在。后来告诉他密码不正确。如果您在单个查询中同时检查 UserName AND Password,您将无法知道 为什么 用户在记录集为空的情况下无法登录。我个人会使用 SP 并返回一个状态,但这超出了这个范围。
  • 如果您将加密的密码存储在数据库中,并且解密逻辑在客户端中,则 OP 的方法也很有用。但通常您只会存储密码哈希(例如 MD5)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多