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

Откуда:
Сообщений: 11
Всем добрый день.

Есть вот такой триггер:
ALTER TRIGGER [dbo].[tD_SMS_USER_GROUP] ON [dbo].[SMS_USER_GROUP] FOR DELETE AS
/* ERwin Builtin Trigger */
BEGIN
  DECLARE  @errno   int,
           @errmsg  varchar(255)
    IF EXISTS (SELECT * FROM deleted,SMS_USERS
      WHERE
        deleted.USER_ID = SMS_USERS.USER_ID AND
        NOT EXISTS (
          SELECT * FROM SMS_USER_GROUP
          WHERE
            SMS_USER_GROUP.USER_ID = SMS_USERS.USER_ID
        )
    )
    BEGIN
      SELECT @errno  = 30010,
             @errmsg = 'Cannot delete last SMS_USER_GROUP because SMS_USERS exists.'
      GOTO ERROR
    END

    RETURN
ERROR:
    raiserror @errno @errmsg
    rollback transaction
END

Вопрос: в какой момент выполняется этот триггер: до удаления записи из таблицы или после?
10 янв 13, 11:29    [13745712]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31962
ginsar
Вопрос: в какой момент выполняется этот триггер: до удаления записи из таблицы или после?
Триггеры FOR (и AFTER) выполняются после совершения операции.
10 янв 13, 11:40    [13745792]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
iap
Member

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

после
10 янв 13, 11:40    [13745798]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74930
Уже давно пора заменить Ервиновские триггера на FK.
10 янв 13, 13:45    [13746776]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
ginsar
Member

Откуда:
Сообщений: 11
Тогда понятно почему этот триггер неправильно отрабатывает.
Чтобы сделать триггер до совершения события, надо сделать его как INSTED OF ?
11 янв 13, 09:02    [13751545]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31962
ginsar
Тогда понятно почему этот триггер неправильно отрабатывает.
Странно, не вижу ошибки.

В любом случае, при срабатывании до удаления он точно будет работать неправильно.

ginsar
Чтобы сделать триггер до совершения события, надо сделать его как INSTED OF ?
Да, только точнее будет сказать "вместо", а не "до" события.
11 янв 13, 09:06    [13751559]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
Гость333
Member

Откуда:
Сообщений: 3683
ginsar
Тогда понятно почему этот триггер неправильно отрабатывает.

Поясните, что вы имеете в виду под "неправильно отрабатывает".
11 янв 13, 10:13    [13751887]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
Гость333
ginsar
Тогда понятно почему этот триггер неправильно отрабатывает.

Поясните, что вы имеете в виду под "неправильно отрабатывает".
JOIN таблицы с deleted некорректен - ведь в таблице этих записей в этот момент уже нет!
IF EXISTS() в данном случае всегда вернёт FALSE
11 янв 13, 10:44    [13752090]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
Glory
Member

Откуда:
Сообщений: 104751
iap
JOIN таблицы с deleted некорректен - ведь в таблице этих записей в этот момент уже нет!

там join c другой таблицей. Не из которой удаление происходит
Просто имена очень похожи
11 янв 13, 10:45    [13752105]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
iap
Гость333
пропущено...

Поясните, что вы имеете в виду под "неправильно отрабатывает".
JOIN таблицы с deleted некорректен - ведь в таблице этих записей в этот момент уже нет!
IF EXISTS() в данном случае всегда вернёт FALSE
Хотя, триггер относится к SMS_USER_GROUP, а не к SMS_USERS...
Но ведь всё равно используется неявная связь deleted и SMS_USER_GROUP
11 янв 13, 10:48    [13752128]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
Ennor Tiegael
Member

Откуда:
Сообщений: 3422
iap
iap
пропущено...
JOIN таблицы с deleted некорректен - ведь в таблице этих записей в этот момент уже нет!
IF EXISTS() в данном случае всегда вернёт FALSE
Хотя, триггер относится к SMS_USER_GROUP, а не к SMS_USERS...
Но ведь всё равно используется неявная связь deleted и SMS_USER_GROUP
Там проверяется, остались на пользователи, членство в группах которых было удалено, хоть в какой-нибудь еще группе, и если нет, то рейзится ошибка - типа нельзя.

Другой вопрос, что синтаксис RAISERROR() какой-то очень странный. Да и сиквел, вроде, не должен дать так просто зарейзить ошибку с кодом меньше 50000...
11 янв 13, 10:52    [13752154]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
Ennor Tiegael
Другой вопрос, что синтаксис RAISERROR() какой-то очень странный. Да и сиквел, вроде, не должен дать так просто зарейзить ошибку с кодом меньше 50000...
Именно такой синтаксис предлагается в шаблоне для MSSQL в ErWinе.
Очень хорошо помню. И кучу объявлений переменных в триггерах помню.
Предлагается в них сохранять результат запроса из inserted/deleted.
Вот оттуда-то и тянутся многочисленные ошибки в триггерах у вопрошающих на форуме
11 янв 13, 11:05    [13752264]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
Гость333
Member

