Гость
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Триггер / 25 сообщений из 91, страница 1 из 4
18.06.2012, 10:30
    #37842272
Sky Dragon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
Здравствуйте!
Сегодня впервые столкнулся с SQL. Задача такая(на пальцах):
есть таблица ("MyTable"). В ней 2 поля: Field1 и Field2.
так вот, необходимо при изменении, если поле Field1 == null, то и Field2 тоже обнулить.
Как я понял, делается это с помощью триггера. Написал что-то типа:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
USE [MyDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER TRIGGER [dbo].[nuller_trigger]
ON [MyDB].[dbo].[MyTable]
AFTER UPDATE 
AS
   DECLARE @field1 int
   SELECT @field1 = Field1   
   FROM MyTable
IF(@field1 =null)
UPDATE MyTable
SET Field2 = null



не обнуляет. Почему то еще есть сомнения, что зациклится такое обновление, ведь всегда будет вызываться UPDATE )
Подскажите пожалуйста, как правильно? Времени читать учебники просто нет, так как это разовая задачка.
...
Рейтинг: 0 / 0
18.06.2012, 10:36
    #37842279
tpg
tpg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
Sky Dragon...не обнуляет...Не удивительно...
Триггер написан из предположения, что он вызывается для каждой измененной строки. Это не так.
...
Рейтинг: 0 / 0
18.06.2012, 10:40
    #37842283
Sky Dragon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
tpg,

подскажите пожалуйста тогда, как сделать, чтобы было "так" :)
...
Рейтинг: 0 / 0
18.06.2012, 10:44
    #37842293
iap
iap
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
Sky Dragontpg,

подскажите пожалуйста тогда, как сделать, чтобы было "так" :)1. Сравнивать поля/переменные с NULL операторами =,<>,<,> и т.п. нельзя!
2. Старайтесь не использовать скалярные переменные в триггерах.
3. Используйте псевдотаблицы deleted и inserted
...
Рейтинг: 0 / 0
18.06.2012, 10:46
    #37842297
iap
iap
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
4. За UPDATE без WHERE надо расстреливать! (За редким исключением)
...
Рейтинг: 0 / 0
18.06.2012, 10:47
    #37842299
tpg
tpg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
... и ничего не сказано о наличии ПК или ещё какого уникального столбца.
...
Рейтинг: 0 / 0
18.06.2012, 10:48
    #37842301
iap
iap
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
iap4. За UPDATE без WHERE надо расстреливать! (За редким исключением)WHERE или INNER JOIN или CROSS APPLY, если точнее
...
Рейтинг: 0 / 0
18.06.2012, 13:18
    #37842584
Winnipuh
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
iap4. За UPDATE без WHERE надо расстреливать! (За редким исключением)

всех не перестреляешь!
...
Рейтинг: 0 / 0
18.06.2012, 13:51
    #37842641
RubinDm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
alter trigger [dbo].[nuller_trigger]
  on [MyDB].[dbo].[MyTable] after update
