如何在一周内只用 10 个输入来制作触发器

How to make trigger with only 10 inputs in one week

我想做一个trigger,检查employee是否在一周内不超过10个questionid's(满足table)。 员工在一周(7 天)内不得回答超过 10 个问题。 这可能吗?

Contentmenttable: employeeid, questionid, date, score

我正在为如何获得每周功能而苦恼。

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 满足 table:

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 到它。

问题是当某些员工已经达到最大问题数并插入新问题时会发生什么。你应该提出错误并拒绝新记录吗?或者不更改此 table 并将插入内容写入不同的 table?或者别的什么?我假设你想要 rise an error。在这种情况下,在触发器中我们需要计算周边界并获取现在插入的所有员工的数据(问题计数)(您可以一次插入多行并且触发器将仅触发一次,所有新行都插入伪 table).在这种情况下,您的触发器可能看起来像这样:

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

更新:如果 table 中的行将仅一一插入,则可以简化代码。此外,它还允许通过输入不在当前周的过去日期的行来解决差异。简化的触发器可能是这样的:

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