Рекомендации по разработке программного обеспечения / базы данных, чтобы избежать использования курсоров при обновлении базы данных - PullRequest
0 голосов
/ 20 мая 2010

У меня есть база данных, в которую заносится информация о том, когда сотрудник посещал курс и когда он в следующий раз должен посетить этот курс (курсы обычно бывают ежегодными).

Например, следующий сотрудник прослушал курс «1» 1 января 2010 года и, поскольку курс является ежегодным, следующий должен пройти 1 января 2011 года. Как и сегодня, 20 мая 2010 года, статус курса читается как « Завершите », то есть они прошли курс и не должны делать это снова до следующего года:

EmployeeID    CourseID    AttendanceDate    DueDate     Status
123456        1           01/01/2010        01/01/2011  Complete

В терминах DueDate я вычисляю это в SQL при обновлении записи сотрудника, например, DueDate = AttendanceDate + CourseFrequency (я определяю частоту курса из отдельной таблицы).

В моем веб-приложении (asp.net mvc) я извлекаю эти данные для всех сотрудников и отображаю их в виде таблицы, которую могут просматривать менеджеры по персоналу. Это позволяет HR определить, кому нужно идти на курсы.

У меня проблема в следующем.

Используя приведенный выше пример, предположим, что сегодня 2 января 2011 года. В этом случае сотрудник 123456 теперь запоздал для курса, и я хотел бы установить Status в Неполный, чтобы менеджер по персоналу мог видеть, что ему нужно Действие это, т.е. получить работника на курс.

Я мог бы создать триггер в базе данных для запуска в одночасье, чтобы обновить поле Status для всех сотрудников на основе текущей даты. Из того, что я прочитал, мне нужно будет использовать курсоры , чтобы циклически проходить по каждой строке, чтобы изменить статус, и это считается плохой практикой / неэффективным или, по крайней мере, чем-то, чего следует избегать, если вы можете ???

В качестве альтернативы, я мог бы вычислить Status в своем коде C # после того, как я извлек данные из базы данных и перед тем, как отобразить их на экране. Проблема в том, что Status в базе данных не обязательно будет соответствовать тому, что показано на экране, что мне кажется просто неправильным.

Есть ли у кого-нибудь какие-либо советы относительно наилучшего подхода к решению этой проблемы?

Помогает, если бы я использовал курсор, я сомневаюсь, что зациклился бы над более чем 1000 записями в любой момент времени. Может быть, это такой маленький объем, что использование курсоров нормально?

Ответы [ 3 ]

5 голосов
/ 20 мая 2010

Если я не пропустил что-то из вашего объяснения, курсоры вообще не нужны:

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

Было бы предпочтительнее вообще не указывать дату или статус для этих записей. Я ожидаю увидеть таблицы 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 голос
/ 20 мая 2010

Вы также можете использовать вычисляемое выражение столбца. Таким образом, вам никогда не придется обновлять столбец 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
)
0 голосов
/ 20 мая 2010

Я бы не использовал триггер для этого, но планировал задание, вероятно, на сервере SQL. Курсор здесь не требуется, конечно, это просто:

UPDATE TABLE SET Status = 'Incomplete' WHERE DueDate < GetDate()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...