大家可以试试:
如下三个存储过程:
create procedure sp_a
as
  exec sp_b
go
create procedure sp_b
as
  exec sp_c
go
create procedure sp_c
as
  raiserror 50002  '如果你能看到我,说明你捕获到了我的错误'
go
然后你在Delphi里面
   try
     adoQuery1.SQL.Text:=' exec  sp_a  ';
     showMessage('哈哈,执行成功');
   except
     on e:Exception do
        showmessage(E.Message);
   end; 
   
大家试试能否捕获错误!!我发现,只要存储过程调用了存储过程,或触发器又调用了存储过程,或者又触发了触发器,那么在以后的存储过程中如果有错误发生,delphi中是捕获不到这种错误的。
   只能用 adoQuery1.Connection.Erros.count>0知道发生了错误。   但这样的话,我总不能每执行一条SQL语句,就检查一下adoConnection.Errors,岂不是太麻烦了?
   (如果不检查的话太不可靠了,谁知道表里面都有什么触发器,触发器又触发或者调用其他存储过程)
   并且我还发现:    conn1.begintrans;
    try
      qry1.sql.text:='...';
      qry1.execsql;   
      qry2.sql.text:='...';
      qry2.execsql;   
      if conn1.Errors.count>0 then
         conn1.rollbacktrans
      else
         conn1.committrans;          
    except
       conn1.rollbacktrans;
    end;     假设在执行 Qry1.execSQL中发生错误,而这个错误是隔了一级(计触发器触发了另外的触发器或调用了其他存储过程中出的错),那么try except是捕获不到的,而之后又执行了Qry2.ExecSQL,而执行该操作没有错误发生。那么现在检测conn1.Errors.count已经是零了。 最终的结果是Qry1执行失败,自动回滚,而Qry2执行成功,最后提交。造成数据不一致。
     但我总不能每次执行一个SQL语句,就检查一下conn1.Errors.count吧?
     大家有什么好的办法?
    是不是合理的解决方法是修改 ADOQuery.ExecSQL 源码,使之本身具有检测 adoConnnetion.Errors得功能  如果有errors发生,就raise exception,好让delphi知道有错误发生了。 这样传统的try except也能捕获这种错误了。