Try and Catch on TSQL - catch 不捕获

2024-02-17

我有一个存储过程似乎没有正确记录其错误。

代码出错,但 catch 块似乎没有生效。

try 块相当长 - 但错误部分很简单并且就在最后,所以我已经精确说明了这一点。

BEGIN TRY 
insert into tbl_X
select * from #temp_tbl_Y

RETURN 1
END TRY

BEGIN CATCH
    Insert Into ExtractsErrorLog
    SELECT 
    getdate() as ErrorDate 
    ,object_name(@@procid) as ProcedureName
    ,ERROR_NUMBER() as ErrorNumber
    ,ERROR_LINE() as ErrorLine
    ,ERROR_MESSAGE() as ErrorMessage
    ;
DECLARE @errormessage as varchar(max);
DECLARE @errorseverity as int;
DECLARE @errorstate as int;

set @errormessage = ERROR_MESSAGE();
set @errorseverity = ERROR_SEVERITY();
set @errorstate = ERROR_STATE();

 RAISERROR (@errormessage,
            @errorseverity,
            @errorstate
               );


END CATCH;

进程失败的错误是我们的老朋友 “列名称或提供的值的数量与表定义不匹配。” 我已经修复了该错误 - 这是一个愚蠢的懒惰错误 - 但我很困惑为什么我的错误日志记录过程似乎不起作用 - 没有行被插入到我的 ExtractsErrorLog 表中。


TSQL's TRY...CATCH没有捕获该错误。该错误属于“编译/重新编译”类型错误,不由CATCH块“在同一执行级别内”。

From MSDN http://msdn.microsoft.com/en-us/library/ms175976.aspx:

以下类型的错误不会由 CATCH 块处理: 它们发生在与 TRY…CATCH 构造相同的执行级别:

  • 编译错误,例如语法错误,会阻止批处理 跑步。

  • 语句级重新编译期间发生的错误,例如 作为编译后发生的对象名称解析错误,因为 延迟名称解析

...

可以使用TRY…CATCH来处理编译过程中出现的错误 或通过执行生成错误的语句级重新编译 TRY 块中单独批处理的代码。例如,你做 通过将代码放入存储过程或执行 使用 sp_executesql 的动态 Transact-SQL 语句。这允许 TRY…CATCH 在比执行级别更高的执行级别捕获错误 错误发生。例如,以下代码显示了存储的 生成对象名称解析错误的过程。该批次 包含 TRY…CATCH 构造的内容正在更高级别执行 比存储过程;和错误,发生在较低的 水平,被抓住。

我在一个脚本中创建事务时遇到了类似的问题TRY...CATCH那会ROLLBACK如果交易失败。事务内的一条语句引发了同样的错误,并导致事务永远不会关闭,因为CATCH从未进入过。

正如 MSDN 文章中提到的,一种替代方法是从您的存储过程中创建一个存储过程。INSERT声明,然后在你的 try/catch 中调用它。如果存储过程错误,您将在尝试创建它时捕获编译错误。如果表定义稍后发生更改以使存储过程无效,则TRY...CATCH将为您捕获异常。

如果您希望所有内容都存在于一个脚本中,您可以将其制作为临时存储过程 http://technet.microsoft.com/en-us/library/ms190669(v=sql.105).aspx/#sectionToggle1,但是您需要在创建存储过程时处理编译错误。它并不漂亮,但它会起作用:

-- Creating error sproc to re-use code
CREATE PROCEDURE #HandleError AS
    Insert Into ExtractsErrorLog
    SELECT  GETDATE() as ErrorDate 
            ,object_name(@@procid) as ProcedureName
            ,ERROR_NUMBER() as ErrorNumber
            ,ERROR_LINE() as ErrorLine
            ,ERROR_MESSAGE() as ErrorMessage;

    DECLARE @errormessage as varchar(max);
    DECLARE @errorseverity as int;
    DECLARE @errorstate as int;

    set @errormessage = ERROR_MESSAGE();
    set @errorseverity = ERROR_SEVERITY();
    set @errorstate = ERROR_STATE();

    RAISERROR ( @errormessage,
                @errorseverity,
                @errorstate);
GO

-- Create a stored procedure of our INSERT and catch any compilation errors
CREATE PROCEDURE #TEST AS
    insert into tbl_X
    select * from #temp_tbl_Y
GO
IF (@@ERROR <> 0) BEGIN
    exec #HandleError
    -- If there was an error creating the sprocs, don't continue to the next batch
    RETURN
END

-- If compilation succeeded, then run the sproc
BEGIN TRY 
    exec #TEST
    RETURN
END TRY
BEGIN CATCH
    exec #HandleError
END CATCH;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Try and Catch on TSQL - catch 不捕获 的相关文章

