Отправляет email-рассылки с помощью сервиса Sendsay

Вопросы и ответы по MS SQL Server

  Все выпуски  

Вопросы и ответы по MS SQL Server


Информационный Канал Subscribe.Ru



Вопросы и ответы по MS SQL Server

Выпуск No. 3 от 2003-03-13

Вопрос : Зачем нужны триггеры, и как ими пользоваться?

Ответ:
1. Зачем нужны триггеры.

Повторю неоднократно слышимую мной фразу - триггеры нужны для поддержания целостности базы данных.
Триггер - это блок кода, который выполняется при попытке внесения изменений в таблицу (или представление), для которой он определен. И в нем может быть какой угодно T-SQL код. Обычно в нем пишут код для проверки заполнения полей, связей с другими таблицами. Есть триггеры для протоколирования изменений в таблицах, т.е. при изменении данных в служебную таблицу записываются старые и новые данные. И т.д.

2. Как пользоваться триггерами.

Несколько замечаний:
  • При внесении изменений в таблицу, триггеры выполняются в последнюю очередь, после проверки всякого рода связей и ограничений.

  • Триггер может быть привязан только к одной таблице.

  • У одной таблицы может быть много триггеров разных типов.

  • Триггеры могут быть на добавление, изменение и удаление (insert, update, delete) в любых вариациях.

  • Триггер вызывается на общую команду изменения данных в таблице, т.е. при вызове update для нескольких записей, он не будет выполняться для каждой записи отдельно, а всего один раз.

  • Если в триггере изменяются данные по таблице, к которой привязан триггер, то вся группа триггеров по этой таблице выполняется повторно за исключением этого триггера (если в опциях сервера стоит метка "allow nested triggers").

  • Писать триггеры надо так, чтобы не была важна последовательность их вызова.


  • В теле триггера можно использовать служебные таблицы deleted и inserted.
    При выполнении INSERT таблица deleted будет пустая, а в inserted будут содержаться вставленные записи.
    При выполнении DELETE таблица inserted будет пустая, а в deleted будут содержаться удаленные записи.
    При выполнении UPDATE в deleted содержаться записи до изменения, а в inserted после изменения.

    Для примеров будем использовать таблицы, созданные с помощью следующего скрипта:
    CREATE TABLE Master1
    
    (
    Master1ID int IDENTITY (1,1) NOT NULL,
    Name varchar(200),
    CONSTRAINT PK_Master1 PRIMARY KEY CLUSTERED
    (Master1ID)
    )
    insert Master1 (Name) values('Иванов')
    insert Master1 (Name) values('Петров')
    insert Master1 (Name) values('Сидоров')
    GO


    Создадим триггер на все виды операций и поэкспериментируем с ним:
    CREATE TRIGGER TriggerMaster1 ON [Master1]
    
    FOR INSERT, UPDATE, DELETE
    AS
    SET NOCOUNT ON
    select 'inserted' as Kind, * from inserted
    union all
    select 'deleted' as Kind, * from deleted

    print 'Выход из триггера'
    GO

    Несколько изменений в таблице:
    insert Master1 (Name)
    
    select 'Москвитин'
    union
    select 'Румянцев'
    GO

    update Master1 set Name='Кошкин' where Master1ID in (3,6,7)
    GO

    delete Master1 where Master1ID>3
    GO

    Результат:
    Kind     Master1ID   Name
    
    -------- ----------- ------------------------------
    inserted 4 Москвитин
    inserted 5 Румянцев

    (2 row(s) affected)

    Выход из триггера

    Kind Master1ID Name
    -------- ----------- ------------------------------
    inserted 3 Кошкин
    deleted 3 Сидоров

    (1 row(s) affected)

    Выход из триггера

    Kind Master1ID Name
    -------- ----------- ------------------------------
    deleted 4 Москвитин
    deleted 5 Румянцев

    (2 row(s) affected)

    Выход из триггера

    Обратите внимание на SET NOCOUNT ON в начале тела триггера. Это нужно для того, чтобы команды из тела триггера не возвращали информацию о количестве обработанных строк, и не перебивали тем самым информацию о количестве измененных строк.

    В триггере можно использовать функции UPDATE и COLUMNS_UPDATED для определения полей, в которых изменяются данные. Даже если данные до изменения и после изменения были одни и те же, эти функции покажут, что данные в поле были изменены. Например, функция UPDATE(Field) возвратит True в запросе:
    UPDATE Table SET Field=Field
    


    В SQL Server 2000 появилась возможность определять триггеры для VIEW.

    Еще в SQL Server 2000 появился новый тип триггеров INSTEAD OF. Данный тип триггеров предназначен в первую очередь для представлений (VIEW). Создадим триггер INSTEAD OF INSERT и внесем изменения в таблицу:
    CREATE TRIGGER TriggerInsteadMaster1 ON [Master1]
    
    INSTEAD OF INSERT
    AS
    SET NOCOUNT ON
    print 'Триггер INSTEAD OF'
    GO
    insert Master1 (Name) values ('Фамилия')
    GO
    select * from Master1
    GO

    При выполнении вставки в таблицу записей никаких изменений в таблице не происходит. Хотя и выдается сообщение о том, что строка добавлена. В таком типе триггеров необходимо добавлять код на изменение данных в таблице. Вот примерная реализация:
    ALTER TRIGGER TriggerInsteadMaster1 ON [Master1]
    
    INSTEAD OF INSERT
    AS
    SET NOCOUNT ON
    INSERT INTO Master1 (Name)

    SELECT Name
    FROM inserted
    print 'Триггер INSTEAD OF'
    GO
    insert Master1 (Name)
    select 'Васечкин'
    union
    select 'Петров'
    GO
    select * from Master1
    GO

    Результат:
    Kind     Master1ID   Name
    
    -------- ----------- ------------------------------
    inserted 6 Васечкин
    inserted 7 Петров


    (2 row(s) affected)

    Выход из триггера
    Триггер INSTEAD OF
    Master1ID Name
    ----------- ------------------------------
    1 Иванов
    2 Петров
    3 Кошкин
    6 Васечкин
    7 Петров

    (5 row(s) affected)

    При работе только с таблицами можно вполне обходиться без этого типа триггеров, но иногда с их использованием T-SQL код упрощается.

    На этом закончим. Удалить созданные объекты можно с помощью следующего кода:
    DROP TRIGGER TriggerInsteadMaster1
    
    DROP TRIGGER TriggerMaster1
    DROP TABLE Master1
    GO


    Зачем нужны триггеры, и как ими пользоваться?

    1. Зачем нужны триггеры.

    Повторю неоднократно слышимую мной фразу - триггеры нужны для поддержания целостности базы данных.
    Триггер - это блок кода, который выполняется при попытке внесения изменений в таблицу (или представление), для которой он определен. И в нем может быть какой угодно T-SQL код. Обычно в нем пишут код для проверки заполнения полей, связей с другими таблицами. Есть триггеры для протоколирования изменений в таблицах, т.е. при изменении данных в служебную таблицу записываются старые и новые данные. И т.д.

    2. Как пользоваться триггерами.

    Несколько замечаний:
  • При внесении изменений в таблицу, триггеры выполняются в последнюю очередь, после проверки всякого рода связей и ограничений.

  • Триггер может быть привязан только к одной таблице.

  • У одной таблицы может быть много триггеров разных типов.

  • Триггеры могут быть на добавление, изменение и удаление (insert, update, delete) в любых вариациях.

  • Триггер вызывается на общую команду изменения данных в таблице, т.е. при вызове update для нескольких записей, он не будет выполняться для каждой записи отдельно, а всего один раз.

  • Если в триггере изменяются данные по таблице, к которой привязан триггер, то вся группа триггеров по этой таблице выполняется повторно за исключением этого триггера (если в опциях сервера стоит метка "allow nested triggers").

  • Писать триггеры надо так, чтобы не была важна последовательность их вызова.


  • В теле триггера можно использовать служебные таблицы deleted и inserted.
    При выполнении INSERT таблица deleted будет пустая, а в inserted будут содержаться вставленные записи.
    При выполнении DELETE таблица inserted будет пустая, а в deleted будут содержаться удаленные записи.
    При выполнении UPDATE в deleted содержаться записи до изменения, а в inserted после изменения.

    Для примеров будем использовать таблицу, созданную с помощью следующего скрипта:
    CREATE TABLE Master1
    
    (
    Master1ID int IDENTITY (1,1) NOT NULL,
    Name varchar(200),
    CONSTRAINT PK_Master1 PRIMARY KEY CLUSTERED
    (Master1ID)
    )
    insert Master1 (Name) values('Иванов')
    insert Master1 (Name) values('Петров')
    insert Master1 (Name) values('Сидоров')
    GO


    Создадим триггер на все виды операций и поэкспериментируем с ним:
    CREATE TRIGGER TriggerMaster1 ON [Master1]
    
    FOR INSERT, UPDATE, DELETE
    AS
    SET NOCOUNT ON
    select 'inserted' as Kind, * from inserted
    union all
    select 'deleted' as Kind, * from deleted

    print 'Выход из триггера'
    GO

    Несколько изменений в таблице:
    insert Master1 (Name)
    
    select 'Москвитин'
    union
    select 'Румянцев'
    GO

    update Master1 set Name='Кошкин' where Master1ID in (3,6,7)
    GO

    delete Master1 where Master1ID>3
    GO

    Результат:
    Kind     Master1ID   Name
    
    -------- ----------- ------------------------------
    inserted 4 Москвитин
    inserted 5 Румянцев

    (2 row(s) affected)

    Выход из триггера

    Kind Master1ID Name
    -------- ----------- ------------------------------
    inserted 3 Кошкин
    deleted 3 Сидоров

    (1 row(s) affected)

    Выход из триггера

    Kind Master1ID Name
    -------- ----------- ------------------------------
    deleted 4 Москвитин
    deleted 5 Румянцев

    (2 row(s) affected)

    Выход из триггера

    Обратите внимание на SET NOCOUNT ON в начале тела триггера. Это нужно для того, чтобы команды из тела триггера не возвращали информацию о количестве обработанных строк, и не перебивали тем самым информацию о количестве измененных строк.

    В триггере можно использовать функции UPDATE и COLUMNS_UPDATED для определения полей, в которых изменяются данные. Даже если данные до изменения и после изменения были одни и те же, эти функции покажут, что данные в поле были изменены. Например, функция UPDATE(Field) возвратит True при выполнении запроса:
    UPDATE Table SET Field=Field
    


    В SQL Server 2000 появилась возможность определять триггеры для VIEW.

    Еще в SQL Server 2000 появился новый тип триггеров INSTEAD OF. Данный тип триггеров предназначен в первую очередь для представлений (VIEW). Создадим триггер INSTEAD OF INSERT и внесем изменения в таблицу:
    CREATE TRIGGER TriggerInsteadMaster1 ON [Master1]
    
    INSTEAD OF INSERT
    AS
    SET NOCOUNT ON
    print 'Триггер INSTEAD OF'
    GO
    insert Master1 (Name) values ('Фамилия')
    GO
    select * from Master1
    GO

    При выполнении вставки в таблицу записей никаких изменений в таблице не происходит. Хотя и выдается сообщение о том, что строка добавлена. В таком типе триггеров необходимо добавлять код на изменение данных в таблице. Вот примерная реализация:
    ALTER TRIGGER TriggerInsteadMaster1 ON [Master1]
    
    INSTEAD OF INSERT
    AS
    SET NOCOUNT ON
    INSERT INTO Master1 (Name)

    SELECT Name
    FROM inserted
    print 'Триггер INSTEAD OF'
    GO
    insert Master1 (Name)
    select 'Васечкин'
    union
    select 'Петров'
    GO
    select * from Master1
    GO

    Результат:
    Kind     Master1ID   Name
    
    -------- ----------- ------------------------------
    inserted 6 Васечкин
    inserted 7 Петров


    (2 row(s) affected)

    Выход из триггера
    Триггер INSTEAD OF
    Master1ID Name
    ----------- ------------------------------
    1 Иванов
    2 Петров
    3 Кошкин
    6 Васечкин
    7 Петров

    (5 row(s) affected)

    При работе только с таблицами можно вполне обходиться без этого типа триггеров, но иногда с их использованием T-SQL код упрощается.

    На этом закончим. Удалить созданные объекты можно с помощью следующего кода:
    DROP TRIGGER TriggerInsteadMaster1
    
    DROP TRIGGER TriggerMaster1
    DROP TABLE Master1
    GO



    Надеюсь, Вы нашли эту информацию полезной. Вопросы, предложения и пожелания шлите на адрес sql@likor.ru
    С уважением, Сергей Кошкин.
    Архив на Subscribe.Ru
    Поиск по архиву рассылки
    "Вопросы и ответы по MS SQL Server"



    http://subscribe.ru/
    E-mail: ask@subscribe.ru
    Отписаться
    Убрать рекламу

    В избранное