如何向TADOQuery传递字符串参数?

3

使用Delphi 2010

有人能告诉我我的代码哪里出了问题吗?注释显示了我尝试向ADOQuery传递参数时遇到的错误。

procedure CreateAdminLogin(const APasswd: string);
var
  qry: TADOQuery;
  //P1, P2: TParameter;
begin
  qry := TADOQuery.Create(nil);
  try
    qry.Connection := frmDataModule.conMain;
    qry.SQL.Text := 'INSERT INTO Users (User_Id, Password) VALUES (:u, :p)';

    //Syntax error in INTO statement
    qry.Parameters.ParamByName('u').Value:= 'Admin';
    qry.Parameters.ParamByName('p').Value:= GetMd5(APasswd);


    //invalid variant operation
    {qry.Parameters.ParamByName('u').Value.AsString:= 'Admin';
    qry.Parameters.ParamByName('p').Value.AsString:= GetMd5(APasswd);}

    //invalid variant operation
    {P1:= qry.Parameters.ParamByName('u');
    P1.Value.asString:= 'Admin';
    P2:= qry.Parameters.ParamByName('p');
    P2.Value.asString:= GetMd5(APasswd);}


    qry.Prepared := True;
    qry.ExecSQL;
  finally
    qry.Free;
  end;

end;

注意:GetMD5的声明如下
function GetMd5(const Value: String): string;
var
  hash: MessageDigest_5.IMD5;
  fingerprint: string;
begin
  hash := MessageDigest_5.GetMd5();
  hash.Update(Value);
  fingerprint := hash.AsString();
  Result := fingerprint;
end;

Thankx


2
没有参数的插入操作能够正常工作吗? - jachguate
好的,你必须先解决这个问题。由于你的语法看起来不错,这肯定取决于你连接的数据库引擎。一旦你能够成功执行没有参数的语句,你就可以开始添加参数了。 - jachguate
我的应用程序中的其他SQL都正常工作,所以我不认为存在数据库问题。我说不认为是因为这是我尝试进行的第一个插入操作。其他操作都是选择查询。用户表中有一个ID字段,但它是自增的。在我的插入操作中,我需要做些什么吗? - Blow ThemUp
我在想你的"user_id"字段是否实际上不是整数类型。而你正在尝试将字符串插入其中。 - Riho
@Riho - 不,这三个字段(ID-整数(自动增量),User_id-字符串,密码-字符串) - Blow ThemUp
显示剩余6条评论
3个回答

9

这对我来说很好用,使用了Delphi附带的DBDemos.MDB文件(C:\Users\Public\Documents\RAD Studio\9.0\Samples\Data\dbdemos.mdb是默认安装路径)

ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('INSERT INTO Country (Name, Capital, Continent, Area, Population)');
ADOQuery1.SQL.Add('VALUES (:Name, :Capital, :Continent, :Area, :Population)');

ADOQuery1.Parameters.ParamByName('Name').Value := 'SomePlace';
ADOQuery1.Parameters.ParamByName('Capital').Value := 'Pitsville';
ADOQuery1.Parameters.ParamByName('Continent').Value := 'Floating';
ADOQuery1.Parameters.ParamByName('Area').Value := 1234;
ADOQuery1.Parameters.ParamByName('Population').Value := 56;
ADOQuery1.ExecSQL;
ADOQuery1.Close;

// Open it to read the data back
ADOQuery1.SQL.Text := 'SELECT * FROM Country WHERE Name = :Name';
ADOQuery1.Parameters.ParamByName('Name').Value := 'SomePlace';
ADOQuery1.Open;
ShowMessage(ADOQuery1.FieldByName('Name').AsString);

对于那些可能被误导的人,需要澄清的是,TADOQueryExecSQL 方法不会使组件处于 Active = True 状态,因此本答案中第一个 Close 调用(即在 ExecSQL 后面的那个)是不必要的,尽管无害。 - Andriy M

0

关于使用like的额外注意事项:

数据源SQL如下所示

select * from Table where Phone like :param

DataModule.findQuery.Parameters.ParamByName('param').Value:= '%%'+yourEdit.Text + '%%';

-1

你应该先创建参数:

procedure CreateAdminLogin(const APasswd: string);
var
  qry: TADOQuery;
begin
  qry := TADOQuery.Create(nil);
  try

   // this part is missed in your code
   with qry.Parameters.AddParameter do
    begin
      Name := 'u';
      DataType := ftString;
    end;
    with qry.Parameters.AddParameter do
    begin
      Name := 'p';
      DataType := ftString;
    end;

    qry.Connection := frmDataModule.conMain;
    qry.SQL.Text := 'INSERT INTO Users (User_Id, Password) VALUES (:u, :p)';

    // Now it will be ok!
    qry.Parameters.ParamByName('u').Value:= 'Admin';
    qry.Parameters.ParamByName('p').Value:= GetMd5(APasswd);

    qry.Prepared := True;
    qry.ExecSQL;
  finally
    qry.Free;
  end;
end;

2
你不必这样做;看我的答案。(除非你计划多次使用查询,否则也不必先准备好。) - Ken White
2Ken White:你的例子对我不起作用。我猜你是从某个项目中复制了参数创建的示例。我只是在原始代码中添加了所需的部分,使其能够工作。 - Andrei Galatyn
我的示例很好用,无论是有或没有GUI,都可以使用我在答案中发布的确切代码。除了将ADOQuery1拖放到表单上并设置ConnectionString之外,在IDE中没有定义任何内容。没有添加SQL,没有参数,没有特殊设置,只有我发布的代码中的内容。如果它对你不起作用,那么你做错了什么。 :-) 在发布之前,我在D2007和Delphi XE中进行了测试。 - Ken White
@user2106715 - 不好意思,你的示例没有起作用。我仍然得到相同的错误。 - Blow ThemUp
如果您只提供查询文本,则参数将根据您的查询自动创建。因此,您所要做的就是正确使用查询中的参数(例如“select * from A where field1 = :p1”),然后可以按名称(使用:)或按索引(使用?)引用参数。 因此,请确保您不要执行Params.Clear(或Parameters.Clear),并确保ParamCheck为true。 - MelOS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接