Создает
В отличие от обычной подпрограммы,
Основной формат команды CREATE TRIGGER показан ниже:
<Определение_триггера>::=
CREATE TRIGGER имя_триггера
BEFORE | AFTER <триггерное_событие>
ON <имя_таблицы>
[REFERENCING
<список_старых_или_новых_псевдонимов>]
[FOR EACH { ROW | STATEMENT}]
[WHEN(условие_триггера)]
<тело_триггера>
BEFORE ( AFTER (после их выполнения).
Выполняемые FOR
EACH ROW ), охваченной данным событием, или только один раз для каждого события ( FOR EACH STATEMENT ).
Обозначение <список_старых_или_новых_псевдонимов> относится к таким компонентам, как старая или новая строка ( OLD / NEW )
либо старая или новая таблица ( OLD TABLE / NEW TABLE ). Ясно, что
старые значения не применимы для событий вставки, а новые – для событий удаления.
При условии правильного использования
Неправильно написанные
В реализации СУБД MS SQL Server используется следующий оператор создания или изменения
<Определение_триггера>::=
{CREATE | ALTER} TRIGGER имя_триггера
ON {имя_таблицы | имя_представления }
[WITH ENCRYPTION ]
{
{ { FOR | AFTER | INSTEAD OF }
{ [ DELETE] [,] [ INSERT] [,] [ UPDATE] }
[ WITH APPEND ]
[ NOT FOR REPLICATION ]
AS
sql_оператор[...n]
} |
{ {FOR | AFTER | INSTEAD OF } { [INSERT] [,]
[UPDATE] }
[ WITH APPEND]
[ NOT FOR REPLICATION]
AS
{ IF UPDATE(имя_столбца)
[ {AND | OR} UPDATE(имя_столбца)] [...n]
|
IF (COLUMNS_UPDATES(){оператор_бит_обработки}
бит_маска_изменения)
{оператор_бит_сравнения }бит_маска [...n]}
sql_оператор [...n]
}
}
Рассмотрим назначение аргументов из команды CREATE | ALTER
TRIGGER.
Имя
При указании аргумента WITH ENCRYPTION сервер выполняет
шифрование кода
В SQL Server существует два параметра, определяющих поведение
AFTER. AFTER -триггеров
для каждой операции ( INSERT, UPDATE, DELETE ). Если для таблицы
предусмотрено выполнение нескольких AFTER -триггеров, то с помощью системной хранимой процедуры sp_settriggerorder
можно указать, какой из них будет выполняться первым, а какой последним. По умолчанию в SQL Server все AFTER -триггерами.INSTEAD OF. AFTER -триггера INSTEAD OF -триггер может быть определен как для таблицы, так и для представления. Для каждой операции INSERT, UPDATE, DELETE можно определить только один INSTEAD
OF -триггер.Существует три типа
INSERT TRIGGER – запускаются при попытке вставки данных с помощью команды INSERT.UPDATE TRIGGER – запускаются при попытке изменения данных с
помощью команды UPDATE.DELETE TRIGGER – запускаются при попытке удаления данных с
помощью команды DELETE.Конструкции [ DELETE] [,] [ INSERT] [,] [ UPDATE] и FOR
| AFTER | INSTEAD OF } { [INSERT] [,] [UPDATE] определяют,
на какую команду будет реагировать
Аргумент WITH APPEND позволяет создавать несколько
При NOT FOR REPLICATION запрещается его запуск во время выполнения модификации таблиц механизмами репликации.
Конструкция AS sql_оператор[...n] определяет набор SQL-
операторов и команд, которые будут выполнены при запуске
Отметим, что внутри
Выполнение этих команд не разрешено, так как они не могут быть
отменены в случае отката транзакции, в которой выполняется
При выполнении команд добавления, изменения и удаления записей
сервер создает две специальные таблицы: и . В них содержатся списки строк, которые будут вставлены или удалены по завершении транзакции. Структура таблиц inserted и deleted идентична
структуре таблиц, для которой определяется inserted и deleted, поэтому никакой другой inserted и deleted может быть разным:
INSERT – в таблице inserted содержатся все строки, которые пользователь пытается вставить в таблицу; в таблице deleted
не будет ни одной строки; после завершения inserted переместятся в исходную таблицу;DELETE – в таблице deleted будут содержаться все строки, которые пользователь попытается удалить; inserted не окажется ни одной строки;UPDATE – при ее выполнении в таблице deleted находятся старые значения строк, которые будут удалены при успешном завершении inserted. Эти строки добавятся в исходную таблицу после успешного выполнения Для получения информации о количестве строк, которое будет изменено при успешном завершении @@ она возвращает количество строк, обработанных последней
командой. Следует подчеркнуть, что
Если
ROLLBACK TRANSACTION.
Для получения списка столбцов, измененных при выполнении команд INSERT или UPDATE, вызвавших выполнение COLUMNS_UPDATED(). Она возвращает двоичное
число, каждый бит которого, начиная с младшего, соответствует одному
столбцу таблицы (в порядке следования столбцов при создании таблицы).
Если бит установлен в значение "1", то соответствующий столбец был изменен. Кроме того, факт изменения столбца определяет и функция UPDATE (имя_столбца).
Для
DROP TRIGGER {имя_триггера} [,...n]
Приведем примеры использования
Пример 14.1. Использование Сделка записи количество проданного товара должно быть не больше, чем его остаток из таблицы Склад.
Команда вставки записи в таблицу Сделка может быть, например,
такой:
INSERT INTO Сделка VALUES (3,1,-299,'01/08/2002')
Создаваемый Склад величина остатка товара оказалась меньше продаваемого количества товара
с введенным кодом (в примере код товара=3 ). Во вставляемой записи количество товара указывается со знаком "+", если товар поставляется, и со
знаком "-", если он продается. Представленный
CREATE TRIGGER Триггер_ins
ON Сделка FOR INSERT
AS
IF @@ROWCOUNT=1
BEGIN
IF NOT EXISTS(SELECT *
FROM inserted
WHERE -inserted.количество<=ALL(SELECT
Склад.Остаток
FROM Склад,Сделка
WHERE Склад.КодТовара=
Сделка.КодТовара))
BEGIN
ROLLBACK TRAN
PRINT
'Отмена поставки: товара на складе нет'
END
END
Пример 14.2. Использование
Создать Сделка, например, такой команды:
INSERT INTO Сделка VALUES (3,1,200,'01/08/2002')
поставляется товар с кодом 3 от клиента с кодом 1 в количестве 200 единиц.
При продаже или получении товара необходимо соответствующим
образом изменить количество его складского запаса. Если товара на складе еще нет, необходимо добавить соответствующую запись в таблицу Склад.
ALTER TRIGGER Триггер_ins
ON Сделка FOR INSERT
AS
DECLARE @x INT, @y INT
IF @@ROWCOUNT=1
--в таблицу Сделка добавляется запись
--о поставке товара
BEGIN
--количество проданного товара должно быть не
--меньше, чем его остаток из таблицы Склад
IF NOT EXISTS(SELECT *
FROM inserted
WHERE -inserted.количество<
=ALL(SELECT Склад.Остаток
FROM Склад,Сделка
WHERE Склад.КодТовара=
Сделка.КодТовара))
BEGIN
ROLLBACK TRAN
PRINT 'откат товара нет '
END
--если записи о поставленном товаре еще нет,
--добавляется соответствующая запись
--в таблицу Склад
IF NOT EXISTS ( SELECT *
FROM Склад С, inserted i
WHERE С.КодТовара=i.КодТовара )
INSERT INTO Склад (КодТовара,Остаток)
ELSE
--если запись о товаре уже была в таблице
--Склад, то определяется код и количество
--товара из добавленной в таблицу Сделка записи
BEGIN
SELECT @y=i.КодТовара, @x=i.Количество
FROM Сделка С, inserted i
WHERE С.КодТовара=i.КодТовара
--и производится изменения количества товара в
--таблице Склад
UPDATE Склад
SET Остаток=остаток+@x
WHERE КодТовара=@y
END
END
Пример 14.3. Создать Сделка, например, такой команды:
DELETE FROM Сделка WHERE КодСделки=4
Для товара, код которого указан при удалении записи, необходимо
откорректировать его остаток на складе.
CREATE TRIGGER Триггер_del
ON Сделка FOR DELETE
AS
IF @@ROWCOUNT=1 -- удалена одна запись
BEGIN
DECLARE @y INT,@x INT
--определяется код и количество товара из
--удаленной из таблицы Склад записи
SELECT @y=КодТовара, @x=Количество
FROM deleted
--в таблице Склад корректируется количество
--товара
UPDATE Склад
SET Остаток=Остаток-@x
WHERE КодТовара=@y
END
Пример 14.4. Создать Сделка, например, такой командой:
UPDATE Сделка SET количество=количество-10 WHERE КодТовара=3
во всех сделках с товаром, имеющим код, равный 3, уменьшить количество товара на 10 единиц.
Указанная команда может привести к изменению сразу нескольких
записей в таблице Сделка. Поэтому покажем, как создать deleted )
и все новые значения (из таблицы inserted ).
CREATE TRIGGER Триггер_upd
ON Сделка FOR UPDATE
AS
DECLARE @x INT, @x_old INT, @y INT, @y_old INT
-- курсор с новыми значениями
DECLARE CUR1 CURSOR FOR
SELECT КодТовара,Количество
FROM inserted
-- курсор со старыми значениями
DECLARE CUR2 CURSOR FOR
SELECT КодТовара,Количество
FROM deleted
OPEN CUR1
OPEN CUR2
-- перемещаемся параллельно по обоим курсорам
FETCH NEXT FROM CUR1 INTO @x, @y
FETCH NEXT FROM CUR2 INTO @x_old, @y_old
WHILE @@FETCH_STATUS=0
BEGIN
--для старого кода товара уменьшается его
--количество на складе
UPDATE Склад
SET Остаток=Остаток-@y_old
WHERE КодТовара=@x_old
--для нового кода товара, если такого товара
--еще нет на складе, вводится новая запись
IF NOT EXISTS (SELECT * FROM Склад
WHERE КодТовара=@x)
INSERT INTO Склад(КодТовара,Остаток)
VALUES (@x,@y)
ELSE
--иначе для нового кода товара увеличивается
--его количество на складе
UPDATE Склад
SET Остаток=Остаток+@y
WHERE КодТовара=@x
FETCH NEXT FROM CUR1 INTO @x, @y
FETCH NEXT FROM CUR2 INTO @x_old, @y_old
END
CLOSE CUR1
CLOSE CUR2
DEALLOCATE CUR1
DEALLOCATE CUR2
В рассмотренном
Пример 14.5. Исправим этот недостаток. Для генерирования сообщения об ошибке используем в теле MS SQL Server
RAISERROR, аргументами которой являются текст сообщения, уровень
серьезности и
ALTER TRIGGER Триггер_upd
ON Сделка FOR UPDATE
AS
DECLARE @x INT, @x_old INT, @y INT,
@y_old INT ,@o INT
DECLARE CUR1 CURSOR FOR
SELECT КодТовара,Количество
FROM inserted
DECLARE CUR2 CURSOR FOR
SELECT КодТовара,Количество
FROM deleted
OPEN CUR1
OPEN CUR2
FETCH NEXT FROM CUR1 INTO @x, @y
FETCH NEXT FROM CUR2 INTO @x_old, @y_old
WHILE @@FETCH_STATUS=0
BEGIN
SELECT @o=остаток
FROM Склад
WHERE кодтовара=@x
IF @o<-@y
BEGIN
RAISERROR('откат',16,10)
CLOSE CUR1
CLOSE CUR2
DEALLOCATE CUR1
DEALLOCATE CUR2
ROLLBACK TRAN
RETURN
END
UPDATE Склад
SET Остаток=Остаток-@y_old
WHERE КодТовара=@x_old
IF NOT EXISTS (SELECT * FROM Склад
WHERE КодТовара=@x)
INSERT INTO Склад(КодТовара,Остаток)
VALUES (@x,@y)
ELSE
UPDATE Склад
SET Остаток=Остаток+@y
WHERE КодТовара=@x
FETCH NEXT FROM CUR1 INTO @x, @y
FETCH NEXT FROM CUR2 INTO @x_old, @y_old
END
CLOSE CUR1
CLOSE CUR2
DEALLOCATE CUR1
DEALLOCATE CUR2
Пример 14.6. В примере 14.5 происходит отмена всех изменений при
невозможности реализовать хотя бы одно из них. Создадим
В этом случае
ALTER TRIGGER Триггер_upd
ON Сделка INSTEAD OF UPDATE
AS
DECLARE @k INT, @k_old INT
DECLARE @x INT, @x_old INT, @y INT
DECLARE @y_old INT ,@o INT
DECLARE CUR1 CURSOR FOR
SELECT КодСделки, КодТовара,Количество
FROM inserted
DECLARE CUR2 CURSOR FOR
SELECT КодСделки, КодТовара,Количество
FROM deleted
OPEN CUR1
OPEN CUR2
FETCH NEXT FROM CUR1 INTO @k,@x, @y
FETCH NEXT FROM CUR2 INTO @k_old,@x_old,
@y_old
WHILE @@FETCH_STATUS=0
BEGIN
SELECT @o=остаток
FROM Склад
WHERE КодТовара=@x
IF @o>=-@y
BEGIN
RAISERROR('изменение',16,10)
UPDATE Сделка SET количество=@y,
КодТовара=@x
WHERE КодСделки=@k
UPDATE Склад
SET Остаток=Остаток-@y_old
WHERE КодТовара=@x_old
IF NOT EXISTS (SELECT * FROM Склад
WHERE КодТовара=@x)
INSERT INTO Склад(КодТовара, Остаток)
VALUES (@x,@y)
ELSE
UPDATE Склад
SET Остаток=Остаток+@y
WHERE КодТовара=@x
END
ELSE
RAISERROR('запись не изменена',16,10)
FETCH NEXT FROM CUR1 INTO @k,@x, @y
FETCH NEXT FROM CUR2 INTO @k_old,@x_old,
@y_old
END
CLOSE CUR1
CLOSE CUR2
DEALLOCATE CUR1
DEALLOCATE CUR2
Создает
В отличие от обычной подпрограммы,
Основной формат команды CREATE TRIGGER показан ниже:
<Определение_триггера>::=
CREATE TRIGGER имя_триггера
BEFORE | AFTER <триггерное_событие>
ON <имя_таблицы>
[REFERENCING
<список_старых_или_новых_псевдонимов>]
[FOR EACH { ROW | STATEMENT}]
[WHEN(условие_триггера)]
<тело_триггера>
BEFORE ( AFTER (после их выполнения).
Выполняемые FOR
EACH ROW ), охваченной данным событием, или только один раз для каждого события ( FOR EACH STATEMENT ).
Обозначение <список_старых_или_новых_псевдонимов> относится к таким компонентам, как старая или новая строка ( OLD / NEW )
либо старая или новая таблица ( OLD TABLE / NEW TABLE ). Ясно, что
старые значения не применимы для событий вставки, а новые – для событий удаления.
При условии правильного использования
Неправильно написанные
В реализации СУБД MS SQL Server используется следующий оператор создания или изменения
<Определение_триггера>::=
{CREATE | ALTER} TRIGGER имя_триггера
ON {имя_таблицы | имя_представления }
[WITH ENCRYPTION ]
{
{ { FOR | AFTER | INSTEAD OF }
{ [ DELETE] [,] [ INSERT] [,] [ UPDATE] }
[ WITH APPEND ]
[ NOT FOR REPLICATION ]
AS
sql_оператор[...n]
} |
{ {FOR | AFTER | INSTEAD OF } { [INSERT] [,]
[UPDATE] }
[ WITH APPEND]
[ NOT FOR REPLICATION]
AS
{ IF UPDATE(имя_столбца)
[ {AND | OR} UPDATE(имя_столбца)] [...n]
|
IF (COLUMNS_UPDATES(){оператор_бит_обработки}
бит_маска_изменения)
{оператор_бит_сравнения }бит_маска [...n]}
sql_оператор [...n]
}
}
Рассмотрим назначение аргументов из команды CREATE | ALTER
TRIGGER.
Имя
При указании аргумента WITH ENCRYPTION сервер выполняет
шифрование кода
В SQL Server существует два параметра, определяющих поведение
AFTER. AFTER -триггеров
для каждой операции ( INSERT, UPDATE, DELETE ). Если для таблицы
предусмотрено выполнение нескольких AFTER -триггеров, то с помощью системной хранимой процедуры sp_settriggerorder
можно указать, какой из них будет выполняться первым, а какой последним. По умолчанию в SQL Server все AFTER -триггерами.INSTEAD OF. AFTER -триггера INSTEAD OF -триггер может быть определен как для таблицы, так и для представления. Для каждой операции INSERT, UPDATE, DELETE можно определить только один INSTEAD
OF -триггер.Существует три типа
INSERT TRIGGER – запускаются при попытке вставки данных с помощью команды INSERT.UPDATE TRIGGER – запускаются при попытке изменения данных с
помощью команды UPDATE.DELETE TRIGGER – запускаются при попытке удаления данных с
помощью команды DELETE.Конструкции [ DELETE] [,] [ INSERT] [,] [ UPDATE] и FOR
| AFTER | INSTEAD OF } { [INSERT] [,] [UPDATE] определяют,
на какую команду будет реагировать
Аргумент WITH APPEND позволяет создавать несколько
При NOT FOR REPLICATION запрещается его запуск во время выполнения модификации таблиц механизмами репликации.
Конструкция AS sql_оператор[...n] определяет набор SQL-
операторов и команд, которые будут выполнены при запуске
Отметим, что внутри
Выполнение этих команд не разрешено, так как они не могут быть
отменены в случае отката транзакции, в которой выполняется
При выполнении команд добавления, изменения и удаления записей
сервер создает две специальные таблицы: и . В них содержатся списки строк, которые будут вставлены или удалены по завершении транзакции. Структура таблиц inserted и deleted идентична
структуре таблиц, для которой определяется inserted и deleted, поэтому никакой другой inserted и deleted может быть разным:
INSERT – в таблице inserted содержатся все строки, которые пользователь пытается вставить в таблицу; в таблице deleted
не будет ни одной строки; после завершения inserted переместятся в исходную таблицу;DELETE – в таблице deleted будут содержаться все строки, которые пользователь попытается удалить; inserted не окажется ни одной строки;UPDATE – при ее выполнении в таблице deleted находятся старые значения строк, которые будут удалены при успешном завершении inserted. Эти строки добавятся в исходную таблицу после успешного выполнения Для получения информации о количестве строк, которое будет изменено при успешном завершении @@ она возвращает количество строк, обработанных последней
командой. Следует подчеркнуть, что
Если
ROLLBACK TRANSACTION.
Для получения списка столбцов, измененных при выполнении команд INSERT или UPDATE, вызвавших выполнение COLUMNS_UPDATED(). Она возвращает двоичное
число, каждый бит которого, начиная с младшего, соответствует одному
столбцу таблицы (в порядке следования столбцов при создании таблицы).
Если бит установлен в значение "1", то соответствующий столбец был изменен. Кроме того, факт изменения столбца определяет и функция UPDATE (имя_столбца).
Для
DROP TRIGGER {имя_триггера} [,...n]
Приведем примеры использования
Пример 14.1. Использование Сделка записи количество проданного товара должно быть не больше, чем его остаток из таблицы Склад.
Команда вставки записи в таблицу Сделка может быть, например,
такой:
INSERT INTO Сделка VALUES (3,1,-299,'01/08/2002')
Создаваемый Склад величина остатка товара оказалась меньше продаваемого количества товара
с введенным кодом (в примере код товара=3 ). Во вставляемой записи количество товара указывается со знаком "+", если товар поставляется, и со
знаком "-", если он продается. Представленный
CREATE TRIGGER Триггер_ins
ON Сделка FOR INSERT
AS
IF @@ROWCOUNT=1
BEGIN
IF NOT EXISTS(SELECT *
FROM inserted
WHERE -inserted.количество<=ALL(SELECT
Склад.Остаток
FROM Склад,Сделка
WHERE Склад.КодТовара=
Сделка.КодТовара))
BEGIN
ROLLBACK TRAN
PRINT
'Отмена поставки: товара на складе нет'
END
END
Пример 14.2. Использование
Создать Сделка, например, такой команды:
INSERT INTO Сделка VALUES (3,1,200,'01/08/2002')
поставляется товар с кодом 3 от клиента с кодом 1 в количестве 200 единиц.
При продаже или получении товара необходимо соответствующим
образом изменить количество его складского запаса. Если товара на складе еще нет, необходимо добавить соответствующую запись в таблицу Склад.
ALTER TRIGGER Триггер_ins
ON Сделка FOR INSERT
AS
DECLARE @x INT, @y INT
IF @@ROWCOUNT=1
--в таблицу Сделка добавляется запись
--о поставке товара
BEGIN
--количество проданного товара должно быть не
--меньше, чем его остаток из таблицы Склад
IF NOT EXISTS(SELECT *
FROM inserted
WHERE -inserted.количество<
=ALL(SELECT Склад.Остаток
FROM Склад,Сделка
WHERE Склад.КодТовара=
Сделка.КодТовара))
BEGIN
ROLLBACK TRAN
PRINT 'откат товара нет '
END
--если записи о поставленном товаре еще нет,
--добавляется соответствующая запись
--в таблицу Склад
IF NOT EXISTS ( SELECT *
FROM Склад С, inserted i
WHERE С.КодТовара=i.КодТовара )
INSERT INTO Склад (КодТовара,Остаток)
ELSE
--если запись о товаре уже была в таблице
--Склад, то определяется код и количество
--товара из добавленной в таблицу Сделка записи
BEGIN
SELECT @y=i.КодТовара, @x=i.Количество
FROM Сделка С, inserted i
WHERE С.КодТовара=i.КодТовара
--и производится изменения количества товара в
--таблице Склад
UPDATE Склад
SET Остаток=остаток+@x
WHERE КодТовара=@y
END
END
Пример 14.3. Создать Сделка, например, такой команды:
DELETE FROM Сделка WHERE КодСделки=4
Для товара, код которого указан при удалении записи, необходимо
откорректировать его остаток на складе.
CREATE TRIGGER Триггер_del
ON Сделка FOR DELETE
AS
IF @@ROWCOUNT=1 -- удалена одна запись
BEGIN
DECLARE @y INT,@x INT
--определяется код и количество товара из
--удаленной из таблицы Склад записи
SELECT @y=КодТовара, @x=Количество
FROM deleted
--в таблице Склад корректируется количество
--товара
UPDATE Склад
SET Остаток=Остаток-@x
WHERE КодТовара=@y
END
Пример 14.4. Создать Сделка, например, такой командой:
UPDATE Сделка SET количество=количество-10 WHERE КодТовара=3
во всех сделках с товаром, имеющим код, равный 3, уменьшить количество товара на 10 единиц.
Указанная команда может привести к изменению сразу нескольких
записей в таблице Сделка. Поэтому покажем, как создать deleted )
и все новые значения (из таблицы inserted ).
CREATE TRIGGER Триггер_upd
ON Сделка FOR UPDATE
AS
DECLARE @x INT, @x_old INT, @y INT, @y_old INT
-- курсор с новыми значениями
DECLARE CUR1 CURSOR FOR
SELECT КодТовара,Количество
FROM inserted
-- курсор со старыми значениями
DECLARE CUR2 CURSOR FOR
SELECT КодТовара,Количество
FROM deleted
OPEN CUR1
OPEN CUR2
-- перемещаемся параллельно по обоим курсорам
FETCH NEXT FROM CUR1 INTO @x, @y
FETCH NEXT FROM CUR2 INTO @x_old, @y_old
WHILE @@FETCH_STATUS=0
BEGIN
--для старого кода товара уменьшается его
--количество на складе
UPDATE Склад
SET Остаток=Остаток-@y_old
WHERE КодТовара=@x_old
--для нового кода товара, если такого товара
--еще нет на складе, вводится новая запись
IF NOT EXISTS (SELECT * FROM Склад
WHERE КодТовара=@x)
INSERT INTO Склад(КодТовара,Остаток)
VALUES (@x,@y)
ELSE
--иначе для нового кода товара увеличивается
--его количество на складе
UPDATE Склад
SET Остаток=Остаток+@y
WHERE КодТовара=@x
FETCH NEXT FROM CUR1 INTO @x, @y
FETCH NEXT FROM CUR2 INTO @x_old, @y_old
END
CLOSE CUR1
CLOSE CUR2
DEALLOCATE CUR1
DEALLOCATE CUR2
В рассмотренном
Пример 14.5. Исправим этот недостаток. Для генерирования сообщения об ошибке используем в теле MS SQL Server
RAISERROR, аргументами которой являются текст сообщения, уровень
серьезности и
ALTER TRIGGER Триггер_upd
ON Сделка FOR UPDATE
AS
DECLARE @x INT, @x_old INT, @y INT,
@y_old INT ,@o INT
DECLARE CUR1 CURSOR FOR
SELECT КодТовара,Количество
FROM inserted
DECLARE CUR2 CURSOR FOR
SELECT КодТовара,Количество
FROM deleted
OPEN CUR1
OPEN CUR2
FETCH NEXT FROM CUR1 INTO @x, @y
FETCH NEXT FROM CUR2 INTO @x_old, @y_old
WHILE @@FETCH_STATUS=0
BEGIN
SELECT @o=остаток
FROM Склад
WHERE кодтовара=@x
IF @o<-@y
BEGIN
RAISERROR('откат',16,10)
CLOSE CUR1
CLOSE CUR2
DEALLOCATE CUR1
DEALLOCATE CUR2
ROLLBACK TRAN
RETURN
END
UPDATE Склад
SET Остаток=Остаток-@y_old
WHERE КодТовара=@x_old
IF NOT EXISTS (SELECT * FROM Склад
WHERE КодТовара=@x)
INSERT INTO Склад(КодТовара,Остаток)
VALUES (@x,@y)
ELSE
UPDATE Склад
SET Остаток=Остаток+@y
WHERE КодТовара=@x
FETCH NEXT FROM CUR1 INTO @x, @y
FETCH NEXT FROM CUR2 INTO @x_old, @y_old
END
CLOSE CUR1
CLOSE CUR2
DEALLOCATE CUR1
DEALLOCATE CUR2
Пример 14.6. В примере 14.5 происходит отмена всех изменений при
невозможности реализовать хотя бы одно из них. Создадим
В этом случае
ALTER TRIGGER Триггер_upd
ON Сделка INSTEAD OF UPDATE
AS
DECLARE @k INT, @k_old INT
DECLARE @x INT, @x_old INT, @y INT
DECLARE @y_old INT ,@o INT
DECLARE CUR1 CURSOR FOR
SELECT КодСделки, КодТовара,Количество
FROM inserted
DECLARE CUR2 CURSOR FOR
SELECT КодСделки, КодТовара,Количество
FROM deleted
OPEN CUR1
OPEN CUR2
FETCH NEXT FROM CUR1 INTO @k,@x, @y
FETCH NEXT FROM CUR2 INTO @k_old,@x_old,
@y_old
WHILE @@FETCH_STATUS=0
BEGIN
SELECT @o=остаток
FROM Склад
WHERE КодТовара=@x
IF @o>=-@y
BEGIN
RAISERROR('изменение',16,10)
UPDATE Сделка SET количество=@y,
КодТовара=@x
WHERE КодСделки=@k
UPDATE Склад
SET Остаток=Остаток-@y_old
WHERE КодТовара=@x_old
IF NOT EXISTS (SELECT * FROM Склад
WHERE КодТовара=@x)
INSERT INTO Склад(КодТовара, Остаток)
VALUES (@x,@y)
ELSE
UPDATE Склад
SET Остаток=Остаток+@y
WHERE КодТовара=@x
END
ELSE
RAISERROR('запись не изменена',16,10)
FETCH NEXT FROM CUR1 INTO @k,@x, @y
FETCH NEXT FROM CUR2 INTO @k_old,@x_old,
@y_old
END
CLOSE CUR1
CLOSE CUR2
DEALLOCATE CUR1
DEALLOCATE CUR2
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.