SQL Server 2008 - 帮助编写简单的INSERT触发器

时间:2009-08-31 05:26:50

标签: sql sql-server-2008 insert triggers

这适用于Microsoft SQL Server 2008。

我有两个表,Employee和EmployeeResult,我正在尝试在EmployeeResult上编写一个简单的INSERT触发器来执行此操作 - 每次INSERT都在EmployeeResult中完成,例如:

(杰克,200,销售) (简,300,市场营销) (John,400,Engineering)

它应该查找Name,Department条目对,例如

(杰克,销售), (Jane,Marketing), (John,Engineering)

在Employee表中

,如果这样的员工不存在,应该将其插入到Employee表中。

我所拥有的是关于如何修复“???”的未知数:

CREATE TRIGGER trig_Update_Employee
ON [EmployeeResult]
FOR INSERT
AS
IF EXISTS (SELECT COUNT(*) FROM Employee WHERE ???)
  BEGIN
   INSERT INTO [Employee] (Name, Department) VALUES (???, ???)
  END

请提前帮助,请提供帮助

架构:

Employee
--------
Name, varchar(50)
Department, varchar (50)

EmployeeResult
--------------
Name, varchar(50)
Salary, int
Department, varchar (50)

3 个答案:

答案 0 :(得分:64)

您希望利用触发器上下文中可用的插入逻辑表。它与正在插入的表格的架构相匹配,并包含将要插入的行(在更新触发器中,您可以访问插入已删除逻辑表分别代表新数据和原始数据。)

因此,要插入当前不存在的Employee / Department对,您可以尝试以下内容。

CREATE TRIGGER trig_Update_Employee
ON [EmployeeResult]
FOR INSERT
AS
Begin
    Insert into Employee (Name, Department) 
    Select Distinct i.Name, i.Department 
    from Inserted i
    Left Join Employee e
    on i.Name = e.Name and i.Department = e.Department
    where e.Name is null
End

答案 1 :(得分:26)

cmsjr有正确的解决方案。我只是想为你未来的触发器开发指出一些事情。如果您在触发器的插入中使用values语句,那么您可能会犯错误。对于插入,删除或更新的每批记录,触发一次触发。因此,如果在一个批次中插入十个记录,则触发器会触发一次。如果要引用插入或删除的数据并使用变量和values子句,那么您将只获取其中一条记录的数据。这会导致数据完整性问题。您可以通过使用基于集合的插入来解决此问题,如上面显示的cmsjr或使用游标。不要选择光标路径。触发器中的光标是一个等待发生的问题,因为它们很慢并且可能会将您的表锁定几个小时。我从触发器中删除了一次光标,并将导入过程从40分钟改为45秒。

您可能认为没有人会添加多条记录,但它比大多数非数据库人员意识到的更频繁。不要编写在所有可能的插入,更新,删除条件下都不起作用的触发器。当他们必须从新客户导入1,000,000个销售目标记录或将所有价格更新10%或删除其产品不再销售的供应商的所有记录时,没有人会一次使用一个记录方法。

答案 2 :(得分:2)

检查此代码:

CREATE TRIGGER trig_Update_Employee ON [EmployeeResult] FOR INSERT AS Begin   
    Insert into Employee (Name, Department)  
    Select Distinct i.Name, i.Department   
        from Inserted i
        Left Join Employee e on i.Name = e.Name and i.Department = e.Department
        where e.Name is null
End