Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Зловредные триггеры.  [new]
Crayzer
Member

Откуда:
Сообщений: 37
Всем доброго времени суток.

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

Реализуется сие действие, как я понимаю, через триггер
INSTEAD OF INSERT


Ворпос заключается вот в чем. Инсертит ли MS все полученные данные после обработки некоторых полей триггером, или будет обрабатывать только несколько указанных в триггере полей и все? А для инсерта прийдется писать:
INSERT INTO TABLE1 SELECT * FROM inserted

Но тогда опять же, не будут учитываться изменения произведенные над полученными данными, значит прийдется все это дело херячить через переменные в триггере, а этого делать не хотелось бы...
27 июн 12, 16:38    [12784048]     Ответить | Цитировать Сообщить модератору
 Re: Зловредные триггеры.  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
Crayzer,

в триггере INSTEAD OF INSERT настоящий INSERT придётся писать самому.
И в нём-то, как Вы изволили выразиться, "херячить", только вот переменные-то тут при чём??
27 июн 12, 16:41    [12784075]     Ответить | Цитировать Сообщить модератору
 Re: Зловредные триггеры.  [new]
Crayzer
Member

Откуда:
Сообщений: 37
iap
только вот переменные-то тут при чём??


Триггер должен поменять некоторые значения, передаваемые в таблицу, а остальные оставить без изменений.
После чего происходит инсерт в таблицу.
Я так понимаю, что для инсерта всего этого в одну строку, необходимо писать
1)
INSERT INTO TABLE1 (field1, field2, field3) VALUES (value1, value2, value3)

или
2)
INSERT INTO TABLE1 (field1, field2, field3) SELECT (field1, field2, field3) FROM inserted


Но в первом случае сначала нужно сделать селект в переменные и потом все это инсертить.
Во втором случае произойдет инсерт только полученных от приложения данных, без изменения полей...

Есть ли чудоспособ одновременно все это вставить одной строкой?
27 июн 12, 16:51    [12784176]     Ответить | Цитировать Сообщить модератору
 Re: Зловредные триггеры.  [new]
Crimean
Member

Откуда:
Сообщений: 13147
Crayzer,

а в select можно весьма сильно данными манипулировать
27 июн 12, 16:52    [12784192]     Ответить | Цитировать Сообщить модератору
 Re: Зловредные триггеры.  [new]
Crayzer
Member

Откуда:
Сообщений: 37
Crimean, не могли бы Вы привести пример одновременного инсерта селекта и переменных.
Ну или что-либо подобное...
27 июн 12, 16:56    [12784222]     Ответить | Цитировать Сообщить модератору
 Re: Зловредные триггеры.  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
Зачем переменные-то? O_o
27 июн 12, 16:56    [12784232]     Ответить | Цитировать Сообщить модератору
 Re: Зловредные триггеры.  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
Crayzer,

как поля-то должны меняться?
Подробности какие-нибудь будут ещё?

А SELECT ... FROM inserted может быть очень сильно усложнён JOINами, условиями в WHERE,
CASEами, производными таблицами, коррелированными подзапросами и т.д. и т.п.
27 июн 12, 17:01    [12784286]     Ответить | Цитировать Сообщить модератору
 Re: Зловредные триггеры.  [new]
Crayzer
Member

Откуда:
Сообщений: 37
Гавриленко Сергей Алексеевич,

Затем, что входящие данные надо как-то изменить.
К примеру.
Приходит от приложения инсерт с 10 полями. В этом инсерте нам надо изменить 3 поля вот таким образом:
 
 SET @EDDATE_CREATED = 'NOW';
 SET @EDDATE_MODIFIED = @EDDATE;
 SET @EDSID = 1;


Как это сделать внутри самого селекта, я что-то не могу уловить пока...
27 июн 12, 17:02    [12784292]     Ответить | Цитировать Сообщить модератору
 Re: Зловредные триггеры.  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
Crayzer
Гавриленко Сергей Алексеевич,

Затем, что входящие данные надо как-то изменить.
К примеру.
Приходит от приложения инсерт с 10 полями. В этом инсерте нам надо изменить 3 поля вот таким образом:
 
 SET @EDDATE_CREATED = 'NOW';
 SET @EDDATE_MODIFIED = @EDDATE;
 SET @EDSID = 1;


