Как сделать триггер только с 10 входами в неделю - PullRequest
0 голосов
/ 19 ноября 2018

Я хочу сделать trigger, который проверяет, имеет ли employee не более 10 questionid's в неделю (в таблице содержания). Сотрудник не может отвечать более чем на 10 вопросов в неделю (7 дней). Возможно ли это?

Contentmenttable : сотрудник, вопрос, дата, оценка

Я изо всех сил пытаюсь получить еженедельную функцию.

Create table скрипт удовлетворенность :

create table contentment
(
employeeid int,
questionid int,
date date,
score char(5) not null,

constraint pk_contentment primary key (medewerkernr, vraagid, datum),
constraint fk_contentment_employeeid foreign key (employeeid) references employee(employeeid),
constraint fk_contentment_questionid foreign key (questionid) references question(questionid),
)

Inserts Содержание Таблица:

1,1, '10-11-2018', null
2,1, '10-11-2018', null
2,2, '11-11-2018', null
2,3, '12-11-2018', null
2,4, '13-11-2018', null
2,5, '14-11-2018', null

Null, потому что employee нужно добавить score к нему.

1 Ответ

0 голосов
/ 19 ноября 2018

Вопрос в том, что должно произойти, если какой-либо сотрудник уже достиг максимального количества вопросов и вставлен новый. Должны ли вы поднять и ошибка и отклонить новую запись? Или не меняете эту таблицу и не пишите вставку в другую таблицу? Или что-нибудь еще? Я предполагаю, что вы хотите вызвать ошибку . В этом случае в триггере нам нужно вычислить границы недели и извлечь данные (количество вопросов) для всех сотрудников, вставленных сейчас (вы можете вставить несколько строк одновременно, и триггер сработает только один раз со всеми новыми строками во вставленной псевдотаблице) , В этом случае ваш триггер может выглядеть примерно так:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE TRIGGER [dbo].[Contentmenttable_AfterInsert]
   ON [dbo].[Contentmenttable]
   AFTER INSERT
AS 
BEGIN
    SET NOCOUNT ON;

    SET DATEFIRST 1; -- Make Monday first day of the week

    declare @StartOfTheWeek date, @StartOfNextWeek date, @QuestionsCount int, @EmployeeId int

    -- datetiff calculates the number of whole weeks between current date and some other "zero" date
    --  dateadd add back this number of whole weeks to this "zero" date to get the beginning of the current week.
    select @StartOfTheWeek = dateadd(wk, datediff(wk, 0, getdate()), 0)
    set @StartOfNextWeek = dateadd(day, 7, @StartOfTheWeek)

    -- Get the employee with the highest number of questions returned by the derived table bellow
    select top 1 @QuestionsCount = q.QuestionCount, @EmployeeId = q.EmployeeId
    from (
        -- Calculate number of questions per affected employee for current week
        select count(distinct questionid) as QuestionCount, t.EmployeeId
        from [dbo].[Contentmenttable] t
        -- inserted pseudo table contains the rows that were added to the table
        -- it may contain multiple rows for different employees if we are inserting more than one row at once
        -- e.g. insert into Contentmenttable values(1, 111, '20180101', 0), (2, 222, '20180101', 0)
        where t.EmployeeId in (select EmployeeId from inserted)
          and t.[Date] >= @StartOfTheWeek and t.[Date] < @StartOfNextWeek
        group by t.EmployeeId
    ) q
    order by QuestionsCount desc

    -- If the highest number of questions is more than 10, raise an error and rollback the insert
    if (@QuestionsCount > 10)
        raiserror('EmployeeId %d already has 10 questions this week.', 16, 1, @EmployeeId)
END
GO

ОБНОВЛЕНИЕ: Если строки в таблице будут вставляться только одна за другой, код может быть упрощен. Также это позволит устранить несоответствие с вводом строк за прошлые даты, которых нет на текущей неделе. Упрощенный триггер может выглядеть примерно так:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE TRIGGER [dbo].[Contentmenttable_AfterInsert]
   ON [dbo].[Contentmenttable]
   AFTER INSERT
AS 
BEGIN
    SET NOCOUNT ON;

    if (select count(*) from inserted) > 1
        raiserror('Rows in this table should inserted only one by one.', 16, 1)

    SET DATEFIRST 1; -- Make Monday first day of the week

    declare @StartOfTheWeek date, @StartOfNextWeek date, @QuestionsCount int, @EmployeeId int, @Date date

    select @EmployeeId = EmployeeId, @Date = [Date]
    from inserted

    -- datetiff calculates the number of whole weeks between current date and some other "zero" date
    -- dateadd add back this number of whole weeks to this "zero" date to get the beginning of the current week.
    select @StartOfTheWeek = dateadd(wk, datediff(wk, 0, @Date), 0)
    set @StartOfNextWeek = dateadd(day, 7, @StartOfTheWeek)

    -- Calculate number of questions per affected employee for current week
    select @QuestionsCount = count(questionid)
    from [dbo].[Contentmenttable] t
    where t.EmployeeId = @EmployeeId
      and t.[Date] >= @StartOfTheWeek and t.[Date] < @StartOfNextWeek

    -- If the highest number of questions is more than 10, raise an error and rollback the insert
    if (@QuestionsCount > 10)
        raiserror('EmployeeId %d already has 10 questions this week.', 16, 1, @EmployeeId)
END
GO
...