桌子ApprovedLeave
列名:
EmployeeID (int)
Leave(varchar(MAX))
Approved(bit)
我想将Leave
列设置为唯一,以便用户不能两次输入相同的日期。我不能将员工 ID 作为主键,因为同一员工可以多次请假
桌子ApprovedLeave
列名:
EmployeeID (int)
Leave(varchar(MAX))
Approved(bit)
我想将Leave
列设置为唯一,以便用户不能两次输入相同的日期。我不能将员工 ID 作为主键,因为同一员工可以多次请假
创建日期列。SQL Server 2008 有一个新的date
数据类型,而不是使用datetime
. 不要使用 avarchar(max)
来表示日期。
LeaveDate ( date )
现在您的主键必须包含新列。
alter table ApprovedLeave add constraint PK_ApprovedLeave primary key ( EmployeeID, LeaveDate );
/* don't forget to drop it if already exists */
这意味着您可以为同一员工输入多条记录,但不能在同一日期输入。
既然您说 Leave 代表一个日期范围,您可以将您的表格表示为
EmployeeID int
LeaveStart date
LeaveEnd date
Approved bit
...并使 EmployeeID、LeaveStart 和 LeaveEnd 成为复合唯一索引的组成部分。
但这只能解决您真正问题的一部分,即您不希望员工在重叠的时间段休假。(完全相同的开始日期和结束日期是重叠的特例)。考虑这些记录:
Employee ID = 101, LeaveStart = 1/1/2012, LeaveEnd = 2/1/2012
Employee ID = 101, LeaveStart = 1/1/2012, LeaveEnd = 2/2/2012
这将满足您的独特约束,但仍然是非常错误的。
您可以使用触发器或涉及 UDF 的约束或通过调用程序中非常仔细的业务逻辑来解决此问题,但索引是不够的。
基于 doublesharp 的答案,您必须将 Leave 列数据类型转换为 datetime。根据该列中已经存在的日期值的格式,您将不得不稍微调整代码以处理格式:
-- // Add new column using correct data type
alter table [tablename] add Leave_New datetime not null
go
-- // populate it from existing column:
update [tablename] set Leave_New = convert(datetime, [Leave], 1)
go
-- // Add the unique constraint:
ALTER TABLE [tablename]
ADD CONSTRAINT [unique_leave] UNIQUE NONCLUSTERED
(
[EmployeeID], [Leave_new]
)
-- // After you verify that the above is successful, you can drop the old column, and rename the new one:
alter table [tablename] drop column [Leave]
go
exec sp_RENAME '[tablename].Leave_New', 'Leave' , 'COLUMN'
您需要UNIQUE CONSTRAINT
在多列上使用 a -EmployeeID
和Leave
. 仅将Leave
列设置为唯一意味着它将被强制执行EmployeeID
,而我假设您希望允许不同的员工使用相同的Leave
日期。
ALTER TABLE [tablename]
ADD CONSTRAINT [unique_leave] UNIQUE NONCLUSTERED
(
[EmployeeID], [Leave]
)