as
begin

  -- Если UPDATE не задел поле [Field1], то ...
  if (not(update(Field1)))
    return; -- нет необходимости в сбросе значения поля [Field2] в NULL

  -- Если UPDATE не задел записи таблицы, то ...
  if (not(exists(select * from [inserted]))
    return; -- нет необходимости в сбросе значения поля [Field2] в NULL

  -- Проверяем наличие записей, в которых
  -- значение поля [Field1] было сброшено в NULL.
  if (not(exists(
    select [new].[ID]
    from [inserted] [new]
    join [deleted]  [old] on [old].[ID] = [new].[ID]
    where [old].Field1 is NOT null
      and [new].Field1 is null
  )))
    return; -- нет необходимости в сбросе значения поля [Field2] в NULL
  
  -- Сброс значения поля [Field2] в NULL
  update T set T.Field2 = null
  from MyTable T
  where T.[ID] in ( -- тут мы вычисляем ID записей, в которых
                    -- значение поля [Field1] было сброшено в NULL.
                    select [new].[ID]
                    from [inserted] [new]
                    join [deleted]  [old] on [old].[ID] = [new].[ID]
                    where [old].Field1 is NOT null
                      and [new].Field1 is null
                  )
  
  return;

end
go



зы: не проверял (ибо не на чем)
...
Рейтинг: 0 / 0
18.06.2012, 16:20
    #37842926
iap
iap
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
RubinDm,

применение функции UPDATE() - абсолютно бессмысленно
...
Рейтинг: 0 / 0
18.06.2012, 17:59
    #37843103
Xordal
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
Да и 2 раза выполнять:
Код: sql
1.
2.
3.
4.
5.
    select [new].[ID]
    from [inserted] [new]
    join [deleted]  [old] on [old].[ID] = [new].[ID]
    where [old].Field1 is NOT null
      and [new].Field1 is null


думаю тоже ни к чему.
...
Рейтинг: 0 / 0
18.06.2012, 18:21
    #37843134
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
Xordal,

В общем-то, даже и один раз ни к чему.
...
Рейтинг: 0 / 0
18.06.2012, 19:09
    #37843192
RubinDm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
iapRubinDm, применение функции UPDATE() - абсолютно бессмысленноНе могли бы Вы аргументировать Ваш комент?
...
Рейтинг: 0 / 0
18.06.2012, 19:10
    #37843193
RubinDm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
XordalДа и 2 раза выполнять:
Код: sql
1.
2.
3.
4.
5.
    select [new].[ID]
    from [inserted] [new]
    join [deleted]  [old] on [old].[ID] = [new].[ID]
    where [old].Field1 is NOT null
      and [new].Field1 is null


думаю тоже ни к чему.И Вы... не могли бы Вы аргументировать Ваш комент?
...
Рейтинг: 0 / 0
18.06.2012, 19:10
    #37843195
RubinDm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
invmXordal, В общем-то, даже и один раз ни к чему.И Вы... не могли бы Вы аргументировать Ваш комент?
...
Рейтинг: 0 / 0
18.06.2012, 20:03
    #37843240
iap
iap
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
RubinDmiapRubinDm, применение функции UPDATE() - абсолютно бессмысленноНе могли бы Вы аргументировать Ваш комент?А можно сначала услышать Ваш комментарий по этому поводу?
...
Рейтинг: 0 / 0
18.06.2012, 20:26
    #37843256
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
RubinDminvmXordal, В общем-то, даже и один раз ни к чему.И Вы... не могли бы Вы аргументировать Ваш комент?
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
alter trigger [dbo].[nuller_trigger]
  on [MyDB].[dbo].[MyTable] after update
as
begin

  -- Если UPDATE не задел поле [Field1], то ...
  if (not(update(Field1)))
    return; -- нет необходимости в сбросе значения поля [Field2] в NULL

  -- Если UPDATE не задел записи таблицы, то ...
  if (not(exists(select * from [inserted]))
    return; -- нет необходимости в сбросе значения поля [Field2] в NULL

  -- Сброс значения поля [Field2] в NULL
  update T
   set
    T.Field2 = null
  from
   inserted i join
   deleted d on d.[ID] = i.[ID] join
   MyTable T on t.[ID] = i.[ID]
  where
   i.Field1 is null and d.Field1 is not null;

 return;
end
go
...
Рейтинг: 0 / 0
18.06.2012, 21:31
    #37843303
RubinDm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
iapRubinDmпропущено...Не могли бы Вы аргументировать Ваш комент?А можно сначала услышать Ваш комментарий по этому поводу?Можно. Я всегда рад помочь незрячим и слабовидящим:
Код: sql
1.
2.
3.
-- Если UPDATE не задел поле [Field1], то ...
  if (not(update(Field1)))
    return; -- нет необходимости в сбросе значения поля [Field2] в NULL

Теперь не могли бы Вы аргументировать Ваш комент?
...
Рейтинг: 0 / 0
18.06.2012, 21:38
    #37843311
iap
iap
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
RubinDmiapпропущено...
А можно сначала услышать Ваш комментарий по этому поводу?Можно. Я всегда рад помочь незрячим и слабовидящим:
Код: sql
1.
2.
3.
-- Если UPDATE не задел поле [Field1], то ...
  if (not(update(Field1)))
    return; -- нет необходимости в сбросе значения поля [Field2] в NULL

Теперь не могли бы Вы аргументировать Ваш комент?"Задел поле" - это как понимать?
...
Рейтинг: 0 / 0
18.06.2012, 21:59
    #37843338
RubinDm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
iapRubinDmпропущено...
Можно. Я всегда рад помочь незрячим и слабовидящим:
Код: sql
1.
2.
3.
-- Если UPDATE не задел поле [Field1], то ...
  if (not(update(Field1)))
    return; -- нет необходимости в сбросе значения поля [Field2] в NULL

Теперь не могли бы Вы аргументировать Ваш комент?"Задел поле" - это как понимать?
1) Этот запрос задевает (меняет) значение поля Field1 и не задевает (не меняет) значение поля Field2.
Код: sql
1.
update T set Field1 = ... from MyTable T


2) Этот запрос задевает (меняет) значение поля Field2 и не задевает (не меняет) значение поля Field1.
Код: sql
1.
update T set Field2 = ... from MyTable T