Откуда:
Сообщений: 3683
Ennor Tiegael
синтаксис RAISERROR() какой-то очень странный.

Упоминание такого синтаксиса есть, например, здась: Deprecated Database Engine Features in SQL Server 2008 R2

автор
Category; Deprecated feature; Replacement; Feature name; Feature ID
Transact-SQL; The old style syntax for RAISERROR (Format: RAISERROR integer string) syntax is deprecated.; Rewrite the statement using the current RAISERROR syntax.; Old style RAISEERROR; 164


Насколько древняя эта фича, трудно сказать, ибо во всех доступных BOL (начиная с 2000), такой синтаксис не документирован.

Ennor Tiegael
Да и сиквел, вроде, не должен дать так просто зарейзить ошибку с кодом меньше 50000...

Ну вообще даёт:
raiserror 12999 'Cannot delete last SMS_USER_GROUP because SMS_USERS exists.'
raiserror 13000 'Cannot delete last SMS_USER_GROUP because SMS_USERS exists.'


автор
Msg 2732, Level 16, State 1, Line 1
Error number 12999 is invalid. The number must be from 13000 through 2147483647 and it cannot be 50000.
Msg 13000, Level 16, State 1, Line 3
Cannot delete last SMS_USER_GROUP because SMS_USERS exists.
11 янв 13, 11:08    [13752297]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
Гость333
Member

Откуда:
Сообщений: 3683
Category Deprecated feature Replacement Feature name Feature ID
Transact-SQL The old style syntax for RAISERROR (Format: RAISERROR integer string) syntax is deprecated. Rewrite the statement using the current RAISERROR syntax. Old style RAISEERROR 164


Так лучше, извиняюсь за корявое форматирование.
11 янв 13, 11:10    [13752311]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
ginsar
Member

Откуда:
Сообщений: 11
iap
JOIN таблицы с deleted некорректен - ведь в таблице этих записей в этот момент уже нет!
IF EXISTS() в данном случае всегда вернёт FALSE

Видимо поэтому у меня он и делает не то что нужно...
Всем спасибо за ответы.
17 янв 13, 10:54    [13783089]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
Glory
Member

Откуда:
Сообщений: 104751
ginsar
iap
JOIN таблицы с deleted некорректен - ведь в таблице этих записей в этот момент уже нет!
IF EXISTS() в данном случае всегда вернёт FALSE

Видимо поэтому у меня он и делает не то что нужно...

Триггер корректный. И делает то, для чего и создавался - для проверки ссылочной целостности между таблицами SMS_USER_GROUP и SMS_USERS
17 янв 13, 10:58    [13783117]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
Гость333
Member

Откуда:
Сообщений: 3683
ginsar
Видимо поэтому у меня он и делает не то что нужно...

Но вы так и не пояснили, что именно ненужного он делает.
То есть непонятно — что вы ожидаете от триггера, и что происходит на самом деле.
17 янв 13, 11:02    [13783146]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
ginsar
Member

Откуда:
Сообщений: 11
Гость333
ginsar
Видимо поэтому у меня он и делает не то что нужно...

Но вы так и не пояснили, что именно ненужного он делает.
То есть непонятно — что вы ожидаете от триггера, и что происходит на самом деле.

Триггер делает проверку таблицы SMS_USERS после удаления строки в SMS_USER_GROUP.
Т.к. в момент проверки удаление записи в таблице SMS_USER_GROUP уже произошло, то IF EXISTS всегда возвращает TRUE и срабатывает откат транзакции. Таким образом удаление записи в SMS_USER_GROUP не происходит.

По логике создания БД пользователь может существовать, но не входить ни в одну группу. Поэтому этот триггер просто не нужен. Я его отключил и все заработало как надо.
18 янв 13, 09:45    [13789117]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
Гость333
Member

Откуда:
Сообщений: 3683
ginsar
По логике создания БД пользователь может существовать, но не входить ни в одну группу.

Ясно, спасибо за разъяснение.

С Ервином дела не имел, может кто-нибудь пояснить, в каких случаях он создаёт подобные триггеры? С учётом того, что "пользователь может существовать, но не входить ни в одну группу" — имеем ошибочно нарисованную схему данных в Ервине, или Ервиновский глюк построения объектов БД?
18 янв 13, 09:59    [13789202]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
ginsar
Member

Откуда:
Сообщений: 11
Гость333
С Ервином дела не имел, может кто-нибудь пояснить, в каких случаях он создаёт подобные триггеры? С учётом того, что "пользователь может существовать, но не входить ни в одну группу" — имеем ошибочно нарисованную схему данных в Ервине, или Ервиновский глюк построения объектов БД?

