Sql server 如何使用触发器基于另一个表的行向表中插入行?

Sql server 如何使用触发器基于另一个表的行向表中插入行?,sql-server,tsql,triggers,bulkinsert,Sql Server,Tsql,Triggers,Bulkinsert,我有三张桌子: 雇员 Id FirstName LastName EmployeeTasksId 员工任务 Id EmployeeId EmployeeTaskDefinitionId 雇员任务定义 Id Description etc. 我要做的是,一旦将员工插入Employees表,我需要根据插入的员工Id和每个EmployeeTaskDefinition的Id将行插入EmployeeTasks表 例如: Id为1的员工被插入到员工表中 EmployeeTaskDefinitions表

我有三张桌子:

雇员

Id
FirstName
LastName
EmployeeTasksId
员工任务

Id
EmployeeId
EmployeeTaskDefinitionId
雇员任务定义

Id
Description
etc.
我要做的是,一旦将员工插入Employees表,我需要根据插入的员工Id和每个EmployeeTaskDefinition的Id将行插入EmployeeTasks表

例如:

Id为1的员工被插入到员工表中 EmployeeTaskDefinitions表有6行,ID为1-6 在此插入之后,EmployeeTasks表需要有6行:

Id = 1, EmployeeId = 1, EmployeeTaskDefinitonId = 1    
Id = 2, EmployeeId = 1, EmployeeTaskDefinitonId = 2     
Id = 3, EmployeeId = 1, EmployeeTaskDefinitonId = 3      
Id = 4, EmployeeId = 1, EmployeeTaskDefinitonId = 4      
Id = 5, EmployeeId = 1, EmployeeTaskDefinitonId = 5      
Id = 6, EmployeeId = 1, EmployeeTaskDefinitonId = 6    
现在我读了很多关于游标的帖子,大多数人都说,在这个任务中使用游标是一种不好的做法。但是你会怎么做呢?注意:除了触发器,我不想使用其他任何东西

编辑:这是我提出的查询

CREATE TRIGGER CreateEmployee 
    ON [dbo].[EmployeeSet]
    AFTER INSERT
AS
    DECLARE @LoopCounter int, @MaxSettingDefinitionId int, @Id int
    SELECT @LoopCounter = MIN(Id), @MaxSettingDefinitionId = MAX(Id)
    FROM SettingsDefinitionSet

    WHILE(@LoopCounter IS NOT NULL AND @LoopCounter <= @MaxSettingDefinitionId)
    BEGIN
        SELECT @Id = Id FROM SettingDefinitionSet
        WHERE Id = @LoopCounter
        INSERT INTO SettingSet(CompanyId, EmployeeId, SettingDefinitionId, SettingType, State, Value)
        VALUES((SELECT CompanyId FROM inserted), (SELECT Id FROM inserted), 
                @Id, 
                (SELECT SettingType FROM SettingSet WHERE EmployeeId IS NULL AND CompanyId = (SELECT CompanyId FROM inserted) AND SettingDefinitionId = @Id), 
                (SELECT State FROM SettingSet WHERE EmployeeId IS NULL AND CompanyId = (SELECT CompanyId FROM inserted) AND SettingDefinitionId = @Id), 
                (SELECT Value FROM SettingSet WHERE EmployeeId IS NULL AND CompanyId = (SELECT CompanyId FROM inserted) AND SettingDefinitionId = @Id))
        SELECT @LoopCounter = MIN(Id) FROM SettingDefinitionSet
        WHERE Id > @LoopCounter
    END
GO

这应该可以做到:

INSERT INTO EmployeeTasks(EmployeeId, EmployeeTaskDefinitionId)
SELECT inserted.id as EmployeeId, t.id as EmployeeTaskDefinitionId
    FROM inserted JOIN EmployeeTaskDefinitions
正如我在评论中所指出的,Employee表是错误的规范化表,不应该有EmployeeTasksId。如果要自动向新员工添加某些任务,请执行以下操作:

alter table EmployeeTaskDefinitions
add DefaultTask bit not null default 0
--update EmployeeTaskDefinitions set DefaultTask = 1 where...
--now create a trigger
create trigger trEmployee_i
on dbo.Employee after insert
as
begin
set nocount on
insert EmployeeTasks(EmployeeId,EmployeeTaskDefinitionId)
select i.id,td.id
from inserted i cross join EmployeeTaskDefinitions td
where td.DefaultTask = 1
end

备注:我希望EmployeeTasks.Id是身份栏

这个去哪儿了?进入AS和GO关键字之间的触发器正文?是的,在触发器正文中,触发器内的游标是SQL Server中的最终“否”。触发器在导致其触发的语句的上下文中执行,并且该语句在触发器完成之前不会完成。因此,触发器必须保持小、灵活、快速—不要在触发器内部执行任何繁重的操作、大量计算、外部调用web服务、不要从触发器内部发送电子邮件等—并且在该上下文中使用游标是您可以提交的最终性能sin。。。别这样!曾经别担心,伙计。但有一个问题是,如果sql查询的大小太大,是否同样适用?我提出了一个有效的查询,但我不确定它是否太大。关于这个问题,请看我的答案。注意,我仍然会对查询进行一些优化。首先,Employee表模式是错误的。EmployeeTaskId不应该在那里。考虑一下当一个雇员有好几个任务时会发生什么。很抱歉,在我输入问题的时候,我只是想了一下这三个表。事实上,我的DB模式要复杂得多,所以我不想在这里显示实际情况,因为这会使我无法集中精力解决实际问题。您是否阅读了我对您评论的回复?我上面描述的这三个表并不在我的模式中,我只是想到了它们,因为我真正的模式要复杂得多。我已经提出了一个有效的查询,但我不确定它是否太复杂,或者没有看到我编辑的查询问题。我只是在你发布的片段中演示如何解决问题。