2010-05-20 18 views
0

我有一个数据库,用于记录员工参加课程以及下一次参加课程时的情况(课程倾向于每年一次)。关于在更新数据库时避免使用游标的软件/数据库设计建议

举例来说,下列员工于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)中,我将所有员工的这些数据都拉回来,并以格式显示给HR经理审查。这使得人力资源部可以确定谁需要参加课程。

我遇到的问题如下。

以上面的例子中,假设今天是2011年第二届一月在这种情况下,员工123456现在逾期的过程中,我想设置Status不完备性,使人力资源经理可以看到,他们需要采取行动这也就是让员工参加课程。

我可以在数据库中建立一个触发器,在一夜之间运行,以根据当前日期更新所有员工的Status字段。从我读过的,我将需要使用游标来循环每一行来修改状态,这被认为是不好的做法/效率低下或至少要避免,如果你可以?

或者,我可以在从数据库中拉回数据之后,在屏幕上显示数据之前,在我的C#代码中计算Status。与此相关的问题是数据库中的Status不一定与屏幕上显示的内容相匹配,这对我来说显然是错误的。

有没有人对这个问题的最佳实践方法有任何建议?

它有帮助,如果我确实使用了游标,我怀疑我会在任何给定时间循环超过1000条记录。也许这是如此小的体积,使用游标可以吗?

回答

5

除非我失去了从你的解释的东西,就没有必要游标都:

UPDATE 
    dbo.YourTable 
SET 
    Status = ‘Incomplete’ 
WHERE 
    DueDate < GETDATE() 

这将是最好不要完全保留这些记录的DueDate或Status。我woudl希望看到员工,当然,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 
+0

我刚回来,更新我的问题说,现在我已经意识到我根本不需要游标,但你战胜保持同步我来吧!像你的想法没有维护截止日期或状态 - 我想我会尝试更新我的SQL为此。非常感谢。 – 2010-05-20 10:53:13

+0

后续问题 - 你是否建议不要在数据库中拥有状态和管理权限,因为你认为这是一种更好的做事方式,或者因为它更高效,因为我不需要将数据存储在数据库中,随时随地需要数据? – 2010-05-20 10:55:55

+0

应避免存储您可以轻松并有效地从现有数据中派生的内容。在某些情况下,您可能想要完全相反,但始终应该正常化。 会推荐阅读关于关系理论和规范化的介绍,应该有助于澄清为什么您的原始计划可能是一个坏主意。 – 2010-05-21 04:06:12

0

我不会为此使用触发器,但可能安排一项工作,可能在SQL服务器中。游标这里不需要要么,当然这只是:

UPDATE TABLE SET Status = 'Incomplete' WHERE DueDate < GetDate() 
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 
)