Не могу однозначно сказать глюк это Ервина или ошибка в создании схемы, но как я не пытался исправить схему и указать в свойствах связи этих таблиц, что "пользователь может существовать, но не входить ни в одну группу" триггер все равно создается и имеет указанный вид...
может кто подскажет, какой вид связи надо устанавливать в таком случае?
18 янв 13, 10:07    [13789256]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
Glory
Member

Откуда:
Сообщений: 104751
ginsar
Триггер делает проверку таблицы SMS_USERS после удаления строки в SMS_USER_GROUP.
Т.к. в момент проверки удаление записи в таблице SMS_USER_GROUP уже произошло, то IF EXISTS всегда возвращает TRUE и срабатывает откат транзакции. Таким образом удаление записи в SMS_USER_GROUP не происходит.


И как же IF EXISTS может вернуть TRUE, если "удаление записи в таблице SMS_USER_GROUP уже произошло," ? Т.е. записей нет, в возвращается TRUE ?
18 янв 13, 10:22    [13789350]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
Гость333
Member

Откуда:
Сообщений: 3683
Glory
И как же IF EXISTS может вернуть TRUE, если "удаление записи в таблице SMS_USER_GROUP уже произошло," ? Т.е. записей нет, в возвращается TRUE ?

IF EXISTS проверяет наличие записей в SMS_USERS:
    IF EXISTS (SELECT * FROM deleted,SMS_USERS

Наличие (точнее, отсутствие) записей в SMS_USER_GROUP проверяется условием в запросе:
        NOT EXISTS (
          SELECT * FROM SMS_USER_GROUP

"Удаление записи в таблице SMS_USER_GROUP уже произошло" (в контексте транзакции, конечно), а запись в SMS_USERS есть => not exists вернёт true => if exists вернёт true.

(Простите за капитанство :-)
18 янв 13, 10:54    [13789592]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
Glory
Member

Откуда:
Сообщений: 104751
Гость333
"Удаление записи в таблице SMS_USER_GROUP уже произошло" (в контексте транзакции, конечно), а запись в SMS_USERS есть => not exists вернёт true => if exists вернёт true.

Ну так это значит, что в группе оставлись пользователи
Это и делается для - 'Cannot delete last SMS_USER_GROUP because SMS_USERS exists.'
Где "глюк" то ?
18 янв 13, 11:01    [13789646]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31962
Glory
ginsar
Триггер делает проверку таблицы SMS_USERS после удаления строки в SMS_USER_GROUP.
Т.к. в момент проверки удаление записи в таблице SMS_USER_GROUP уже произошло, то IF EXISTS всегда возвращает TRUE и срабатывает откат транзакции. Таким образом удаление записи в SMS_USER_GROUP не происходит.


И как же IF EXISTS может вернуть TRUE, если "удаление записи в таблице SMS_USER_GROUP уже произошло," ? Т.е. записей нет, в возвращается TRUE ?
Текст условия немного того, избыточный.

Вместо:
    IF EXISTS (SELECT * FROM deleted,SMS_USERS
      WHERE
        deleted.USER_ID = SMS_USERS.USER_ID AND
        NOT EXISTS (
          SELECT * FROM SMS_USER_GROUP
          WHERE
            SMS_USER_GROUP.USER_ID = SMS_USERS.USER_ID
        )
    )

Можно написать:
IF NOT EXISTS (
          SELECT * FROM deleted, SMS_USER_GROUP
          WHERE SMS_USER_GROUP.USER_ID = deleted.USER_ID
   )
Т.е. "если пользователь из удалённой привязки к группе не привязан хотя бы ещё к одной группе, то это ошибка"

Т.ею. триггер правильный, просто бизнес-логика изменилась, и триггер нужно удалить. А ginsar всех вводит в заблуждение, говоря, что в тексте триггера ошибка :-)
18 янв 13, 11:02    [13789652]     Ответить | Цитировать Сообщить модератору
 Re: в какой момент выполняется триггер?  [new]
Гость333
Member

Откуда:
Сообщений: 3683
Glory
Гость333
"Удаление записи в таблице SMS_USER_GROUP уже произошло" (в контексте транзакции, конечно), а запись в SMS_USERS есть => not exists вернёт true => if exists вернёт true.

Ну так это значит, что в группе оставлись пользователи

Неее... Это значит, что у пользователя не осталось ни одной группы, в которую он входит.

Glory
Это и делается для - 'Cannot delete last SMS_USER_GROUP because SMS_USERS exists.'

"Нельзя удалить вхождение пользователя в группу, поскольку это его последняя группа, и он больше никуда не будет входить". Как-то так следует читать указанное сообщение. Об этом ещё Ennor Tiegael написал.

Glory
Где "глюк" то ?

В триггере нет никакого глюка, он вполне делает то, для чего предназначен :-)
Глюк либо в криво нарисованной схеме данных erwin, либо схема хороша, а erwin создал в БД какую-то отсебятину.
18 янв 13, 11:29    [13789867]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить