如何通过TADOStoredProc获取存储过程的RAISERROR进度消息?
可以通过TADO组件实时获取RAISERROR WITH NOWAIT的进度消息
结论是可以实现,但需要正确配置ADO组件并处理对应的事件,以下是具体实现步骤:
1. 配置ADO组件属性
- 将
TADOStoredProc关联的TADOConnection的CursorLocation设置为clUseServer:客户端游标会缓存结果集和消息,无法实时获取进度;服务器端游标才能让SQL Server实时推送消息。 - 给
TADOStoredProc的ExecuteOptions添加eoAsyncExecute:适配你的线程异步执行场景,同时确保消息能被实时捕获。
2. 处理ADOConnection的OnInfoMessage事件
SQL Server通过RAISERROR WITH NOWAIT发送的信息类消息(严重级别1-10)会触发TADOConnection的OnInfoMessage事件,你可以在这个事件中获取进度消息并更新UI:
procedure TMainForm.ADOConnInfoMessage(Connection: TADOConnection; const Error: Error; var EventStatus: TEventStatus); begin // 跨线程更新UI必须同步到主线程 TThread.Synchronize(nil, procedure begin ProgressMemo.Lines.Add('进度:' + Error.Description); end); end;
3. 存储过程的要求
RAISERROR的严重级别必须在1-10之间:级别≥11会被ADO判定为错误,触发OnError事件而非OnInfoMessage。- 必须带
WITH NOWAIT关键字:否则SQL Server会把消息缓存到存储过程执行结束后才一次性发送,无法实时展示进度。
示例存储过程代码:
CREATE PROCEDURE dbo.LongRunningProcess AS BEGIN SET NOCOUNT ON; RAISERROR('正在初始化数据...', 0, 1) WITH NOWAIT; WAITFOR DELAY '00:00:03'; -- 模拟耗时操作 RAISERROR('已完成30%,正在处理核心逻辑...', 0, 1) WITH NOWAIT; WAITFOR DELAY '00:00:05'; RAISERROR('处理完成,正在生成结果...', 0, 1) WITH NOWAIT; WAITFOR DELAY '00:00:02'; RAISERROR('全部执行完成!', 0, 1) WITH NOWAIT; END
4. 线程执行的注意事项
- 线程中操作ADO组件时,建议为每个线程创建独立的
TADOConnection实例,避免多线程共享连接导致的线程安全问题。 - 调用
TADOStoredProc.Execute时,确保异步选项已开启,线程不会阻塞主线程,同时保证消息能被实时捕获。
内容的提问来源于stack exchange,提问作者Keith Miller
相关产品推荐
相关产品推荐

