有关软件/数据库设计的建议,以避免在更新数据库时使用游标

Ale*_*x P 0 sql-server cursor

我有一个数据库,可以记录员工参加课程的时间以及下次参加课程的时间(课程往往是年度课程).

例如,以下员工于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条记录.也许这个数量很小,使用游标是可以的吗?

Mar*_*ith 5

除非我遗漏了你的解释,否则根本不需要游标:

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)