随机推荐

  • 反转 HList 并转换为类?

    我使用 Shapeless 在 Akka 中累积物化值作为 HList 并将其转换为案例类 对于这个问题 您不必了解 Akka 太多 但默认方法将物化值累积为递归嵌套的 2 元组 这并不是很有趣 因此 Shapeless HLists 似乎
  • 通过 Socket 连接使用 PrintWriter 将 PDF 文件打印到打印机

    我必须使用具有特定 IP 地址的打印机打印 pdf 文件 我可以打印特定的文本 但我想打印文件或 html 解析的文本 My Code try Socket sock new Socket 192 168 0 131 9100 PrintW
  • NetFSMountURLSync 无法使用自定义安装点?

    我正在尝试以编程方式挂载一些 WebDAV 和 SMB 共享 并且我想为卷指定除默认名称之外的特定名称 例如 如果我安装 https my sharepoint school edu personal grigutis https my s
  • Android AppWidget 配置 - 在新任务中启动

    我一直在寻找这个 所以我有一个应用程序小部件 它有一个配置活动 我可以在按下应用程序上的按钮时打开该活动 场景是 打开应用程序 使用主页按钮关闭应用程序 选择添加我的小部件 我已经配置了小部件 放置在我的主屏幕上 然后使用小部件上的按钮再次
  • 如何在perl中读取匹配字符串上方的n行?

    假设我有一个文件 xx txt 它包含数据 1 I am here 2 to work in 3 Perl for writing 4 a script for 5 myself 假设我想搜索字符串脚本并想显示三个 上面有几行 我该怎么办
  • int a=1, b=a++; 是否调用未定义的行为?

    Does int a 1 b a 调用未定义的行为 初始化之间没有序列点介入a及其在初始化程序中的访问和修改b 但据我所知 初始化不是对象的 修改 指定初始值设定项来给出对象的 初始值 根据 6 7 8 初始化 第 8 段 初始化器指定存储
  • 可以直接用二进制写程序吗?我怎样才能让计算机执行它?

    我知道这可能看起来很奇怪并且自找麻烦 但我认为体验古代程序员以前经历过的事情是很有趣的 那么如何执行仅用二进制编写的程序呢 假设我知道我在做什么 当然不使用汇编 我只想写一系列像111010111010101010101并执行它 那么我该怎
  • 如何使用 WPF 后台工作者

    在我的应用程序中 我需要执行一系列初始化步骤 这些步骤需要 7 8 秒才能完成 在此期间我的 UI 变得无响应 为了解决这个问题 我在一个单独的线程中执行初始化 public void Initialization Thread initT
  • -XX:+PrintGC 和 -verbose:gc 之间的区别

    我想了解以下之间的区别 XX PrintGC and verbose gc显然这些看起来很相似 本文没有列出verbose gc http www oracle com technetwork articles java vmoptions
  • 如何使用 TFS 构建服务器中的模板运行 NUnit 测试

    我需要使用 TFS Server 2010 中的工作流模板运行 nUnit 测试 我找到了下面所有解释如何配置构建服务器的参考资料 http morten lyhr dk 2008 05 using nunit and ncover wit
  • Error62:在 VBA 脚本中输入文件末尾以搜索目录中包含关键字的文件

    希望有人能够指出我误入歧途的地方 我创建了一个脚本来搜索目录中的所有文件 并返回包含已输入到单元格中的特定关键字的任何文件的文件路径和文件名 该脚本似乎适用于我在桌面上设置的测试文件夹 但是当我尝试搜索包含更多文件的另一个目录时 我收到 输
  • 自定义活动设计器中的参数验证

    我在验证自定义活动的设计器中正常工作时遇到问题 重现该行为的最简单示例如下 我有一个自定义 WF4 活动 其中包含存储在字典中的动态参数集合 Designer typeof DictionaryActivityDesigner public
  • Rand Index函数(聚类性能评估)

    据我所知 python 中没有可用于 Rand Index 的软件包 而对于调整后的 Rand Index 您可以选择使用sklearn metrics adjusted rand score labels true labels pred
  • 获取自己的标头 $Resource AngularJs

    我有 GO 语言的 REST API 和 Angularjs 的前端 但是当我以 Angular 形式获取资源时 我的自定义标头不存在 控制器 Persons query function data headerGetter status
  • 共享元素转换不适用于 Android 中的添加片段

    我观察到共享元素转换仅适用于 替换 方法 有什么方法可以使其与 add 方法一起使用 None
  • 使用php通过android volley发送图像[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在用数据和图像从 android 到 php 发布帖子 我正在 android 中缩小图像并对其进行 base 64 编码 当通过齐射
  • [Firestore][I-FST000001] 无法到达 Firestore 后端

    我已经配置了 Firebase Firestore 但 Firestore 曾返回此错误 Firestore I FST000001 无法到达 Firestore 后端 我正在使用 Swift 4 和 Xcode 9 有什么想法吗 2018
  • 程序部署后 JNI 找不到共享库

    将导出的 Java 项目从开发计算机移至生产环境后 我遇到了麻烦 java项目 一个Eclipse插件 有一个我写的JNI库 它依赖于一个开源库 而这个库又依赖于Boost 我在我的 SLES11 机器上编译了所有内容 包括 Boost 并
  • 使用节点 8 async/await 和 Angular 6 调试量角器时出错

    我无法让量角器调试器与节点 8 async await 和 Angular 6 一起使用 以旧方式返回到节点 7elementExplorer browser pause and browser debugger 不是一个选择 也因为在未来
  • Try and Catch on TSQL - catch 不捕获

    我有一个存储过程似乎没有正确记录其错误 代码出错 但 catch 块似乎没有生效 try 块相当长 但错误部分很简单并且就在最后 所以我已经精确说明了这一点 BEGIN TRY insert into tbl X select from t