我正在开发一个用于房间预订的数据库。我希望有一个触发器来检查预订是否存在时间冲突。
第一种情况是定义的时间(在“设置”表中定义),无法进行预订。 ('开始'时间不得在禁止范围内)这已经按预期工作:
CREATE TABLE dbo.einstellungen --setings
(
einst_id varchar(30) CONSTRAINT pk_einstellungen PRIMARY KEY, --setting-id
beschreibung varchar(300) NOT NULL, --description
wert_char varchar(300), --wert = value
wert_int int,
wert_float float,
wert_datetime datetime,
wert_time time,
CONSTRAINT ck_einstellungen_wert
CHECK (wert_char IS NOT NULL
OR wert_datetime IS NOT NULL
OR wert_int IS NOT NULL
OR wert_time IS NOT NULL
OR wert_float IS NOT NULL)
);
INSERT INTO dbo.einstellungen (einst_id, beschreibung, wert_time)
VALUES ('keine_lv_startzeit', 'Ab dieser Uhrzeit können Räume nicht mehr reserviert werden', '22:00:00') --rooms can't be reserved starting from this time
,('keine_lv_endzeit', 'Ab dieser Uhrzeit können Räume reserviert werden', '07:00:00'); --...and ending at this time
GO
CREATE TRIGGER dbo.reservierung_iu --reservations
ON dbo.reservierung --reservations
FOR insert, update
AS
BEGIN;
SET NOCOUNT ON;
DECLARE @sperreanfang TIME(0) = (SELECT wert_time
FROM dbo.einstellungen
WHERE einst_id = 'keine_lv_startzeit'); --begin of "lock"
DECLARE @sperreende TIME(0) = (SELECT wert_time
FROM dbo.einstellungen
WHERE einst_id = 'keine_lv_endzeit'); --end of "lock"
-- Zeitcheck dbo.einstellungen
IF (SELECT COUNT(*) FROM inserted WHERE cast(beginn as time) > @sperreanfang OR cast(beginn as time) < @sperreende) > 0 --Is the Begin time of the new reservation within the "lock time"?
BEGIN;
ROLLBACK; --If yes - abort
DECLARE @errormessage varchar(100) = ('Raumreservierungen sind nur für Zeiten von ' + CAST(@sperreende as varchar(10)) + ' bis ' + cast(@sperreanfang as varchar(10)) + ' möglich.');
THROW 50000, @errormessage , 1;
END;
--some more code which doesn't work as intended
END;
然而,下一部分应该检查房间是否在相同的时间跨度内没有预订两次,以及如果教师为不同的房间预订两次也不起作用 - &gt;即使预订表完全为空,触发器也会始终抛出错误。这些是相关表格和触发器的其余部分:
CREATE TABLE dbo.reservierung
(reservierungs_ID int IDENTITY CONSTRAINT pk_reservierungs_ID PRIMARY KEY, --reservation ID
beginn datetime not null, --begin time of reservation
ende datetime not null, --end time of reservation
lehrender int NOT NULL CONSTRAINT fk_reservierung_lehrender FOREIGN KEY REFERENCES dbo.personal(personalnummer), --teacher ID
lehrveranstaltungen varchar(12) NOT NULL CONSTRAINT fk_reservierung_lehrveranstaltungen FOREIGN KEY REFERENCES dbo.lehrveranstaltungen(Lv_Kürzel), --reference to course (not really relevant here)
raum varchar(20) NOT NULL CONSTRAINT fk_reservierung_räume FOREIGN KEY REFERENCES dbo.räume(raum_ID), -- reference to room
constraint chk_ende check (ende > beginn)
); --reservation can't end before it begins
--INSERT INTO dbo.reservierung(beginn, ende, lehrender, lehrveranstaltungen, raum)
--VALUES('20171201 16:00:00', '20171201 17:00:00', 1, 'CBSGL', 'G.AP147.318'); (example reservation - 1 refers to the teacher, 'CBSGL' is the name of the course)
-
ELSE IF (SELECT COUNT(*) FROM inserted i INNER JOIN dbo.reservierung re ON i.reservierungs_ID = re.reservierungs_ID INNER JOIN dbo.räume ra ON ra.raum_ID = re.raum -- New reservation(s), old reservation, rooms
WHERE ra.raum_ID = i.raum AND ((re.beginn > i.beginn AND re.beginn < i.ende) OR (re.ende > i.beginn AND re.ende < i.ende))) > 0 --are there existing reservations which would overlap with the new one?
BEGIN;
ROLLBACK; -- if yes, abort
THROW 50001, 'Der Raum ist zu dieser Zeit bereits belegt!', 1;
END;
ELSE IF (SELECT COUNT(*) FROM inserted i INNER JOIN dbo.reservierung re ON i.reservierungs_ID = re.reservierungs_ID
WHERE re.lehrender = i.lehrender AND ((cast(re.beginn as time) > cast(DATEADD(minute, -15, i.beginn) as time) AND --is there an existing reservation which begins after the new reservation begins....
cast(re.beginn as time) < cast(DATEADD(minute, 15, i.ende) as time)) -- ... and before it ends (including a 15 minute buffer)
OR (cast(re.ende as time) > cast(DATEADD(minute, -15, i.beginn) as time) AND --or is there an existing reservation which ends after the new one begins...
cast(re.ende as time) < cast(DATEADD(minute, 15, i.ende) as time)))) > 0 --- and before it ends
BEGIN;
ROLLBACK;
THROW 50004, 'Der Lehrende ist zu dieser Zeit nicht verfügbar (Es müssen immer 15 Minuten zwischen Lehrveranstaltungen liegen!', 1;
END;
我尝试了几种不起作用的方法,其中一些我在stackoverflow上发现,我认为非常接近正确的解决方案,这就是为什么我决定在这里创建一个帐户。 我真的很感激任何帮助我更接近解决方案的帮助。