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

26

这是使用 Microsoft SQL Server 2008。

我有两个表,Employee 和 EmployeeResult,我正在尝试在 EmployeeResult 上编写一个简单的 INSERT 触发器,使它可以在每次插入到 EmployeeResult 中时执行以下操作:

(Jack, 200, Sales) (Jane, 300, Marketing) (John, 400, Engineering)

它应该查找 Employee 表中的姓名、部门条目对,例如

(Jack, Sales), (Jane, Marketing), (John, Engineering)

如果不存在这样的员工,则应将其插入到 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个回答

70

您希望利用触发器上下文中提供的“inserted”逻辑表。它符合要插入的表的模式,并包括将要插入的行(在更新触发器中,您可以访问“inserted”和“deleted”逻辑表,分别代表新数据和原始数据)。

因此,为了插入尚不存在的员工/部门对,您可以尝试以下操作。

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

28

cmsjr提供了正确的解决方案。我想指出一些关于您未来触发器开发的问题。如果您在触发器中使用值语句进行插入,那么很可能您正在做错误的事情。触发器会针对每批插入、删除或更新的记录触发一次。因此,如果一批插入了十条记录,则触发器只会触发一次。如果您引用已插入或已删除的数据并使用变量和值子句,则只会获取其中一个记录的数据。这会导致数据完整性问题。您可以通过使用基于集合的插入(如上所示)或使用游标来解决此问题。永远不要选择游标路径。触发器中的游标是一个等待发生问题的问题,因为它们速度较慢,可能会锁定您的表数小时。我曾经从触发器中删除了一个游标,并将导入过程的时间从40分钟缩短到45秒。

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


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接