【问题标题】:How to debug Array DML FireDAC queries?如何调试 Array DML FireDAC 查询?
【发布时间】:2022-10-21 01:39:47
【问题描述】:

我正在尝试使用 Array DML 将取自逗号分隔文件的值插入到 Interbase SQL DB 中。问题是,我有很多问题

算术、数字溢出或字符串截断

尝试执行 DML 查询时出错,这很可能是由于循环走得太远。

虽然 DML 比使用传统循环并为文件的每一行推送查询要快,但我很难调试,因为我看不到在最后或逐步调试期间推送的查询。

有没有一种方法可以查看正在推送的查询? FDQuery 目前似乎还没有提供这种可能性,所以我很难判断运行时出了什么问题。

使用的 csv 文件可以在here 找到,代码如下:

if FileExists(OpenDialog1.FileName) then
begin
  Strings := TStringList.Create;
  CurrentLine := TStringList.Create;

  try
        Strings.Clear;
        Strings.LoadFromFile(OpenDialog1.FileName);

        iArraySize := Strings.Count;
        FDQuery1.SQL.Text := 'INSERT INTO tbl_post4 (lngpostid, strname, strdesc, ysnisdefault, memLabelList, memNotesText, lnggroupid, ysnisgroup, dtiCreated, dtiModified) VALUES(:p1, :p2, :p3, :p4, :p5, :p6, :p7, :p8, :p9, :p10);';
        FDQuery1.Params.ArraySize := iArraySize;

           for m := 1 to Strings.Count - 1 do   //starting at second line of file since first is used for column names
           begin
              CurrentLine.Clear;
              Split(',', Strings[m], CurrentLine);
              for n := 0 to CurrentLine.Count - 1 do
              begin //  replace empty with space && escape single quotes if found
                    if CurrentLine[n].IsEmpty then
                    begin
                      CurrentLine[n] := ' ';
                    end;
                    if CurrentLine[n].Contains('''') then
                    begin
                      CurrentLine[n] := StringReplace(CurrentLine[n], '''', '''''', [rfReplaceAll, rfIgnoreCase]);
                    end;

              end;

              FDQuery1.Params[0].AsIntegers[m] := CurrentLine[0].ToInteger;
              FDQuery1.Params[1].AsStrings[m] := CurrentLine[1];
              FDQuery1.Params[2].AsStrings[m] := CurrentLine[2];
              FDQuery1.Params[3].AsBooleans[m] := CurrentLine[3].ToBoolean;
              FDQuery1.Params[4].AsStrings[m] := CurrentLine[4];
              FDQuery1.Params[5].AsStrings[m] := CurrentLine[5];
              FDQuery1.Params[6].AsIntegers[m] := CurrentLine[6].ToInteger;
              FDQuery1.Params[7].AsBooleans[m] := CurrentLine[7].ToBoolean;
              FDQuery1.Params[8].Values[m] := CurrentLine[8];
              FDQuery1.Params[9].Values[m] := CurrentLine[9];


           end; //end for m

        FDConnection1.StartTransaction;
        FDQuery1.Execute(FDQuery1.Params.ArraySize);
        FDConnection1.CommitRetaining;
           
        ShowMessage('Data imported');
        CurrentLine.Free;
        Strings.Free;
  except
     on E : Exception do
        begin
          ShowMessage(E.Message);
          FDConnection1.RollbackRetaining;
          FDConnection1.Commit;
          CurrentLine.Free;
          Strings.Free;
        end;

  end;
  FDConnection1.Commit;

  end
  else
  begin
     raise Exception.Create('File does not exist.');
  end;



  // split function for reference
  procedure Split(Delimiter: Char; Str: string; ListOfStrings: TStrings) ;
  begin
      ListOfStrings.Clear;
      ListOfStrings.Delimiter       := Delimiter;
      ListOfStrings.StrictDelimiter := True; // Requires D2006 or newer.
      ListOfStrings.DelimitedText   := Str;
  end;

【问题讨论】:

  • 您是否尝试使用 TMonitor 来查看发生了什么?不过,我不确定这是否可以帮助您正确捕获错误并在运行时提供反馈。
  • 执行 Array DML 查询时有一个OnExecuateError 事件。

标签: csv delphi firedac dml interbase


【解决方案1】:

就我而言,我的问题是我将 FDQuery1.Exec(FDQuery1.Params.Size, 0) 的范围设置得太低,从而插入了空记录。只需将 0 提高到 1 即可解决我的问题。

然而,我没有找到一种有用的方法来监视 sql 错误并提取在 TMonitor 上发送的 Array DML 查询。

【讨论】:

    【解决方案2】:

    不需要第二个 for 循环。您检查要修复的每一行的整个字符串列表。

    我会将循环部分更改为此(PS:未测试):

    for m := 1 to iArraySize do   //starting at second line of file since first is used for column names
    begin
      CurrentLine.Clear;
      Split(',', Strings[m], CurrentLine);
    
      if CurrentLine[m].IsEmpty then
      begin
        CurrentLine[m] := ' ';
      end;
      if CurrentLine[m].Contains('''') then
      begin
        CurrentLine[m] := StringReplace(CurrentLine[m], '''', '''''', [rfReplaceAll, rfIgnoreCase]);
      end;
    
      FDQuery1.Params[0].AsIntegers[m] := CurrentLine[0].ToInteger;
      FDQuery1.Params[1].AsStrings[m] := CurrentLine[1];
      FDQuery1.Params[2].AsStrings[m] := CurrentLine[2];
      FDQuery1.Params[3].AsBooleans[m] := CurrentLine[3].ToBoolean;
      FDQuery1.Params[4].AsStrings[m] := CurrentLine[4];
      FDQuery1.Params[5].AsStrings[m] := CurrentLine[5];
      FDQuery1.Params[6].AsIntegers[m] := CurrentLine[6].ToInteger;
      FDQuery1.Params[7].AsBooleans[m] := CurrentLine[7].ToBoolean;
      FDQuery1.Params[8].Values[m] := CurrentLine[8];
      FDQuery1.Params[9].Values[m] := CurrentLine[9];
    end;
    

    也改变

    FDConnection1.CommitRetaining;
    

    FDConnection1.RollbackRetaining;
    

    FDConnection1.Commit;
    

    FDConnection1.Rollback;
    

    提交或回滚事务。

    FDConnection1.CommitRetaining 提交当前事务但不结束它。

    FDConnection1.RollbackRetaining 回滚当前事务但不结束它。

    要监控 FireDac 流量,您可以使用其内置的 Monitor & Tracking 功能。

    另外,不要在回滚后提交。做一个或另一个。

    【讨论】:

    • 我很欣赏这些建议,但这并不能真正解决我的问题
    • 是的,链接错误。无论如何,显示器似乎不适用于 Array DML。我得到的不是任何东西,就是带有“VALUES(?, ?, ?, ?, ?, ?, etc..)”的 FDQuery1.Text,所以它不是很有帮助......
    猜你喜欢
    • 2013-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多