You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi中ADOConnection.Execute异常处理优化及执行结果获取咨询

解决Delphi ADO执行SQL时的异常捕获与结果验证问题

一、为什么你的代码没捕获到SQL Server的截断错误?

ADO连接默认不会对SQL Server的Level 16及以下的部分错误抛出Delphi异常,比如你遇到的Msg 2628(Level 16)。需要修改ADOConnection的Attributes属性,强制让这类错误触发Delphi异常:

// 可在连接打开前设置,或在设计时直接修改属性面板
ADOConnection1.Attributes := ADOConnection1.Attributes + [xaErrorRecords];

这个属性会让ADO把SQL Server返回的错误记录转化为Delphi异常,确保except块能捕获到这类错误。

二、优化后的异常处理代码

不要只显示模糊的"DB error",应该捕获具体的ADO异常并提取详细错误信息,同时确保连接资源被正确释放:

var cmdResult: _Recordset;
begin
  try
    ADOConnection1.Connected := True;
    // 保存Execute返回的结果对象,用于获取行数及后续释放
    cmdResult := ADOConnection1.Execute(Memo1.Lines.Text);
    try
      // 获取受影响的行数(针对INSERT/UPDATE/DELETE等DML语句)
      var affectedRows := cmdResult.RowsAffected;
      ShowMessage(Format('Floorplan imported to DB, %d rows affected', [affectedRows]));
    finally
      cmdResult.Free; // 必须释放_Recordset对象,避免内存泄漏
    end;
  except
    on E: EADOError do
    begin
      // 提取SQL Server返回的所有错误细节
      var errMsg := '';
      for var i := 0 to E.Errors.Count - 1 do
      begin
        errMsg := errMsg + Format('Error %d: %s'#13#10, [E.Errors[i].Number, E.Errors[i].Description]);
      end;
      ShowMessage('DB error:'#13#10 + errMsg);
    end;
    on E: Exception do
    begin
      ShowMessage('Unexpected error:'#13#10 + E.Message);
    end;
  end;
  // 确保无论是否异常,连接都会被关闭
  finally
    if ADOConnection1.Connected then
      ADOConnection1.Close;
  end;
end;

三、获取插入行数或SQL返回码的方法

1. 获取受影响的行数

ADOConnection.Execute返回的_Recordset对象的RowsAffected属性,可直接获取INSERT/UPDATE/DELETE等语句的受影响行数;如果是SELECT语句,可使用RecordCount属性(需注意游标类型,默认游标可能返回-1,可设置CursorType为ctStatic确保计数准确)。

2. 获取SQL Server自定义返回码

如果你的SQL脚本中包含RETURN语句(比如RETURN 0表示成功,RETURN 1表示失败),可以通过ADO命令对象获取返回值:

var cmd: TADOCommand;
    returnParam: TParameter;
begin
  cmd := TADOCommand.Create(nil);
  try
    cmd.Connection := ADOConnection1;
    cmd.CommandText := Memo1.Lines.Text;
    // 添加返回值参数
    returnParam := cmd.Parameters.CreateParameter('@ReturnVal', ftInteger, pdReturnValue);
    cmd.Parameters.Append(returnParam);
    cmd.Execute;
    // 获取返回码
    var returnCode := returnParam.Value;
    if returnCode = 0 then
      ShowMessage('Import success')
    else
      ShowMessage(Format('Import failed with code: %d', [returnCode]));
  finally
    cmd.Free;
  end;
end;

额外建议

  • 执行多行SQL时,尽量拆分语句逐一执行,或使用参数化查询,避免SQL注入和语法错误;
  • 对于字符串截断问题,建议在前端提前验证输入长度(比如检查输入是否超过表字段定义的长度),从源头避免错误发生。

内容的提问来源于stack exchange,提问作者milenjao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 14:30:21