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

Откуда: Киев
Сообщений: 204
Доброго дня!
Может, опять глуповатый вопрос, но в документации я ответа не нашёл и самостоятельно не вышло решить.

Необходимо ПЕРЕД втсавкой заменить данные в конкретном поле.
В ORACLE, например, я делал это вот так :
create or replace trigger trigger_TEST
before insert or update on TEST
for each row
begin
   if :new.DT is null then
      :new.DT := SYSDATE_TO_INT(); 
   end if;
end trigger_TEST;

В MSSQL я пытаюсь сделать вот так:
CREATE TRIGGER trigger_TEST
ON Table_TEST
OF INSERT, UPDATE
AS
DECLARE @iDate		int
SET @iDate = (SELECT iDate FROM SYSDATE_TO_INT());
UPDATE inserted SET DT  = @iDate WHERE  IdC IN (SELECT IdC FROM inserted)

ошибка - inserted нельзя изменять.

Есть 2 корявых варианта, которые я хотел исопльзовать:

1. Делать при помощи INSTEAD OF, но тогда необходимо плодить по 2 триггера, на UPDATE и на INSERT отдельно.

2. Заменять данные в таблице TEST после вставки, но тогда поле должно сначала принимать NULL и триггер будет выглядеть где-то так:
CREATE TRIGGER trigger_TEST
ON Table_TEST
OF INSERT, UPDATE
AS
DECLARE @iDate		int
SET @iDate = (SELECT iDate FROM SYSDATE_TO_INT());
UPDATE TEST SET DT  = @iDate WHERE  IdC IN (SELECT IdC FROM inserted) AND DT is NULL
при этом выходит, что триггер будет 2 раза вызываться? в первый раз вставиться NULL, а второй раз замениться на нужное значение.

Подскажите, пожалуйста, есть какие-то лучшие варианты? Или я эти как не так прикрутил?
30 ноя 09, 13:01    [7996168]     Ответить | Цитировать Сообщить модератору
 Re: замена данных перед вставкой, обновлением  [new]
Паганель
Member

Откуда: Винница
Сообщений: 22552
Я что-то не пойму, зачем в этой задаче вообще триггер
create table t(id int not null, dt datetime default getdate() not null)
go
insert into t(id) values(1)
select * from t
go
drop table t
go

id          dt
----------- -----------------------
1           2009-11-30 12:05:17.750

(1 row(s) affected)
30 ноя 09, 13:06    [7996202]     Ответить | Цитировать Сообщить модератору
 Re: замена данных перед вставкой, обновлением  [new]
Дедушка
Member

Откуда: Город трёх революций
Сообщений: 5111
Либо заменять в процедуре через которую делаете insert
Либо тригер instead of (разделение тригеров на "до" и "после" есть "фирменный подход")
--------------------------------------------------------------
Дьявол кроется в деталях.
30 ноя 09, 13:06    [7996203]     Ответить | Цитировать Сообщить модератору
 P.S.  [new]
Игаев
Member

Откуда: Киев
Сообщений: 204
Да ещё по-ходу дела вопрос : а в чём же тогда отличия апраметров OF и AFTER в объявлении триггера если и в обоих случаях триггер срабатывает "после".
30 ноя 09, 13:07    [7996206]     Ответить | Цитировать Сообщить модератору
 Re: замена данных перед вставкой, обновлением  [new]
iljy
Member

Откуда:
Сообщений: 8711
Игаев,

вы просто не умеете их готовить;) inserted i deleted - это псевдо-таблицы и из них можно только читать. Соответственно в триггере instead of просто вставляйте (или изменяйте) нужные данные в целевой таблице. 2 раза триггер выполняться не будет.
30 ноя 09, 13:07    [7996211]     Ответить | Цитировать Сообщить модератору
 Re: P.S.  [new]
iljy
Member

Откуда:
Сообщений: 8711
Игаев
Да ещё по-ходу дела вопрос : а в чём же тогда отличия апраметров OF и AFTER в объявлении триггера если и в обоих случаях триггер срабатывает "после".


в первом случае он срабатывает не ПОСЛЕ, а ВМЕСТО, и называется INSTEAD OF.
30 ноя 09, 13:11    [7996231]     Ответить | Цитировать Сообщить модератору
 Re: замена данных перед вставкой, обновлением  [new]
Игаев
Member

Откуда: Киев
Сообщений: 204
iljy
Соответственно в триггере instead of просто вставляйте (или изменяйте) нужные данные в целевой таблице. 2 раза триггер выполняться не будет.

Но INSTEAD OF можно использовать либо только на UPDATE либо только на INSERT.
Мне необходимо учесть оба действия. То есть, прийдётся делать по 2 тригера.


Дедушка
Либо тригер instead of (разделение тригеров на "до" и "после" есть "фирменный подход")

Не могли про этот подход по-подробнее?

Паганель
dt datetime default getdate() not null

datetime - это пример. Есть другие случаи где не обойтись default-ом
30 ноя 09, 13:13    [7996249]     Ответить | Цитировать Сообщить модератору
 Re: замена данных перед вставкой, обновлением  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
