【问题标题】:SQL Statement Termination using RAISERROR使用 RAISERROR 终止 SQL 语句
【发布时间】:2010-11-17 09:06:32
【问题描述】:

(SQL 2005) raiserror 是否可以终止存储过程。

例如,在一个大型系统中,我们有一个不希望输入到特定列中的值。如果你写的话,在更新触发器中:

如果存在(从插入的地方选择 * testcol = 7) 开始 raiseerror('我的自定义错误', 16, 1) 结束

更新信息仍然适用。 但是,如果你运行

如果存在(从插入的地方选择 * testcol = 7) 开始 选择 1/0 结束

抛出除以 0 的错误,实际上终止了更新。 有什么办法可以通过 raiseerror 来做到这一点,以便我可以返回自定义错误消息?

【问题讨论】:

    标签: sql sql-server-2005 triggers raiserror


    【解决方案1】:

    您应该在执行更新之前检查有效数据。

    IF (@testvalue = 7)
        RAISERROR("Invalid value.", 16, 1);
    ELSE
        UPDATE...
    

    【讨论】:

    • 本例中的数据是输入参数,除非存储过程显式更改,否则不应更改。
    • 我不知道哪个 sproc 正在更新它,或者它是否是一个夜间数据库作业,所以我无法在更新之前检查它的值。
    • 你想让这个神秘的工作在它试图输入这个值时爆炸吗?
    【解决方案2】:

    你能不能只在列中添加一个 CHECK 约束来防止它首先被插入?

    ALTER TABLE YourTable ADD CONSTRAINT CK_No_Nasties
        CHECK (testcol <> 7)
    

    或者,您可以在插入存储过程中启动一个事务(如果有),并在发生错误时将其回滚。这可以通过 SQL Server 2005 中的 TRYCATCH 来实现,并且不必使用触发器。

    【讨论】:

      【解决方案3】:

      在触发器中,发出 ROLLBACK、RAISERROR 然后返回。

      Error Handling in SQL Server - Trigger Context by Erland Sommarskog

      【讨论】:

      • 这仅对交易有效吗?还是触发器是事务性的?
      • 来自我发布的链接“当在触发器中时,不必有匹配的 BEGIN TRANSACTION 语句,因为不在显式事务中的每个 SQL 语句实际上都是单语句事务。”
      • 来自我的链接:触发器总是在事务的上下文中执行,因为即使没有正在进行的多语句事务,每个 INSERT、UPDATE 和 DELETE 语句都是它自己的事务SQL Server,触发器是该事务的一部分。
      • 是的!你的唐!我们的 dba 在事务方面存在问题,因此我们不倾向于沿着这条路径进行研究,我不知道触发器属于事务过程(尽管现在你已经让我想到了这很明显)。谢谢!
      【解决方案4】:
      Begin try
      @temp number
      @temp=1/0
      End try
      Begin catch
      @errormsg varchar(100)
      @errormsg=error_massage()
      Raiseerror(@errormsg,16,1)
      End catch
      

      【讨论】:

      • 您可以为您的解决方案添加说明吗?
      猜你喜欢
      • 2020-07-21
      • 2014-07-02
      • 2021-08-20
      • 2021-10-29
      • 2021-09-01
      • 2011-09-21
      • 2016-05-22
      • 1970-01-01
      • 2016-06-26
      相关资源
      最近更新 更多