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

FireDAC CmdExecTimeout超时设置失效问题求助

问题描述

我希望限制查询获取数据的耗时,本应通过控制Execute和Open命令的ResourceOptions.CmdExecTimeout属性实现,但设置后该超时被忽略,查询无响应且未触发异常。

同步查询示例代码

procedure TfrmMainForm.btnSynchronousOpenClick(Sender: TObject);
begin
  var Query := TFDQuery.Create(Self);
  Query.Connection := cnConnection;
  Query.SQL.Text := '''
     DECLARE @X int
     WHILE 1=1   -- Infinite Loop
       SET @X = 1
     ''';
  
  Query.ResourceOptions.CmdExecTimeout := 1000;
  try
    Query.Open;
    ShowMessage('Query Opened');
  except
    on E: EFDDBEngineException do
      if E.Kind = ekCmdAborted then
        ShowMessage('Query Aborted');
  end;
end;

上述SQL为无限循环,预期1000ms后触发超时异常,但无任何反应。

连接配置

cnConnection通过Microsoft ODBC Driver 17 for SQL Server连接SQL Server:

object cnConnection: TFDConnection
  Params.Strings = (
    'Database=agilITy_0002'
    'Server=10.0.0.48'
    'OSAuthent=Yes'
    'MARS=yes'
    'ODBCAdvanced=TrustServerCertificate=Yes'
    'DriverID=MSSQL')
  Connected = True
  LoginPrompt = False
  Left = 60
  Top = 152
end

异步查询尝试

我也尝试了异步查询,同样未触发异常:

procedure TfrmMainForm.QueryOpened(Dataset: TDataset);
begin
  ShowMessage('Query Opened');
end;

procedure TfrmMainForm.btnAynchronousOpenClick(Sender: TObject);
begin
  var Query := TFDQuery.Create(Self);
  Query.Connection := cnConnection;
  Query.SQL.Text := '''
    DECLARE @X int
    WHILE 1=1   -- Infinite Loop
      SET @X = 1
    ''';
  
  Query.ResourceOptions.CmdExecMode := amAsync;
  Query.ResourceOptions.CmdExecTimeout := 1000;
  Query.AfterOpen := QueryOpened;
  try
    Query.Open;
  except
    on E: EFDDBEngineException do
      if E.Kind = ekCmdAborted then
        ShowMessage('Query Aborted');
  end;
end;

请问我哪里操作错误?如何正确设置查询打开的超时时间?


解决方案

1. 修正SQL字符串语法错误

你的代码中Query.SQL.Text的赋值存在核心问题:使用三重单引号导致实际传递给SQL Server的语句被外层单引号包裹,变成了字符串字面量而非可执行的批处理语句。SQL Server不会执行循环逻辑,自然不会触发超时。

正确的SQL赋值写法(二选一):

  • 单引号转义的多行写法:
Query.SQL.Text := 'DECLARE @X int'#13#10 +
                  'WHILE 1=1   -- Infinite Loop'#13#10 +
                  '  SET @X = 1';
  • Delphi 10.2+支持的多行字符串语法:
Query.SQL.Text := `
DECLARE @X int
WHILE 1=1   -- Infinite Loop
  SET @X = 1
`;

2. 协同配置FireDAC与ODBC超时

在ODBC驱动连接SQL Server的场景下,仅设置FireDAC的CmdExecTimeout可能无法生效,需要配合ODBC驱动的查询超时参数:

方法一:连接级别全局设置

在TFDConnection的参数中添加QueryTimeout(单位为秒),对应ODBC的SQL_ATTR_QUERY_TIMEOUT,强制SQL Server在指定时间后终止查询:

object cnConnection: TFDConnection
  Params.Strings = (
    'Database=agilITy_0002'
    'Server=10.0.0.48'
    'OSAuthent=Yes'
    'MARS=yes'
    'ODBCAdvanced=TrustServerCertificate=Yes'
    'DriverID=MSSQL'
    'QueryTimeout=1') // 1秒超时
  Connected = True
  LoginPrompt = False
  Left = 60
  Top = 152
end

方法二:单查询精细控制

如果需要为不同查询设置不同超时,可在代码中同时配置FireDAC和ODBC参数:

procedure TfrmMainForm.btnSynchronousOpenClick(Sender: TObject);
begin
  var Query := TFDQuery.Create(Self);
  Query.Connection := cnConnection;
  // 修正后的SQL
  Query.SQL.Text := `
DECLARE @X int
WHILE 1=1   -- Infinite Loop
  SET @X = 1
`;
  
  // FireDAC层面超时(毫秒)
  Query.ResourceOptions.CmdExecTimeout := 1000;
  // ODBC驱动超时(秒),与FireDAC超时同步
  Query.Connection.Params.Values['QueryTimeout'] := '1';
  
  try
    Query.Open;
    ShowMessage('Query Opened');
  except
    on E: EFDDBEngineException do
      if E.Kind = ekCmdAborted then
        ShowMessage('Query Aborted');
  end;
end;

3. 异步模式的额外配置

异步模式下需启用FireDAC的异步等待机制,确保超时触发:

procedure TfrmMainForm.btnAynchronousOpenClick(Sender: TObject);
begin
  var Query := TFDQuery.Create(Self);
  Query.Connection := cnConnection;
  Query.SQL.Text := `
DECLARE @X int
WHILE 1=1   -- Infinite Loop
  SET @X = 1
`;
  
  Query.ResourceOptions.CmdExecMode := amAsync;
  Query.ResourceOptions.CmdExecTimeout := 1000;
  Query.AfterOpen := QueryOpened;
  // 启用异步超时检查
  Query.ResourceOptions.WaitForAsync := True;
  
  try
    Query.Open;
    // 等待执行完成或超时
    Query.WaitFor(1000);
  except
    on E: EFDDBEngineException do
      if E.Kind = ekCmdAborted then
        ShowMessage('Query Aborted');
  end;
end;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 14:39:53