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模式要复杂得多,所以我不想在这里显示实际情况,因为这会使我无法集中精力解决实际问题。您是否阅读了我对您评论的回复?我上面描述的这三个表并不在我的模式中,我只是想到了它们,因为我真正的模式要复杂得多。我已经提出了一个有效的查询,但我不确定它是否太复杂,或者没有看到我编辑的查询问题。我只是在你发布的片段中演示如何解决问题。