我有一个数据库,可以记录员工参加课程以及下次参加课程的时间(课程往往是年度课程)。
例如,以下员工于2010年1月1日参加了“1”课程,并且该课程是每年一次,将于2011年1月1日参加。截至今天是2010年5月20日,课程状态显示为'完成'即他们已经完成了课程,并且在明年之前不需要再做一次:
EmployeeID CourseID AttendanceDate DueDate Status
123456 1 01/01/2010 01/01/2011 Complete
就DueDate
而言,我在更新员工记录时在SQL中对此进行计算,例如DueDate = AttendanceDate + CourseFrequency(我从一个单独的表中提取课程频率)。
在我的基于网络的应用程序(asp.net mvc)中,我为所有员工提取这些数据,并以类似网格的格式显示,供人力资源经理审核。这使人力资源部门能够确定需要参加课程的人员。
我遇到的问题如下。
以上面的例子为例,假设今天是2011年1月2日。在这种情况下,员工123456现在已经过期了,我想将Status
设置为Incomplete,以便HR经理可以看到他们需要采取行动,即让员工参加课程。
我可以在数据库中构建一个触发器,以便在一夜之间运行,根据当前日期更新所有员工的Status
字段。根据我的阅读,我需要使用游标来遍历每一行以修改状态,这被认为是不好的做法/效率低下或至少要避免的事情,如果你可以???
或者,在我从数据库中撤回数据之后,在我在屏幕上显示数据之前,我可以在我的C#代码中计算Status
。这个问题是数据库中的Status
不一定与屏幕上显示的内容相匹配,这对我来说是错误的。
有没有人对这种问题的最佳实践方法有任何建议?
这有帮助,如果我使用了游标,我怀疑在任何给定时间我都会循环超过1000条记录。也许这个数量很小,使用游标是可以的吗?
答案 0 :(得分:5)
除非我遗漏了你的解释,否则根本不需要游标:
UPDATE
dbo.YourTable
SET
Status = ‘Incomplete’
WHERE
DueDate < GETDATE()
最好不要为这些记录维护DueDate或Status。我希望看到Employee,Course,EmployeeCourse和EmployeeCourseAttendance表,您可以使用以下表格:
-- Employees that haven't attended a course
-- within dbo.Course.Frequency of current date
SELECT
ec.EmployeeID
, ec.CourseID
, eca.LastAttendanceDate
, DATEADD(day, c.Frequency, eca.LastAttendanceDate) AS DueDate
FROM
dbo.EmployeeCourse ec
INNER JOIN
dbo.Course c
LEFT OUTER JOIN
ebo.EmployeeCourseAttendance eca
ON eca.EmployeeID = ec.EmployeeId
AND eca.CourseID = ec.CourseID
WHERE
GETDATE() > DATEADD(day, c.Frequency, eca.LastAttendanceDate)
-- Show all employees and status for each course
SELECT
ec.EmployeeID
, ec.CourseID
, eca.LastAttendanceDate
, DATEADD(day, c.Frequency, eca.LastAttendanceDate) AS DueDate
, CASE
WHEN eca.LastAttendanceDate IS NULL THEN 'Has not attended'
WHEN (GETDATE() > DATEADD(day, c.Frequency, eca.LastAttendanceDate) THEN 'Incomplete'
WHEN (GETDATE() < DATEADD(day, c.Frequency, eca.LastAttendanceDate) THEN 'Complete'
END AS Status
FROM
dbo.EmployeeCourse ec
INNER JOIN
dbo.Course c
LEFT OUTER JOIN
ebo.EmployeeCourseAttendance eca
ON eca.EmployeeID = ec.EmployeeId
AND eca.CourseID = ec.CourseID
答案 1 :(得分:1)
您还可以使用计算列表达式。这样您就不必更新STATUS
列/使其与日期保持同步
create table coureses
(
employeeid int not null,
courseid int not null,
attendancedate datetime null,
duedate datetime null,
[status] as case
when duedate is null and attendancedate is null then 'n/a'
when datediff(day,duedate, getdate()) > 0 then 'Incomplete'
when datediff(day,attendancedate, getdate()) > 0 then 'Complete'
else 'n/a'
end
)
答案 2 :(得分:0)
我不会为此使用触发器,而是安排作业,可能在SQL服务器中。这里也不需要光标,当然只是:
UPDATE TABLE SET Status = 'Incomplete' WHERE DueDate < GetDate()