尝试从 pascal 执行查询时出现异常

Exception when trying to execute a query from pascal

以下函数从网格中获取 cuits(cuit 类似于社会安全号码)并将它们插入临时 table。我正在使用 Delphi XE7 和 Firebird 2.5。

function TfImportFileARBARetenPercep.fxListClientFromGrid(
      pboClient: Boolean): WideString;
var
   wsAux : WideString;
   stTable, stCuit: String;
   qCliProv, qCuitsExcl, qCuit : TFXQuery;
   niRow : Integer;
begin
  wsAux := '';

  qCuitsExcl.SQL.Text := 'Create global temporary table TempExcl (cuitExcl varchar(13)) on commit delete rows';
  qCuitsExcl.ExecSQL;

  if pboClient then
  begin
    stTable := 'Client'
  end
  else
  begin
    stTable := 'Prov';

  end;
  for niRow := 1 to gDetails.RowCount - 1 do
    if Trim(gDetails.Cells[3,niRow]) <> '' then
    Begin
      stCuit := QuotedStr(Trim(gDetails.Cells[3,niRow]));
      qCuit.SQL.Text := 'Insert into TempExcl(:cuitExcl)';
      qCuit.ParamByName('cuitExcl').AsString := stCuit;
      qCuit.ExecSQL;//←←←←←←←←←←←←←←←←this line throws the exception
    End;

  qCuitsExcl.SQL.Text :='';
  qCuitsExcl.SQL.Text := 'commit;';//to commit previous inserts
  qCuitsExcl.SQL.Add('drop table TempExcl;');//in case the table is not deleted when the connection is closed
  qCuitsExcl.SQL.Add('commit;');//commit previous drop
  qCuitsExcl.ExecSQL;

//the rest of the code only returns the list of cuits that were loaded 
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

  try
    qCliProv.SQL.Text :=
      ' Select Code' +
      '   From ' + stTable +
      '  Where Active = 1 ';

    if gDetails.RowCount  > 0 then
      begin
        qCliProv.SQL.Add('And Cuit Not In (Select cuitExcl from TempExcl)');
      end;

    qCliProv.Open;

    wsAux := '';

    while not qCliProv.Eof do
    begin
      wsAux := wsAux + iif((wsAux = ''), '', ',') + qCliProv.FieldByName('Code').AsString;
      qCliProv.Next;
    end;

    Result := wsAux;
  finally
    FreeAndNil(qCliProv);
    FreeAndNil(qCuit);
    FreeAndNil(qCuitsExcluidos);
  end;
end;

尝试执行行 qCuit.ExecSQL; 时抛出以下异常:

Project ERP.exe raised exception class EIBNativeException with message '[FireDAC][Phys][FB] Dynamic SQL Error SQL error code = -104 Token unknown - line 1, column 27 ?'.

不知道为什么会抛出这个异常

问题是这是错误的:

qCuit.SQL.Text := 'Insert into TempExcl(:cuitExcl)';

这将生成一个查询:

Insert into TempExcl(?)

这是一个语法错误(“Token unknown”),因为 Firebird 不希望这个位置有问号(参数占位符),它需要标识符(列名).

一个有效的查询是:

Insert into TempExcl (cuitExcl) values (?)

或:

Insert into TempExcl values (?)

首选第一种形式,因为您明确指定了列,但在这种情况下并不是真正必要的,因为 table 无论如何都有一列。

换句话说,你需要使用:

qCuit.SQL.Text := 'Insert into TempExcl (cuitExcl) values (:cuitExcl)';

顺便说一句,我不熟悉 Delphi 或准备查询的方式和时间,但最好将此语句移出循环,因此它只准备一次(在每当 qCuit.SQL.Text 被赋值时,case Delphi 都会再次准备语句。

评论"//万一关闭连接时table没有被删除"似乎表示对Global Temporary Tables的理解不足.它们旨在成为永久对象,可供您的应用程序重复使用。也就是说,on commit delete rows 使内容仅对您当前的事务可用,而 on commit preserve rows 将使内容对您连接的其余部分(且仅您的连接)可用,并在连接关闭时删除数据。在多次执行的内容中创建和删除 GTT 表明您的设计存在问题。