我有一个数据库,可以记录员工参加课程的时间以及下次参加课程的时间(课程往往是年度课程).
例如,以下员工于2010年1月1日参加了"1"课程,并且由于课程是年度课程,将于2011年1月1日参加.由于今天是2010年5月20日,课程状态显示为"完成",即他们已经完成了课程,直到明年才需要再做一遍:
EmployeeID CourseID AttendanceDate DueDate Status
123456 1 01/01/2010 01/01/2011 Complete
Run Code Online (Sandbox Code Playgroud)
在DueDate我更新员工的记录时,我在SQL中计算这一点,例如DueDate = AttendanceDate + CourseFrequency(我从一个单独的表中提取课程频率).
在我的基于Web的应用程序(asp.net mvc)中,我为所有员工提取这些数据,并以类似网格的格式显示,供人力资源经理审核.这使得人力资源部门可以确定谁需要参加课程.
我的问题如下.
以上面的例子为例,假设今天是2011年1月2日.在这种情况下,员工123456现在已经过期了,我想设置Status为Incomplete,以便HR经理可以看到他们需要采取行动,即让员工参与课程.
我可以在数据库中构建一个触发器,在一夜之间运行,Status根据当前日期更新所有员工的字段.从我所看到的,我将需要使用游标循环每一行来修改状态,这被认为是不好的做法/低效或至少要避免的事情,如果你可以???
或者,Status在我从数据库中撤回数据之后,在我将其显示在屏幕上之前,我可以在我的C#代码中计算.这个问题是Status数据库中的内容不一定与屏幕上显示的内容相匹配,这对我来说是完全错误的.
有没有人对这种问题的最佳实践方法有任何建议?
它有帮助,如果我使用游标我怀疑我会在任何给定时间循环超过1000条记录.也许这个数量很小,使用游标是可以的吗?
除非我遗漏了你的解释,否则根本不需要游标:
UPDATE
dbo.YourTable
SET
Status = ‘Incomplete’
WHERE
DueDate < GETDATE()
Run Code Online (Sandbox Code Playgroud)
最好不要为这些记录维护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
Run Code Online (Sandbox Code Playgroud)