Паганель
Я что-то не пойму, зачем в этой задаче вообще триггер
create table t(id int not null, dt datetime default getdate() not null)
go
insert into t(id) values(1)
select * from t
go
drop table t
go

id          dt
----------- -----------------------
1           2009-11-30 12:05:17.750

(1 row(s) affected)
При UPDATE dt не изменится.
INSTEAD OF INSERT, UPDATE неудобны тем, что в них придётся писать полный INSERT или UPDATE для всех полей.
Может, всё-таки, AFTER INSERT, UPDATE? Только, конечно, менять надо саму таблицу в JOINе с inserted и deleted.
Кстати. не понял, зачем дату конвертировать в INT?
Вместо GETDATE() можно использовать и стандартный CURRENT_TIMESTAMP. Он, наверно, и в Oracle есть?
30 ноя 09, 13:14    [7996252]     Ответить | Цитировать Сообщить модератору
 Re: замена данных перед вставкой, обновлением  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
Игаев
Но INSTEAD OF можно использовать либо только на UPDATE либо только на INSERT.
Это почему же?
INSTEAD OF INSERT, UPDATE
Но лучше два разных триггера. Проще, чем внутри общего триггера разбираться.
30 ноя 09, 13:17    [7996271]     Ответить | Цитировать Сообщить модератору
 Re: замена данных перед вставкой, обновлением  [new]
Игаев
Member

Откуда: Киев
Сообщений: 204
iap

Может, всё-таки, AFTER INSERT, UPDATE? Только, конечно, менять надо саму таблицу в JOINе с inserted и deleted.

Подсобите примерчиком, пожалуйста.

iap
Кстати. не понял, зачем дату конвертировать в INT?

Это не моя прихоть - такой формат хранения принят до меня.
30 ноя 09, 13:18    [7996281]     Ответить | Цитировать Сообщить модератору
 Re: замена данных перед вставкой, обновлением  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
Игаев
Это не моя прихоть - такой формат хранения принят до меня.
И какой же смысл в этом INT?
Подозреваю, что в MSSQL он совсем не такой, как в Oracle.
30 ноя 09, 13:20    [7996295]     Ответить | Цитировать Сообщить модератору
 Re: замена данных перед вставкой, обновлением  [new]
Игаев
Member

Откуда: Киев
Сообщений: 204
INSTEAD OF - у меня 15 таблиц куда требуется прикрутить такую замену даты. Это на кажду писать по 2 триггера с заменой INSERT и UPDATE ? Как минимум, не красиво....
30 ноя 09, 13:20    [7996301]     Ответить | Цитировать Сообщить модератору
 Re: замена данных перед вставкой, обновлением  [new]
Игаев
Member

Откуда: Киев
Сообщений: 204
iap
Подозреваю, что в MSSQL он совсем не такой, как в Oracle.

Сам тип данных может не такой, но натуральное чило получаемое клиентской программой одинаковое что на ORACLE, что на MSSQL , что на Informix. Проверено.
30 ноя 09, 13:22    [7996319]     Ответить | Цитировать Сообщить модератору
 Re: замена данных перед вставкой, обновлением  [new]
Игаев
Member

Откуда: Киев
Сообщений: 204
Посдкажите по этому триггеру:
CREATE TRIGGER trigger_TEST
ON Table_TEST
OF INSERT, UPDATE
AS
DECLARE @iDate		int
SET @iDate = (SELECT iDate FROM SYSDATE_TO_INT());
UPDATE TEST SET DT  = @iDate WHERE  IdC IN (SELECT IdC FROM inserted) AND DT is NULL
Может его и применять? Ничего слишком критического нет в нём? Должен отрабатвать согласно условиям?
30 ноя 09, 13:24    [7996336]     Ответить | Цитировать Сообщить модератору
 Re: замена данных перед вставкой, обновлением  [new]
Дедушка
Member

Откуда: Город трёх революций
Сообщений: 5111
Игаев
INSTEAD OF - у меня 15 таблиц куда требуется прикрутить такую замену даты. Это на кажду писать по 2 триггера с заменой INSERT и UPDATE ? Как минимум, не красиво....

у вас прямые запросы лезут в таблицы?
30 ноя 09, 13:24    [7996340]     Ответить | Цитировать Сообщить модератору
 Re: замена данных перед вставкой, обновлением  [new]
Игаев
Member

Откуда: Киев
Сообщений: 204
Дедушка
у вас прямые запросы лезут в таблицы?

Да. Из приложения под Windows прямые запросы к таблицам, но они не вставляют свою дату и время, это должно делать СУБД.
30 ноя 09, 13:27    [7996354]     Ответить | Цитировать Сообщить модератору
 Re: замена данных перед вставкой, обновлением  [new]
