Delphi:“参数对象定义不正确。提供的信息不一致或不完整。“

时间:2009-08-21 13:40:04

标签: delphi parameters ado

这是一个执行以下操作的函数:

  
      
  • 创建一个长度为8的随机令牌
  •   
  • 将该令牌插入数据库
  •   
  •     

    如果用户已有令牌,请更新它。

      
  •   
  •     

    如果用户没有令牌,请将其插入。

      
  •   
procedure createToken(BenuNr: integer);
var
  AQ_Query:       TADOQuery;
  strToken:       string;
  intZaehler:     integer;
  const cCharSet: string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
begin
    //Random String as Token
    SetLength(strToken, 8);
  for intZaehler := 1 to 8 do
  begin
    strToken[intZaehler] := cCharSet[1+Random(Length(cCharSet))];
  end;
  //Inserts the Token into the Database
  with AQ_Query do
  begin
    try
      AQ_Query := TADOQuery.Create(nil);
      ConnectionString := strConnectionString;
      SQL.Text := 'if EXISTS(select * from TOKN where BENU_NR = :paramBenu_NR) begin update TOKN set TOKEN = :paramTOKEN where BENU_NR = :paramBenu_NR end else insert into TOKN (BENU_NR, TOKEN) values (:paramBENU_NR,:paramTOKEN)';
      Prepared := true;
      Parameters.ParamByName('paramBENU_NR').DataType := ftInteger;
      Parameters.ParamByName('paramTOKEN').DataType := ftString;
      Parameters.ParamByName('paramBENU_NR').Value := BenuNr;
      Parameters.ParamByName('paramTOKEN').Value := strToken;
      ExecSQL;    //<< Exception as stated in the title
    finally
      Free;
    end;
  end;
end;

执行此操作会抛出标题中所述的异常。我把上面的例子放下来瞧瞧:没有例外。不幸的是我不明白为什么?

procedure createToken();
var
  AQ_Query:     TADOQuery;
  strToken:     string;
  intZaehler:      integer;
  const cCharSet:  string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
begin
    //Random String as Token
    SetLength(strToken, 8);
  for intZaehler := 1 to 8 do
  begin
    strToken[intZaehler] := cCharSet[1+Random(Length(cCharSet))];
  end;
  //Inserts the Token into the Database
  with AQ_Query do
  begin
    try
      AQ_Query := TADOQuery.Create(nil);
      ConnectionString := strConnectionString;
      SQL.Text := 'update TOKN set TOKEN = :paramTOKEN where BENU_NR = 1';
      Prepared := true;
      Parameters.ParamByName('paramTOKEN').DataType := ftString;
      Parameters.ParamByName('paramTOKEN').Value := strToken;
      ExecSQL;   //<< No more exception
    finally
      Free;
    end;
  end;
end;

似乎每个SQL只允许1个参数。我正在使用Delphi 7和MSSQL Server 2005

知道如何修复第一个代码块以使其正常工作吗?

8 个答案:

答案 0 :(得分:11)

要完成这项工作,您必须在SQL子句中仅使用每个参数一次。要多次使用相同的参数,只需使用新名称声明它。我不知道为什么会这样,但我知道这可能很烦人。

答案 1 :(得分:2)

我有机会尝试使用编译器:)我必须在家中安装一个。

虽然我仍然发现你使用WITH异常,但它似乎确实有效。

我已经看到了你在几种情况下得到的错误:

  1. 尝试运行多个查询 立即反对连接(由于线程或计时器+ processMessages)
  2. 当ProcedureName不正确时使用TADOStoredProc
  3. 有时,如果ADO无法解析查询 - 无法在没有数据库架构的情况下对此进行测试。
  4. 请注意,SQL Server中无需显式定义参数类型。这些由附加到SQL TStringList对象的OnChanged事件自动分配。

    因此,最好分配SQL.Text属性(就像你一样),或者如果使用.Add('SELECT ...'),则使用SQL.BeginUpdate / SQL.EndUpdate对。 / p>

    原始回复:

      with AQ_Query do
      begin
        try
          AQ_Query := TADOQuery.Create(nil);
          ConnectionString := strConnectionString;
    

    虽然这似乎有效但在实例化之前引用对象似乎有点奇怪。

    AQ_Query应该在with语句之前实例化:

      AQ_Query := TADOQuery.Create(nil);
      with AQ_Query do
      begin
        try
          ConnectionString := strConnectionString;
    

    最好不要使用WITH - 这是在寻找麻烦。

    另请注意,对象创建应该在尝试之前进行。最后。如上所述,您将收到编译器警告。不要忽略这些 - 它们可以帮助你编写更好的代码。

答案 2 :(得分:1)

虽然此错误具有挑战性,但您可以对其进行足够的诊断,以确定您的查询是否有效。问题出在您的参数中。找到真正问题的最佳方法是让SQL Server Profiler在查询进入时跟踪数据库。它将向您展示如何解释参数。将该查询复制到文本编辑器中以查看问题所在。

如果您无法使用SQL Server Profiler,您只需将值“BenuNr”和“strToken”输出到屏幕或控制台,这样您就可以真正看到传入的内容作为参数。

答案 3 :(得分:1)

到现在为止,我没有解决问题。

但我想这个问题存在于参数内部以及如何访问它们。编译器通过索引选择它们,而不是按照我的假设选择名称。

仔细查看OI中的TADOQuery组件(特别是在TParameters部分),您可以看到索引。

最后,它首先是一个问题,添加一个参数,为它指定一个名称,然后插入一个值,或类似的东西。

答案 4 :(得分:1)

关闭准备工作。在ADO组件上设置prepared = False。服务器似乎在两个参数都存在之前就已经看到它,并准备(编译)它。当您使用两个参数执行它时,参数列表与准备好的语句不匹配。

答案 5 :(得分:0)

哎哟。你刚刚看到我们的工作系统架构师称之为“有史以来最严重的错误”。这是一个非常普遍的错误,可能意味着各种各样的事情。但我只是在INSERT语句中看过它,所以试试看那里。这是由ADO以某种方式与数据库模式不匹配的定义引起的。

尝试减少查询以仅执行插入操作并使用SQL Management Studio附带的SQL事件探查器来查看ADO在触发时正在执行的操作。它很可能会询问你的表的结构,将它与你的语句的结构进行比较,最终不喜欢它发现的内容,并且从不实际将INSERT命令发送到数据库。

确保您在字段上拥有正确的数据类型,并且只需使用这两个值就可以成功地将INSERT运行到该表中。这可能不起作用 - 这个有史以来最糟糕的错误 - 但它应该给你一个起点。

答案 6 :(得分:0)

您无需指定DataType。成功调用Prepare;后,应根据服务器表定义正确配置参数。

我的猜测是,通过分配DataType,参数可能会重置并且缺少某些信息,例如,ParamType应为ptInput,但会重置为ptUnknown或类似的东西。

尝试删除设置DataType的行,看看它是否有帮助。

答案 7 :(得分:0)

对我来说,这个错误没有参数,当(否则完全有效)SQL语句包含一个varchar文字值,并且在引用的子文本中包含冒号(:)。 E.g。

UPDATE ... SET myfield = 'foo " :bar "'

解决方案可以是从丑陋的嵌入文字切换到参数。我还没有找到其他正确的解决方法。