我创建了这个表:
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id =OBJECT_ID(N'[dbo].[czlonkowie_jednostek]') AND type IN (N'U'))
BEGIN
CREATE TABLE [dbo].[czlonkowie_jednostek]
(
[id_czlonkostwa] [int] IDENTITY(1,1) NOT NULL,
[id_uzytkownika] [int] NOT NULL,
[id_jednostki] [int] NOT NULL,
[data_od_przynaleznosci] [date],
[data_do_przynaleznosci] [date]
) ON [PRIMARY]
END
其中id_uzytkownika和id_jednostki是外键。
还有一个触发器负责检查新插入的id_uzytkownika是否与此id_uzytkownika的早期记录的时间不一致:
IF EXISTS (SELECT name FROM sys.triggers
WHERE Name = 'PilnujCzlonkowJednostki')
DROP TRIGGER PilnujCzlonkowJednostki
GO
CREATE TRIGGER PilnujCzlonkowJednostki
ON [dbo].[czlonkowie_jednostek]
FOR INSERT
AS
DECLARE @wstawiany_poczatek date
DECLARE @wstawiany_koniec date
DECLARE @wstawiany_czlonek int
DECLARE @ile int
-- czy tylko 1 czlonkostwo
SELECT @ile = COUNT(*) FROM inserted
IF @ile > 1
BEGIN
raiserror ('wstawienie wiecej niz jednego czlonka jednoczesnie zabronione - anulowano!',16,1)
rollback
return
END
SELECT
@wstawiany_czlonek = id_uzytkownika,
@wstawiany_poczatek = data_od_przynaleznosci,
@wstawiany_koniec = data_do_przynaleznosci
FROM
inserted
--przeglad istniejacych wpisow
DECLARE @czlonek_baza int
DECLARE @poczatek_baza date
DECLARE @koniec_baza date
DECLARE kursor CURSOR FOR
SELECT id_uzytkownika, data_od_przynaleznosci,data_do_przynaleznosci
FROM czlonkowie_jednostek
OPEN kursor
FETCH NEXT FROM kursor
INTO @czlonek_baza, @poczatek_baza, @koniec_baza;
WHILE @@FETCH_STATUS = 0
BEGIN
IF ((@wstawiany_czlonek = @czlonek_baza AND (@wstawiany_poczatek between @poczatek_baza and @koniec_baza))
OR
(@wstawiany_czlonek = @czlonek_baza AND (@wstawiany_koniec between @poczatek_baza and @koniec_baza))
OR
(@wstawiany_czlonek = @czlonek_baza AND (@wstawiany_poczatek <= @poczatek_baza and @wstawiany_koniec >= @koniec_baza)))
BEGIN
raiserror('Wstawiany czlonek jest czlonkiem innej jednostki w tym samym czasie!',16,1)
rollback
CLOSE kursor
DEALLOCATE kursor
return
END
FETCH NEXT FROM kursor
INTO @czlonek_baza, @poczatek_baza, @koniec_baza;
END
CLOSE kursor
DEALLOCATE kursor
GO
在执行触发器脚本期间,一切看起来都很好不幸的是,当我试图将记录记录到TABLE [dbo]。[czlonkowie_jednostek]时,尽管表格为空,但触发器似乎执行IF语句。
我想插入的代码:
INSERT INTO [dbo].[czlonkowie_jednostek] ([id_uzytkownika],[id_jednostki],[data_od_przynaleznosci],[data_do_przynaleznosci])
VALUES(13,2,'1997-09-01','2000-08-31')
我收到服务器的响应:
Msg 50000,Level 16,State 1,Procedure PilnujCzlonkowJednostki,Line 257 Wstawiany czlonek jest czlonkiem innej jednostki w tym samym czasie! 消息3609,级别16,状态1,行213 交易在触发器中结束。批次已中止。
你能看到我错过了什么吗?
答案 0 :(得分:0)
执行插入后触发器会触发,因此当您循环遍历dbo.czlonkowie_jednostek记录时,您尝试插入的行也会被处理。 所以我会选择这样的东西(删除CURSOR):
ALTER TRIGGER PilnujCzlonkowJednostki
ON [dbo].[czlonkowie_jednostek]
FOR INSERT
AS
BEGIN
DECLARE @inserted_id_czlonkostwa INT
SELECT @inserted_id_czlonkostwa = IDENT_CURRENT('dbo.czlonkowie_jednostek')
DECLARE @wstawiany_poczatek date
DECLARE @wstawiany_koniec date
DECLARE @wstawiany_czlonek int
DECLARE @ile INT
-- czy tylko 1 czlonkostwo
SELECT @ile = COUNT(*) FROM inserted
IF @ile > 1
BEGIN
raiserror ('wstawienie wiecej niz jednego czlonka jednoczesnie zabronione - anulowano!',16,1)
rollback
return
END
SELECT
@wstawiany_czlonek = id_uzytkownika,
@wstawiany_poczatek = data_od_przynaleznosci,
@wstawiany_koniec = data_do_przynaleznosci
FROM
INSERTED
PRINT @inserted_id_czlonkostwa
IF EXISTS(SELECT *
FROM czlonkowie_jednostek cj
WHERE ((@wstawiany_czlonek = cj.id_uzytkownika AND (@wstawiany_poczatek between cj.data_od_przynaleznosci and cj.data_do_przynaleznosci))
OR
(@wstawiany_czlonek = cj.id_uzytkownika AND (@wstawiany_koniec between cj.data_od_przynaleznosci and cj.data_do_przynaleznosci))
OR
(@wstawiany_czlonek = cj.id_uzytkownika AND (@wstawiany_poczatek <= cj.data_od_przynaleznosci and @wstawiany_koniec >= cj.data_do_przynaleznosci))
)
AND cj.id_czlonkostwa <> @inserted_id_czlonkostwa
)
BEGIN
raiserror('Wstawiany czlonek jest czlonkiem innej jednostki w tym samym czasie!',16,1)
rollback
return
END
END
GO