我有一个可以工作的触发器(它必须触发)但我仍然会收到错误。 我理解错误但我不知道如何解决它。
我尝试将一些BEGIN TRANSACTION与所有使用它的代码放在一起,但我认为我的语法是错误的,因为我总是会超时!
所以我的问题是,我在哪里必须将BEGIN TRANSACTION
语句放在我的代码中?
另外,我需要3 BEGIN TRANSACTION
个语句,因为我有3个ROLLBACK
?
提前谢谢!
我的代码:
ALTER TRIGGER [dbo].[Tr_CheckOverlap]
ON [dbo].[Tranche]
FOR INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE @IdVol INT, @IdTranche INT,
@AgeMinInserted DATE, @AgeMaxInserted DATE
SELECT @AgeMinInserted = t.TRA_Age_Min
FROM Tranche t
JOIN inserted AS i ON t.TRA_Id = i.TRA_Id
SELECT @AgeMaxInserted = t.TRA_Age_Max
FROM Tranche t
JOIN inserted AS i ON t.TRA_Id = i.TRA_Id
DECLARE CR_TrancheVol CURSOR FOR
SELECT t.TRA_Vol_Id,t.TRA_Id
FROM Tranche t
JOIN inserted AS i ON t.TRA_Vol_Id = i.TRA_Vol_Id;
OPEN CR_TrancheVol
FETCH CR_TrancheVol INTO @IdVol, @IdTranche
WHILE( @@FETCH_STATUS = 0)
BEGIN
DECLARE @AgeMin DATE, @AgeMax DATE
SELECT @AgeMin = t.TRA_Age_Min
FROM Tranche t
WHERE t.TRA_Id = @IdTranche
SELECT @AgeMax = t.TRA_Age_Max
FROM Tranche t
WHERE t.TRA_Id = @IdTranche
IF @AgeMinInserted > @AgeMin AND @AgeMinInserted < @AgeMax
BEGIN
PRINT 'Trans1'
RAISERROR('Overlap: Date de naissance minimum déjà couverte', 1, 420)
ROLLBACK TRANSACTION
END
IF @AgeMaxInserted > @AgeMin AND @AgeMaxInserted < @AgeMax
BEGIN
PRINT 'Trans2'
RAISERROR('Overlap: Date de naissance maximum déjà couverte', 1, 421)
ROLLBACK TRANSACTION
END
IF @AgeMinInserted < @AgeMin AND @AgeMaxInserted > @AgeMax
BEGIN
PRINT 'Trans3'
RAISERROR('Overlap: Tranche déjà couverte complètement', 1, 422)
ROLLBACK TRANSACTION
END
FETCH CR_TrancheVol INTO @IdVol, @IdTranche
END
CLOSE CR_TrancheVol
DEALLOCATE CR_TrancheVol
END
修改:
好的,所以我在没有光标的情况下尝试了你的答案(我明白我的方式显然不是最好的!)但是现在它没有用。
我的目标:我有一个DB来预订航班。在这个数据库中,我有一张桌子&#34; Tranche&#34;谁包含一些日期和一些价格(取决于航班时间)。
我需要预防和避免生日的任何重叠,例如:
1y-17y: 80€
18y-64y: 120€
因此,当我尝试插入17y-63y时,我的触发器必须触发:xx€(因为我已经为这些年龄段定价)。
对不起,如果我的英语不是很完美btw!
这是我的桌子&#34; Tranche&#34;:
https://i.stack.imgur.com/KuQH8.png
TRA_Vol_ID是另一个表的外键&#34; Vol&#34;谁包含航班
这是我的代码:
ALTER TRIGGER [dbo].[Tr_CheckOverlap]
ON [dbo].[Tranche]
FOR INSERT
AS
BEGIN
/*
Some SQL goes here to get the value of Minimum age.
I assuming that it doesn't vary by entry, however,
I don't really have enough information to go on to tell
*/
SET NOCOUNT ON;
DECLARE @MinAge DATE, @MaxAge DATE
SELECT @MinAge = t.TRA_Age_Min
FROM Tranche t
JOIN Vol AS v ON v.VOL_Id = t.TRA_Vol_Id
JOIN inserted AS i ON t.TRA_Id = i.TRA_Id
WHERE t.TRA_Id = i.TRA_Id
SELECT @MaxAge = t.TRA_Age_Max
FROM Tranche t
JOIN inserted AS i ON t.TRA_Id = i.TRA_Id
JOIN Vol AS v ON v.VOL_Id = t.TRA_Vol_Id
WHERE t.TRA_Id = i.TRA_Id
IF (SELECT COUNT(CASE WHEN i.TRA_Age_Min > @MinAge AND i.TRA_Age_Min < @MaxAge THEN 1 END) FROM inserted i) > 0
BEGIN
RAISERROR('Overlap: Birthday min reached',1,430);
ROLLBACK
END
ELSE IF (SELECT COUNT(CASE WHEN i.TRA_Age_Max > @MinAge AND i.TRA_Age_Max < @MaxAge THEN 1 END) FROM inserted i) > 0
BEGIN
RAISERROR('Overlap: Birthday max reached',1,430);
ROLLBACK
END
END
答案 0 :(得分:2)
我真的不知道OP的目标是什么。但是,我想发布一个小例子如何进行数据集方法,以及如何一次性检查所有行。
目前,如果用户插入1行,OP的触发器将仅“工作”。更多,事情不会正常工作。然后我们也遇到CURSOR
的问题。我注意到游标的声明根本没有引用inserted
,所以我实际上并不知道它们的目标是什么。看起来更像OP在发生INSERT
时审计表中已有的数据,而不是正在插入的数据。这看起来很奇怪。
无论如何,这不是OP的解决方案,但是,我没有足够的空间来评论所有这些。也许它会把OP推向正确的方向。
ALTER TRIGGER [dbo].[Tr_CheckOverlap]
ON [dbo].[Tranche]
FOR INSERT
AS
BEGIN
/*
Some SQL goes here to get the value of Minimum age.
I assuming that it doesn't vary by entry, however,
I don't really have enough information to go on to tell
*/
IF (SELECT COUNT(CASE WHEN i.Age < @MinAge THEN 1 END) FROM inserted i) > 0 BEGIN
RAISERROR('Age too low',1,430);
ROLLBACK
END
ELSE
IF (SELECT COUNT(CASE WHEN i.Age > @MaxAge THEN 1 END) FROM inserted i) > 0 BEGIN
RAISERROR('Age too high',1,430);
ROLLBACK
END
END
眼前的问题似乎是一个xy问题;问题不在于CURSOR
或ROLLBACK
,此触发器的问题更为根本。我建议修改你的问题并实际解释你想要用Trigger做什么的目标。为您的表CREATE
提供DDL,为任何样本数据提供INSERT
语句。您可能还想提供一些INSERT
语句,这些语句会对您的触发器产生不同的结果(确保包含一次插入多行的那些语句)。
我意识到这是更多的评论,然而,再一次,我没有足够的空间评论我写这一切。 :)