例如: 如果经理A在2016年1月1日11:00到14:00与员工1有约定, 那么如果员工2(或其他员工)试图在2016年1月1日13:00到16:00之间预约,则不允许。
注:这是关于设计表格,所以不鼓励使用触发器/存储过程等方法。
不必插入范围,而是可以插入时间片段。您可以将时间片段设置为任意宽度,但假装您每次只能预订30分钟的经理。要从11:30到12:00预订,请插入具有时间值11:30的行。要从11:30到12:30预订,则需插入两行,一行在11:30,另一行在12:00。然后,您只需使用主键约束或唯一约束来防止超订。
create table appointment_booking (
manager char not null,
startSlice DateTime,
visiting_employee varchar2(255),
primary key (manager, startSlice)
)
检查约束 + 函数(这是我能够接近DDL答案的方式)
您可以创建一个标量函数 - "SCHEDULE_OPENING_EXISTS()",它以开始时间、结束时间和员工ID作为输入,并输出true或false。
然后,您可以在表上创建一个检查约束。
CREATE TABLE...
WITH CHECK ADD CONSTRAINT OPENING_EXISTS
CHECK (SCHEDULE_OPENING_EXISTS(begin, end, employeeID)) = 'True')
触发器:
我尽量避免使用触发器。它们本身并不是邪恶的,但它们确实给应用程序增加了新的复杂度层面。如果你无法避免使用触发器,你需要一个INSTEAD OF INSERT,以及一个INSTEAD OF UPDATE(大概率)。参考Technet:https://technet.microsoft.com/en-us/library/ms179288%28v=sql.105%29.aspx
请记住,如果您拒绝插入/更新尝试,您需要决定是否以及如何将其通知给用户。
存储过程/用户界面:
存储过程是否适用于您的情况?以下是一个示例场景:
用户界面--用户需要查看他们预约的人员的日程安排。
从用户界面--尝试使用存储过程进行插入/更新。在最后一分钟重新检查开放情况(如果开放不存在则返回失败),然后有条件地插入/更新(返回成功消息)。
我认为这些类型的问题很有趣,因为在设计数据库时,了解将与您的数据库交互的应用程序的要求非常重要。
话虽如此,只要应用程序可以引用多个表,我认为 Chris Steele 的回答是一个很好的起点,我会在其基础上进行改进...
我需要两个表。第一个表将一天分成几个部分(切片),具体取决于组织的业务需求。每个切片都将是该表的主键。我个人会选择15分钟的时间段,相当于96个日段。该表中的每个日段都将有“块开始”和“块结束”时间,当用户选择实际开始时间和实际结束时间以进行会议安排时,调度应用程序将引用这些时间。应用程序需要应用逻辑(例如,在3个“AND”语句之间插入两个“OR”运算符),以查看特定的 blockID 是否将被插入到您的约会表中:
这与Chris Steele的答案略有不同,因为它使用了两个表。实际时间戳仍然可以插入到您的应用程序表中,但只有在与TimeBlocks表进行比较时才对它们应用逻辑。在我的约会表中,我更喜欢将日期分解为组成部分,以进行跨平台分析(我们的组织使用多个RDBMS以及SAS进行分析):
CREATE TABLE TimeBlocks (
blockID Number(X) NOT NULL,
blockStart DateTime NOT NULL,
blockEnd DateTime NOT NULL,
primary key (blockID)
);
CREATE TABLE Appointments (
mgrID INT NOT NULL,
yr INT NOT NULL,
mnth INT NOT NULL,
day INT NOT NULL,
blockID INT NOT NULL,
ApptStart DateTime NOT NULL,
ApptEnd DateTime NOT NULL
empID INT NOT NULL,
primary key (mgrID, yr, mnth, day, blockID),
CONSTRAINT timecheck
check (ApptStart < ApptEnd)
);