Конференция "Базы" » MS SQL. inserted и deleted таблицы в InstedOfUpdate триггере
 
  • ЮЮ © (25.09.08 02:02) [0]
    У кого какие мысли по поводу того, в одном и том ли порядке следуют записи ы этих табоицах? :)
  • Ega23 © (25.09.08 09:54) [1]
    Update - суть удаление предыдущей и вставка новой записи.
    Далее - со всеми вытекающими.
  • ЮЮ © (25.09.08 10:25) [2]
    > Далее - со всеми вытекающими.


    Я имел в виду: Имеет ли место тот факт, что порядок следования записей в deleted и inserted один и тот же и можно в одном ципле по курсору из, (например, inserted) параллельно фетчить записи из куhсора по deleted.

    Вот, например, у нас программно генерится такая стандартная болванка:

    CREATE TRIGGER E_Employments_OnUpdate ON E_Employments
    INSTEAD OF UPDATE
    AS
    BEGIN
     DECLARE @Admin int
     SELECT @Admin = dbo.UuaIsUserAdmin()
     DECLARE c_i CURSOR LOCAL FOR SELECT
       [Position],
       [DocumentItem],
       [EmploymentRate]
     FROM inserted
     DECLARE c_d CURSOR LOCAL FOR SELECT [Id]
     FROM deleted

     DECLARE @Position int
     DECLARE @DocumentItem int
     DECLARE @EmploymentRate float
     DECLARE @deleted_Id int
     OPEN c_i
     OPEN c_d

     FETCH NEXT FROM c_d INTO @deleted_Id
     FETCH NEXT FROM c_i INTO
       @Position,
       @DocumentItem,
       @EmploymentRate
     WHILE @@FETCH_STATUS <> - 1 BEGIN
       IF @@FETCH_STATUS = 0 BEGIN
         UPDATE E_Employments SET
           [Position] = @Position,
           [DocumentItem] = @DocumentItem,
           [EmploymentRate] = @EmploymentRate
         WHERE [Id] = @deleted_Id
       END
       FETCH NEXT FROM c_d INTO @deleted_Id
       FETCH NEXT FROM c_i INTO
         @Position,
         @DocumentItem,
         @EmploymentRate
     END
    END



    и я всегда без стаха им пользовался. Но вчера наткнулся на непрятные последствия использования такой схемы.
  • Василий Жогарев © (25.09.08 10:33) [3]

    > ЮЮ ©   (25.09.08 10:25) [2]


    Кто-то на форуме помнится кричал, что курсоры в триггере это жесть...
    А ты сортируй таблицы
    Inserted

    и
    Deleted

    в том порядке, в котором есть необходимость...
  • Виталий Панасенко (25.09.08 10:36) [4]

    > Василий Жогарев ©   (25.09.08 10:33) [3]

    А это как? Особенно, если ключ поменялся.Я, конечно, не спец в "скале", но возник такой вопрос. ORDER BY KEY нам даст очень прикольный результат
  • Ega23 © (25.09.08 10:46) [5]
    В чём проблема?

    DECLARE c_i CURSOR LOCAL FOR SELECT
      [Position],
      [DocumentItem],
      [EmploymentRate]
    FROM inserted
    ORDER BY Так как надо



    И так везде.
  • ЮЮ © (25.09.08 10:50) [6]
    > Кто-то на форуме помнится кричал, что курсоры в триггере
    > это жесть...

    Ну уж точно не я :)


    > если ключ поменялся

    вот этим никогда не балуюсь, ибо Id - атрибут по имени Судьба: сто получил, с тем и живи :)


    > ORDER BY KEY нам даст очень прикольный результат

    ORDER BY KEY только и спас в той ситуации, когда в запрос, заполянявший одно-лишь поле в таблице (поле связи, ранее отсутсвкющее) проапдейтил все записи таблицы так, что "лог изменений" чуть не треснул :)
  • ЮЮ © (25.09.08 10:55) [7]
    > В чём проблема?
    >
    > DECLARE c_i CURSOR LOCAL FOR SELECT
    >  [Position],
    >  [DocumentItem],
    >  [EmploymentRate]
    > FROM inserted
    > ORDER BY Так как надо
    >
    > И так везде.


    Проблема в том, что много лет триггеры писались по схеме [2], без сортировки. А вчера, набрёл на эти грабли и всю ночь ломал голову как все это "откатить".
  • Ega23 © (25.09.08 11:13) [8]
    Если порядок сортировки важен, то Order By обязательно надо указывать. Т.к., теоретически, 2 абсолютно одинаковых по тексту запроса могут дать одну и ту же выборку, но отсортированную по-разному.
  • stas © (25.09.08 11:24) [9]
    >ЮЮ ©   (25.09.08 10:25) [2]
    тут помоему можно обойтись и без курсора.
  • ЮЮ © (25.09.08 11:33) [10]
    > тут помоему можно обойтись и без курсора.

    триггер по болванке с курсором естественно делается когда нужна обработка для каждой записи. Сама болванка полезного кода не содержит, а избавляет от необходимости объявлять локальнве переменные и перечислять их и поля в запросах.
  • Ega23 © (25.09.08 11:44) [11]

    > ЮЮ ©  


    Напрямую к делу не относится, но:
    1. Коль скоро открыл кусор - закрой в конце.
    2. Deallocate тоже нефигово делать.
  • KSergey © (25.09.08 13:36) [12]
    > Виталий Панасенко   (25.09.08 10:36) [4]
    > А это как? Особенно, если ключ поменялся.

    Тогда это не ключ а профанация. Тогда вообще концов не сыскать.
  • stone (25.09.08 13:57) [13]
    Я вот только не понял зачем тут
    DECLARE @Admin int
    SELECT @Admin = dbo.UuaIsUserAdmin()


    и зачем тут курсоры вообще?
  • Виталий Панасенко (25.09.08 15:18) [14]

    > KSergey ©   (25.09.08 13:36) [12]

    А если ПК - "натуральный"  и ты ошибся, например, в МФО? а МФО - ключ
  • ANB (25.09.08 20:40) [15]

    > А если ПК - "натуральный"  и ты ошибся, например, в МФО?
    >  а МФО - ключ

    Вот оно - преимущество искусственных ключей.
  • ЮЮ © (26.09.08 02:32) [16]
    > [13] stone   (25.09.08 13:57)
    > Я вот только не понял зачем тут


    У ты какой любопытный :)

    Это проверка прав на корректировку данной записи данной таблицы.


    > и зачем тут курсоры вообще?

    см.[10].
  • stone (26.09.08 10:38) [17]

    > ЮЮ ©   (26.09.08 02:32) [16]

    Тогда рекомендую избавится от одного из курсоров, либо заменить его на альтернативный цикл. Иначе @@FETCH_STATUS не всегда будет принимать то значение, которое ты ожидаешь.
  • ЮЮ © (26.09.08 11:14) [18]
    > Иначе @@FETCH_STATUS не всегда будет принимать то значение

    С чего это? Количестов записей в inserted и deleted по определению равны. поэтому и @@FETCH_STATUS будет одинаков для обоих курсоров.
    Подчеркиваю, проблематичным оказался различный порядок записей.
    Возможно это было так всегда, но не парило до тех пор, пока не возникла потребность в ведении доп.таблицы логов изменений.
  • stone (26.09.08 12:28) [19]
    Если количество записей равно и иды совпадают (т.е. не менялись), тогда смысл второго курсора вообще теряется. Соответственно и порядок записей с одним курсором не будет иметь решающего значения.
    Либо ты что-то не договариваешь.
 
Конференция "Базы" » MS SQL. inserted и deleted таблицы в InstedOfUpdate триггере
Есть новые Нет новых   [134444   +21][b:0][p:0.002]