Как это сделать внутри самого селекта, я что-то не могу уловить пока...
Например, CASEом
27 июн 12, 17:03    [12784302]     Ответить | Цитировать Сообщить модератору
 Re: Зловредные триггеры.  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
В списке полей селекта можно указывать не только названия полей, но и выражения, и даже константы.
27 июн 12, 17:03    [12784308]     Ответить | Цитировать Сообщить модератору
 Re: Зловредные триггеры.  [new]
Crayzer
Member

Откуда:
Сообщений: 37
iap, Так ведь CASE "перебирает" значения, и если оно равно тому-то, то делаем то-то, т.е. нам необходимо знать что прийдет в этом поле, тогда выполнится условие... но мы то не знаем что может там наваять юзверь....

Гавриленко Сергей Алексеевич, можно поподробнее про выражения в селекте?
27 июн 12, 17:13    [12784391]     Ответить | Цитировать Сообщить модератору
 Re: Зловредные триггеры.  [new]
Crayzer
Member

Откуда:
Сообщений: 37
Господа знатоки! Ну хоть пример приведите , как это в общем и целом должно выглядеть на Ваш взгляд...
27 июн 12, 17:56    [12784611]     Ответить | Цитировать Сообщить модератору
 Re: Зловредные триггеры.  [new]
Glory
Member

Откуда:
Сообщений: 104751
Crayzer
Ну хоть пример приведите , как это в общем и целом должно выглядеть на Ваш взгляд...

Как обыкновенный select из нескольких таблиц
27 июн 12, 17:58    [12784623]     Ответить | Цитировать Сообщить модератору
 Re: Зловредные триггеры.  [new]
Crayzer
Member

Откуда:
Сообщений: 37
Glory,

нескольких?

У нас есть только одна темповая таблица "inserted".
Или Вы предлагаете создавать еще одну темповую таблицу, для изменяемых полей?
27 июн 12, 18:07    [12784684]     Ответить | Цитировать Сообщить модератору
 Re: Зловредные триггеры.  [new]
Glory
Member

Откуда:
Сообщений: 104751
Crayzer
Glory,

нескольких?

У нас есть только одна темповая таблица "inserted".

Хорошо. Как обыкновенный select из нужных таблиц.
27 июн 12, 18:10    [12784701]     Ответить | Цитировать Сообщить модератору
 Re: Зловредные триггеры.  [new]
Crayzer
Member

Откуда:
Сообщений: 37
Glory,

Речь идет об INSTEAD OF INSERT триггере, который выполняет свои действия перед вставкой полученных от внешнего приложения данных. Нету там никаких "нужных" таблиц. Есть только одна единственная темповая таблица "inserted". И необходимо, чтобы триггер обрабатывал полученные данные, изменял некоторые поля и инсертил строку в таблицув БД. Я категорически не могу понять, как все это завернуть в один единственный селект.
Приведите хоть пример кода, что-ли...

Заранее благодарен.
27 июн 12, 18:16    [12784734]     Ответить | Цитировать Сообщить модератору
 Re: Зловредные триггеры.  [new]
Glory
Member

Откуда:
Сообщений: 104751
Crayzer
Речь идет об INSTEAD OF INSERT триггере, который выполняет свои действия перед вставкой полученных от внешнего приложения данных. Нету там никаких "нужных" таблиц. Есть только одна единственная темповая таблица "inserted".

Таблицы вообще то в базе есть.

Crayzer
Я категорически не могу понять, как все это завернуть в один единственный селект.

А мы как это поймем ? То, что вам нужно завернуть ?

Crayzer
Приведите хоть пример кода, что-ли...

Да легко
USE AdventureWorks2008R2;
GO
SELECT Name, 
   SUBSTRING('This is a long string', 1, 5) AS SampleText, 
   ProductNumber, 
   ListPrice * 1.5 AS NewPrice
FROM Production.Product;
27 июн 12, 18:19    [12784752]     Ответить | Цитировать Сообщить модератору
 Re: Зловредные триггеры.  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31949
