sql - 回滚 SQL 事务而不返回错误
问题描述
考虑下面的触发器
ALTER TRIGGER [dbo].[trgUpdateTasks]
ON [dbo].[Tasks]
FOR UPDATE
AS
BEGIN
SET NOCOUNT ON;
-- Check if job has quotation --
DECLARE @JobID NUMERIC(18,0)
DECLARE @QuotationID UNIQUEIDENTIFIER
SELECT @JobID = INSERTED.JobID FROM INSERTED
SET @QuotationID = (SELECT TOP 1 QuotationID FROM Jobs WHERE (JobID=@JobID))
--------------------------------
IF( NOT (@QuotationID IS NULL) )
BEGIN
ROLLBACK TRANSACTION;
END;
END
这个想法是停止对Tasks记录进行的任何更改,如果它与QuotationID字段中具有值的Jobs记录相关联。
它之所以有效,是因为满足这些条件时,不会保存更改。但是,会向应用程序返回一个错误,导致应用程序崩溃。不幸的是,该应用程序无法更新以忽略此类错误,因为它运行在一台非常旧的 Windows 机器上,不允许安装较新的 exe。
有没有办法将触发器设置为在回滚时不返回错误,以便就应用程序而言,更改已正常保存?
解决方案
/* *** DDL and Test Data *** */
USE tempdb;
GO
SET ANSI_NULLS, QUOTED_IDENTIFIER, ANSI_PADDING ON;
GO
CREATE TABLE dbo.Tasks
(
TaskID int NOT NULL PRIMARY KEY
,JobID int NOT NULL
,Task varchar(50) NOT NULL
,TaskStart date NOT NULL
,TaskEnd date NULL
);
GO
INSERT INTO dbo.Tasks
VALUES (1, 1, 'Task1 Job1', '20210901', '20210902')
,(2, 1, 'Task2 Job1', '20210902', NULL)
,(3, 2, 'Task1 Job2', '20210903', '20210904')
,(4, 2, 'Task2 Job2', '20210905', '20210906')
,(5, 3, 'Task1 Job3', '20210910', '20210911')
,(6, 3, 'Task2 Job3', '20210915', NULL)
,(7, 4, 'Task1 Job4', '20210903', '20210904')
,(8, 4, 'Task2 Job4', '20210905', '20210906');
GO
CREATE TABLE dbo.Jobs
(
JobID int NOT NULL PRIMARY KEY
,QuotationID uniqueidentifier NULL
,Job varchar(50) NOT NULL
);
GO
INSERT INTO dbo.Jobs
VALUES (1, 'F15EAF03-4F45-40E8-85D6-D89B20E00F38', 'Job1')
,(2, NULL, 'Job2')
,(3, 'F15EAF03-4F45-40E8-85D6-D89B20E00F38', 'Job3')
,(4, '3D74F043-2FAC-4C91-8288-13D71C6558C8', 'Job4');
GO
/* *** End DDL and Test Data *** */
/* *** Create Trigger *** */
SET ANSI_NULLS, QUOTED_IDENTIFIER ON;
GO
CREATE TRIGGER dbo.Tasks_TR_U
ON dbo.Tasks
INSTEAD OF UPDATE
AS
BEGIN
SET NOCOUNT, XACT_ABORT ON;
UPDATE T
SET Task = I.Task
,TaskStart = I.TaskStart
,TaskEnd = I.TaskEnd
FROM dbo.Tasks T
JOIN inserted I
ON T.TaskID = I.TaskID
WHERE EXISTS
-- Only QuotationID of NULL allowed
(
SELECT 1
FROM dbo.Jobs J
WHERE J.JobID = T.JobID
AND J.QuotationID IS NULL
)
-- Only update if any changes
AND NOT
(
T.Task = I.Task
AND T.TaskStart = I.TaskStart
AND ISNULL(T.TaskEnd, '1900') = ISNULL(I.TaskEnd, '1900')
);
END
GO
/* *** End Create Trigger *** */
/* Check data in tables. */
select * from dbo.Tasks;
select * from dbo.Jobs;
/* Run test */
UPDATE dbo.Tasks
SET Task = Task + ' Updated'
/* Only JobId = 2 should be updated. */
select * from dbo.Tasks;
/* Drop Test Tables
DROP TABLE dbo.Tasks;
DROP TABLE dbo.Jobs;
*/
推荐阅读
- android - 无法从 RTSP URL 播放视频
- sql - 在子查询中使用 CTE
- matlab - 获取向量与正 x 轴之间角度的内置函数 - Matlab
- tikz - 圆形区域的阴影
- php - 如何从 span 中获取值并将其分配给 php 变量?
- scala - 如何使用@See scaladoc?
- c++ - C++/pthread/join 错误消息“what(): Invalid argument”的含义
- angular - 测试时在 *ngIf 语句中找不到按钮,因为语句涉及模拟类
- php - php.ini 中的更改未反映 PHP Memory_Limit Master Value
- python - 如何在python中使用文本文件求解具有多个参数数据的微分方程?