aleks2
Guest
Игаев
Посдкажите по этому триггеру:
CREATE TRIGGER trigger_TEST
ON Table_TEST
OF INSERT, UPDATE
AS
DECLARE @iDate		int
SET @iDate = (SELECT iDate FROM SYSDATE_TO_INT());
UPDATE TEST SET DT  = @iDate WHERE  IdC IN (SELECT IdC FROM inserted) AND DT is NULL
Может его и применять? Ничего слишком критического нет в нём? Должен отрабатвать согласно условиям?


Короче надо

CREATE TRIGGER trigger_TEST
ON Table_TEST
OF INSERT, UPDATE
AS
UPDATE T SET DT  = X.iDate
FROM 
TEST T 
INNER JOIN 
inserted I
ON I.IdC=T.IdC
CROSS JOIN 
(SELECT iDate FROM SYSDATE_TO_INT()) X
WHERE  I.DT is NULL
30 ноя 09, 13:29    [7996363]     Ответить | Цитировать Сообщить модератору
 Re: замена данных перед вставкой, обновлением  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
aleks2
CREATE TRIGGER trigger_TEST
ON Table_TEST
OF INSERT, UPDATE
AS
UPDATE T SET DT  = X.iDate
FROM 
TEST T 
INNER JOIN 
inserted I
ON I.IdC=T.IdC
CROSS JOIN 
(SELECT iDate FROM SYSDATE_TO_INT()) X
WHERE  I.DT is NULL
А что такое "OF INSERT, UPDATE"?
И SYSDATE_TO_INT()?
30 ноя 09, 13:40    [7996452]     Ответить | Цитировать Сообщить модератору
 Re: замена данных перед вставкой, обновлением  [new]
Игаев
Member

Откуда: Киев
Сообщений: 204
iap
А что такое "OF INSERT, UPDATE"?
И SYSDATE_TO_INT()?

"OF INSERT, UPDATE" - это, получается, тоже самое что и "AFTER INSERT, UPDATE"
В документации пишут : "OF | AFTER | INSTEAD OF"

SYSDATE_TO_INT() - это функция возвращающая результат типа INT

Кстати, касательно SYSDATE_TO_INT(), триггер акой компилируется, а вот когда вставку в таблицу TEST делаяю, то выдаёт ошибку : Invalid object name 'SYSDATE_TO_INT'. Шо тут неправильно? 'SYSDATE_TO_INT' - тончо есть в БД.
30 ноя 09, 13:45    [7996497]     Ответить | Цитировать Сообщить модератору
 Re: замена данных перед вставкой, обновлением  [new]
Glory
Member

Откуда:
Сообщений: 104760
Игаев
iap
А что такое "OF INSERT, UPDATE"?
И SYSDATE_TO_INT()?

"OF INSERT, UPDATE" - это, получается, тоже самое что и "AFTER INSERT, UPDATE"
В документации пишут : "OF | AFTER | INSTEAD OF"


В документации пишут { FOR | AFTER | INSTEAD OF }
30 ноя 09, 13:47    [7996518]     Ответить | Цитировать Сообщить модератору
 Re: замена данных перед вставкой, обновлением  [new]
Игаев
Member

Откуда: Киев
Сообщений: 204
Ой, не OF, а FOR! OF - это там ошиблись.
30 ноя 09, 13:48    [7996526]     Ответить | Цитировать Сообщить модератору
 Re: замена данных перед вставкой, обновлением  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
Игаев
В документации пишут : "OF | AFTER | INSTEAD OF"
В документации пишут "FOR | AFTER | INSTEAD OF"
Игаев
'SYSDATE_TO_INT' - тончо есть в БД.
Такого точно нет, только если Вы сами не написали такую функцию.
30 ноя 09, 13:49    [7996537]     Ответить | Цитировать Сообщить модератору
 Re: замена данных перед вставкой, обновлением  [new]
Игаев
Member

Откуда: Киев
Сообщений: 204
iap
Такого точно нет, только если Вы сами не написали такую функцию.

Так и есть - сам написал.
30 ноя 09, 13:50    [7996550]     Ответить | Цитировать Сообщить модератору
 Re: замена данных перед вставкой, обновлением  [new]
Игаев
Member

Откуда: Киев
Сообщений: 204
Кстати, фукция в общих чертах вот такая:
CREATE FUNCTION SYSDATE_TO_INT2()
RETURNS int
BEGIN
DECLARE @iDate		int;
SET @iDate=9999; --это, естественно, упрощение
RETURN @iDate;
END
Я, наверное, неправильно присваеваю её результат в триггере?
30 ноя 09, 14:03    [7996675]     Ответить | Цитировать Сообщить модератору
 Re: замена данных перед вставкой, обновлением  [new]
Glory
Member

Откуда:
Сообщений: 104760
Игаев
Кстати, фукция в общих чертах вот такая:
CREATE FUNCTION SYSDATE_TO_INT2()
RETURNS int
BEGIN
DECLARE @iDate		int;
SET @iDate=9999; --это, естественно, упрощение
RETURN @iDate;
END
Я, наверное, неправильно присваеваю её результат в триггере?

Cкалярные функции во FROM не используются. Потому что не таблицы они
30 ноя 09, 14:06    [7996698]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить