以下是适用于多行的解决方案。
感谢jFun为单行插入所做的工作,但这种触发器并不是真正安全的使用方式。
好的,假设有这个表:
create table TestingTransactions (
id int identity,
transactionNo int null,
contract_id int not null,
Data1 varchar(10) null,
Data2 varchar(10) null
);
在我的情况下,我需要“transactionNo”始终具有每个合同的正确下一个值。在遗留金融系统中对我很重要的是,transactionNo编号没有间隙。
因此,我们需要以下触发器来确保transactionNo列的引用完整性。
CREATE TRIGGER dbo.Trigger_TransactionNo_Integrity
ON dbo.TestingTransactions
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
WITH trans
AS (SELECT F.*,
Row_number()
OVER (
ORDER BY contract_id) AS RowNum,
A.*
FROM inserted F
CROSS apply (SELECT Isnull(Max(transactionno), 0) AS
LastTransaction
FROM dbo.testingtransactions
WHERE contract_id = F.contract_id) A),
newtrans
AS (SELECT T.*,
NT.minrowforcontract,
( 1 + lasttransaction + ( rownum - NT.minrowforcontract ) ) AS
NewTransactionNo
FROM trans t
CROSS apply (SELECT Min(rownum) AS MinRowForContract
FROM trans
WHERE T.contract_id = contract_id) NT)
INSERT INTO dbo.testingtransactions
SELECT Isnull(newtransactionno, 1) AS TransactionNo,
contract_id,
data1,
data2
FROM newtrans
END
GO
好的,我承认这是一个相当复杂的触发器,几乎使用了所有技巧,但这个版本应该可以在 SQL 2005 上运行。脚本利用了 2 个 CTE、2 个交叉应用和 Row_Num() 函数来计算所有插入的行的正确“下一个”TransactionNo。
它使用了 instead of insert
触发器,在丢弃任何传入的 transactionNo 的情况下,用“NEXT” transactionNo 替换它们。
因此,我们现在可以运行这些更新:
delete from dbo.TestingTransactions
insert into dbo.TestingTransactions (transactionNo, Contract_id, Data1)
values (7,213123,'Blah')
insert into dbo.TestingTransactions (transactionNo, Contract_id, Data2)
values (7,333333,'Blah Blah')
insert into dbo.TestingTransactions (transactionNo, Contract_id, Data1)
values (333,333333,'Blah Blah')
insert into dbo.TestingTransactions (transactionNo, Contract_id, Data2)
select 333 ,333333,'Blah Blah' UNION All
select 99999,44443,'Blah Blah' UNION All
select 22, 44443 ,'1' UNION All
select 29, 44443 ,'2' UNION All
select 1, 44443 ,'3'
select * from dbo.TestingTransactions
order by Contract_id,TransactionNo
我们正在更新单行和混合合同编号的多行,但正确的交易号会覆盖传入的值,从而获得预期的结果。
id transactionNo contract_id Data1 Data2
117 1 44443 NULL Blah Blah
118 2 44443 NULL 1
119 3 44443 NULL 2
120 4 44443 NULL 3
114 1 213123 Blah NULL
115 1 333333 NULL Blah Blah
116 2 333333 Blah Blah NULL
121 3 333333 NULL Blah Blah
我对并发的看法很感兴趣。我非常确定这两个CTE将被视为单个传递,因此,我99.99%确定引用完整性将始终得到保持。