我在 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/