Crayzer
необходимо, чтобы триггер обрабатывал полученные данные, изменял некоторые поля и инсертил строку в таблицув БД. Я категорически не могу понять, как все это завернуть в один единственный селект.
Удивительно, что не можете понять.

--	Это без изменений
INSERT INTO TABLE1 (field1, field2, field3) SELECT field1, field2, field3 FROM inserted
--	А это с изменениями!!!
INSERT INTO TABLE1 (field1, field2, field3) SELECT field1 * 2, field2, field3 FROM inserted

Вы точно программист?
27 июн 12, 18:32    [12784816]     Ответить | Цитировать Сообщить модератору
 Re: Зловредные триггеры.  [new]
Crayzer
Member

Откуда:
Сообщений: 37
Glory,

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




alexeyvg,
Я прекрасно понимаю, что в селектах можно производить простые арифметические действия, в него можно пихать функции, но я никак не могу понять, каким образом организовать триггер. Для примера могу привести код написанный на фаэрберде, который делает примерно те же операции, которые мне надо реализовать на MS:

CREATE OR ALTER TRIGGER TBL1_BI FOR TBL1
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
  IF (NEW.PAYID IS NULL) THEN
    NEW.PAYID = GEN_ID(GEN_TBL1_ID,1);

  NEW.PAYTYPE = COALESCE (NEW.PAYTYPE, -1);

END


ACTIVE BEFORE INSERT - это и есть INSTEAD OF INSERT

POSITION 0 - последовательность его выполнения

IF (NEW.PAYID IS NULL) THEN NEW.PAYID = GEN_ID(GEN_TBL1_ID,1); - генератор ID, в MS реализуется как IDENTITY

И вот тут самое интересное:
NEW.PAYTYPE = COALESCE (NEW.PAYTYPE, -1);


new.* - соответствует SELECT * FROM inserted
old.* - соответствует SELECT * FROM deleted


На ФБ все проще. Триггер при получении записи изменяет только указанное поле/поля и добавляет его/их в строку инсерта, после чего происходит инсерт всех полученных данных + измененных. Он не блочит инсерт, как MS.
27 июн 12, 18:42    [12784871]     Ответить | Цитировать Сообщить модератору
 Re: Зловредные триггеры.  [new]
Crayzer
Member

Откуда:
Сообщений: 37
Повторюсь. Это пример, понятно, что COALESCE тоже можно использовать в селекте.
27 июн 12, 18:44    [12784883]     Ответить | Цитировать Сообщить модератору
 Re: Зловредные триггеры.  [new]
Crimean
Member

Откуда:
Сообщений: 13147
Crayzer
ACTIVE BEFORE INSERT - это и есть INSTEAD OF INSERT


неа. "INSTEAD OF" - это "ВМЕСТО ТОГО", а не "ДО ТОГО". "ДО ТОГО" у мс нету. есть только "вместо" и "после"
если повесить пустой "INSTEAD OF", то ничего реально с данными происходить вообще не будет
27 июн 12, 18:48    [12784896]     Ответить | Цитировать Сообщить модератору
 Re: Зловредные триггеры.  [new]
Crayzer
Member

Откуда:
Сообщений: 37
Crimean,

Я понимаю, что это ВМЕСТО... но что делать, если надо сделать ДО... )))
INSTEAD OF - единственный выход.
Отсюда и куча приключений на свои вторые 90 )))
27 июн 12, 18:51    [12784910]     Ответить | Цитировать Сообщить модератору
 Re: Зловредные триггеры.  [new]
Crimean
Member

Откуда:
Сообщений: 13147
Crayzer,

тогда ваш пример будет очень примерно выглядеть как-то так:

CREATE /*ALTER*/ TRIGGER dbo.TBL1_BI ON dbo.TBL1
INSTEAD OF INSERT
AS
SET NOCOUNT ON

INSERT INTO dbo.TBL1 ( ... , PAYID , ... , PAYTYPE , ... )
SELECT ... , ISNULL( PAYID, dbo.GEN_ID(GEN_TBL1_ID,1)) , ... , COALESCE (NEW.PAYTYPE, -1) , ...
FROM INSERTED

-- IF @@ERROR <> 0 ROLLBACK TRAN

RETURN
27 июн 12, 19:22    [12785051]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить