delphi - Delphi XE7中的登录程序给出错误: Parameter object is improperly defined.提供的信息不一致或不完整

标签 delphi

我在 Delphi 中编写的一个简单且基本的程序遇到以下问题。它是一个登录程序,用户在其中输入用户名和密码。然后,程序将从访问数据库获取密码,其中用户名等于用户输入的用户名。然后程序将从access数据库获取的密码与用户输入的密码进行比较。

这是我的代码的副本:

(我有以下变量:密码、用户名、sPassword)

Username := edtUsername.Text;
Password := edtPassword.Text;

UserQuery.SQL.Add('Select Password as Password1 from Users where Username = :Username');
UserQuery.Parameters.ParamByName('Username').Value := Username;
UserQuery.Open;

sPassword := UserQuery['Password1'];
if sPassword = Password then
begin
  showmessage('Correct');
end
else
begin
  showmessage('Incorrect');
end;

它将查询值保存到变量中。如果用户名正确并且用户输入的密码正确,则程序可以正常运行。 我的问题是,第二次或者如果用户输入了错误的用户名或密码之类的内容,则会出现错误:参数对象定义不正确。提供的信息不一致或不完整。我认为它必须检查查询是否存在,但我不知道该怎么做。我该如何解决这个问题?

(我还是个学习者)

最佳答案

问题是,每次执行方法时,都会在查询中添加 SQL 语句。如果您在调试时检查其值,或者只是 ShowMessage(UserQuery.SQL.Text) 您会清楚地看到它

它看起来像这样:

Select Password as Password1 from Users where Username = :Username
Select Password as Password1 from Users where Username = :Username
Select Password as Password1 from Users where Username = :Username
...

查询失败,因为从第二个到最后一个 :Username 参数没有提供任何值

有几种方法可以解决这个问题。其中之一可能涉及清除查询,然后再次分配 SQL 语句:

UserQuery.Clear; // clear the query before adding the SQL statement 
UserQuery.SQL.Add('Select Password as Password1 from Users where Username = :Username');
UserQuery.Parameters.ParamByName('Username').Value := Username;
UserQuery.Open;

或者您可以直接分配给 Text 属性,该属性将用新提供的值替换整个字符串:

UserQuery.SQL.Text := 'Select Password as Password1 from Users where Username = :Username';
UserQuery.Parameters.ParamByName('Username').Value := Username;
UserQuery.Open;

由于您一遍又一遍地使用相同的查询,最理想的设置是初始化它(例如在构造函数上)并将其保持在准备状态。准备好的 SQL 语句被准备好并发送给数据库引擎,使其准备好执行。当您需要反复执行查询或命令并且唯一更改的是参数值(只是您的情况)时,应该使用它

procedure TForm1.Create(Sender: TObject);
begin
    UserQuery.SQL.Text := 'Select Password as Password1 from Users where Username = :Username';
    // it's a good practice to set the parameter type
    UserQuery.Parameters.ParamByName('Username').DataType := ftString;
    // prepares the query: preparses sql, sends it to the DB engine, etc
    UserQuery.Prepared := True;
end;

// usage
procedure TForm1.YourLoginMethod;
begin
    UserQuery.Parameters.ParamByName('Username').Value := Username;
    UserQuery.Open;
    try
      sPassword := UserQuery.FieldByName('Password1').AsString;
      // perform login logic
    finally
      UserQuery.Close;
    end;  
end;

还有几件事需要注意。我建议,与设置参数 DataType 类似,您使用类型安全的 TField 属性,又名 .AsString.AsInteger

TDataSet默认属性将为给定字段值返回一个Variant,并执行隐式转换。我建议明确一些,因为您比 RTL 更了解您的数据类型

这里还需要一个 try-finally block 。使用准备好的查询时,每次执行它们时,都需要有一个关闭查询,设置参数,然后调用 open。 try-finally 将允许每次打开查询时,无论可能发生什么情况,查询都会关闭

关于delphi - Delphi XE7中的登录程序给出错误: Parameter object is improperly defined.提供的信息不一致或不完整,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38308617/

相关文章:

arrays - 设置数组(记录)长度时,Delphi 堆栈溢出和访问冲突错误

delphi - 绕过函数 "out"参数

Delphi Word自动化: how to insert text after a table?

delphi - 来自 DLL 的 Application.handle

delphi - 为什么将 varEmpty 与零评估的 varInteger 进行比较时 "="运算符结果为 True?

python - 我应该如何将 Python 嵌入到 C++ Builder/Delphi 2010 应用程序中?

delphi - Firemonkey 和 Android 64 位要求

Delphi:在数据感知控件中显示数据集的子集

delphi - 如何使用 DragType dtOLE 将节点从 TVirtualStringTree 拖放到 VCL 控件中?

delphi - 为什么 Delphi 在将 ShortString 分配给字符串时会发出警告?