3) Этот запрос задевает (меняет) значения обоих полей.
Код: sql
1.
update T set Field1 = ..., Field2 = ... from MyTable T


По условиям поставленной автором топика задачи интерес представляют только те случаи, в которых значение поля Field1 может быть изменено (примеры 1 и 3). В противном случае (пример 2) актуализация поля Field2 не требуется, т.к. Field1 не меняется и ловить там нечего в принципе.

Так я увижу Ваши аргументы или забудем об этом?
...
Рейтинг: 0 / 0
19.06.2012, 09:44
    #37843649
Xordal
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
RubinDmXordalДа и 2 раза выполнять:
Код: sql
1.
2.
3.
4.
5.
    select [new].[ID]
    from [inserted] [new]
    join [deleted]  [old] on [old].[ID] = [new].[ID]
    where [old].Field1 is NOT null
      and [new].Field1 is null


думаю тоже ни к чему.И Вы... не могли бы Вы аргументировать Ваш комент?
Ну это условие как минимум один раз будет проверяться, а в случае если есть что апдейтить, то даже 2 раза. Зачем серверу лишнюю работу давать? И, как отметил invm, в update ... set ... подзапрос не нужен, можно сразу джойниться на таблицы inserted и deleted
...
Рейтинг: 0 / 0
19.06.2012, 09:52
    #37843665
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
2 RubinDm

Код: sql
1.
if (not(update(Field1)))

это полезный стейтмент, позволит уменьшить нагрузку на сервер

Код: sql
1.
if (not(exists(select * from [inserted]))

не нужно, обновление и так не будет потреблять ресурсов, если в inserted ничего нет.

Код: sql
1.
2.
if (not(exists(
    select [new].[ID] ...

не нужно, запрос в update сделает то же самое.

А из обновления можно убрать лишний джойн:
Код: sql
1.
2.
3.
4.
5.
6.
7.
-- Сброс значения поля [Field2] в NULL
  update T
  set T.Field2 = null
  from deleted d
   MyTable T on T.[ID] = d.[ID]
  where
    T.Field1 is null and d.Field1 is not null;
...
Рейтинг: 0 / 0
19.06.2012, 10:03
    #37843694
Sky Dragon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
Ого, сколько обсуждений вызвал такой маленький вопрос)
Из одних только комментариев уже можно выучить синтаксис SQL )

Всем спасибо, что откликнулись
...
Рейтинг: 0 / 0
19.06.2012, 12:39
    #37844090
iap
iap
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
RubinDmiapпропущено...
"Задел поле" - это как понимать?
1) Этот запрос задевает (меняет) значение поля Field1 и не задевает (не меняет) значение поля Field2.
Код: sql
1.
update T set Field1 = ... from MyTable T


2) Этот запрос задевает (меняет) значение поля Field2 и не задевает (не меняет) значение поля Field1.
Код: sql
1.
update T set Field2 = ... from MyTable T


3) Этот запрос задевает (меняет) значения обоих полей.
Код: sql
1.
update T set Field1 = ..., Field2 = ... from MyTable T


По условиям поставленной автором топика задачи интерес представляют только те случаи, в которых значение поля Field1 может быть изменено (примеры 1 и 3). В противном случае (пример 2) актуализация поля Field2 не требуется, т.к. Field1 не меняется и ловить там нечего в принципе.

Так я увижу Ваши аргументы или забудем об этом?Кто кого "задевает" в этом примере:
Код: sql
1.
update T set Field1 = Field1, Field2 = Field2 from MyTable T

?
...
Рейтинг: 0 / 0
19.06.2012, 12:53
    #37844112
RubinDm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Триггер
iapКто кого "задевает" в этом примере:
Код: sql
1.
update T set Field1 = Field1, Field2 = Field2 from MyTable T

?Задевает поля инструкция, в данном случае это update , который задевает два поля: Field1 и Field2. Тот факт, что значения полей фактически не должны изменится, вовсе не означает, что сервер не должен выполнять инструкцию update. Сервер понимает, что могут быть тригеры, которые также могут влиять на результат выполнения инструкции. Возможно, что сервер понимает еще много разного, о чем мы даже не догадываемся. При этом полей в таблице иногда бывает много, но не всегда все из них подвергаются воздействиям инструкции update. И в тригерах, как правило, надо отлавливать изменение только конкретного набора полей, как в случае задачи поставленной автором топика. Вызов функции update(Field1) отвечает на вопрос, было ли упомянуто поле Field1 в инструкции update в части set. Если не было, но нет никакой необходимости в актуализации Field2.
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Триггер / 25 сообщений из 91, страница 1 из 4
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]