【发布时间】:2016-02-17 16:48:15
【问题描述】:
我遇到了一个问题,其中一个触发器的一部分出现故障。此故障导致包装触发器的事务回滚。问题在于它没有向命令的调用点引发错误。它表现得好像事务中没有错误,并且捕获它的唯一方法是应该更改的数据没有。 在我的示例中,交易发生了很多变化。错误发生在触发器中。一切都回滚了,但是,命令的调用者没有看到 SQL 异常。从来没有通知调用者有问题。
有什么方法可以指示 TSQL 抛出异常,使其向命令的调用点报告错误?
CREATE TABLE Archive (
aColumn INT NOT NULL
)
CREATE TABLE Source (
aColumn INT NULL
)
--
CREATE TRIGGER Archive_Trigger ON Source
AFTER UPDATE
AS
BEGIN
INSERT INTO Archive
SELECT DELETED.aColumn
FROM DELETED
END
-- Other attempts
CREATE TRIGGER Archive_Trigger ON Source
AFTER UPDATE
AS
BEGIN
BEGIN TRY
INSERT INTO Archive
SELECT DELETED.aColumn
FROM DELETED
END TRY
BEGIN CATCH
SET XACT_ABORT ON;
DECLARE @ErrorMessage NVARCHAR(4000) ;
SET @ErrorMessage = ERROR_MESSAGE() ;
RAISERROR('Error %s occurred in Archive Trigger', 16, 1, @ErrorMessage) ;
END CATCH
END
这是触发器所做工作的一个非常幼稚的版本。问题没有发生在生产系统上。当它发生时是在开发环境中。当 /Source/ 表更改时,/Archive/ 表也必须更改。有时会忘记存档,这就是发生错误的时候。例如,如果 aColumn 在存档中不为空,在源中为空。这个实例会导致问题。
如果我执行以下代码,则在表中有一行具有空 aColumn 之后。我期望的结果是得到一个异常。我不。
DataSource source;
Connection connection = source.getConnection();
PreparedStatement statement = connection.prepareStatement("UPDATE Source SET aColumn = NULL");
statement.executeUpdate();
【问题讨论】:
-
能否添加一些示例代码
-
@TheGameiswar 我已经添加了一些代码,但我不知道它会有多大帮助。该问题的代码方式并不多。
-
您可以通过显式命名插入中的列来消除错误。无论如何,这应该作为一种通用方式来避免这种确切的情况。当然,如果删除一列,这仍然是一个问题。
-
我们不能使用isnull来纠正错误
-
这将修复这种情况下的错误。问题不是特定的错误。问题是表格中的偏差。 /Source/ 被更改并且 /Archive/ 被遗忘。这会导致错误回滚但不会引发错误。
标签: sql sql-server hibernate tsql