SQL Server 2008 - Помогите написать простой триггер INSERT - PullRequest
21 голосов
/ 31 августа 2009

Это с Microsoft SQL Server 2008.

У меня есть 2 таблицы, Employee и EmployeeResult, и я пытаюсь написать простой триггер INSERT для EmployeeResult, который делает это - каждый раз, когда INSERT выполняется в EmployeeResult, например:

(Джек, 200, продажа) (Джейн, 300, маркетинг) (Джон, 400, Инженерное дело)

Должен искать пары Имя, Отдел, например

(Джек, Продажи), (Джейн, Маркетинг), (Джон, Инжиниринг)

в таблице Employee, и если такого сотрудника не существует, вставьте его в таблицу Employee.

Что у меня есть с неизвестными о том, как исправить "???" s:

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 ]

65 голосов
/ 31 августа 2009

Вы хотите воспользоваться вставленной логической таблицей , доступной в контексте триггера. Он соответствует схеме для вставляемой таблицы и включает в себя строки, которые будут вставлены (в триггере обновления у вас есть доступ к вставлен и удален логические таблицы которые представляют новые и оригинальные данные соответственно.)

Таким образом, чтобы вставить пары «Сотрудник / Отдел», которые в настоящее время не существуют, вы можете попробовать что-то вроде следующего.

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
26 голосов
/ 31 августа 2009

cmsjr имел правильное решение.Я просто хотел бы отметить пару вещей для вашего будущего развития триггера.Если вы используете оператор значений в вставке в триггере, есть большая вероятность, что вы делаете не то, что нужно.Триггеры запускаются один раз для каждой партии вставленных, удаленных или обновленных записей.Таким образом, если десять записей были вставлены в один пакет, то триггер срабатывает один раз.Если вы ссылаетесь на данные во вставленных или удаленных данных и используете переменные и предложение values, то вы получите данные только для одной из этих записей.Это вызывает проблемы целостности данных.Это можно исправить с помощью вставки на основе набора, как показано выше в cmsjr, или с помощью курсора.Никогда не выбирайте путь курсора.Курсор в триггере - это проблема с ожиданием, потому что он медленный и может блокировать вашу таблицу на несколько часов.Я удалил курсор из триггера один раз и улучшил процесс импорта с 40 минут до 45 секунд.

Вы можете подумать, что никто не собирается добавлять несколько записей, но это происходит чаще, чем большинство людей, не связанных с базой данных,Не пишите триггер, который не будет работать при всех возможных условиях вставки, обновления, удаления.Никто не собирается использовать метод одной записи за раз, когда им приходится импортировать 1 000 000 целевых записей продаж от нового клиента, обновлять все цены на 10% или удалять все записи от поставщика, чьи продукты вы больше не продаете.

2 голосов
/ 30 мая 2011

проверьте этот код:

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
...