1. SQL / Говнокод #15698

    −123

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    ALTER TRIGGER [dbo].[ObjectTrade]
    ON [dbo].[packets] 
    AFTER INSERT
    AS 
    BEGIN
    SET NOCOUNT ON;
    
    DECLARE
    @id_key int,
    @id_th int,
    @date_end datetime,
    @date_beg datetime
    
    SET @id_key = (SELECT id_key FROM inserted)
    SET @id_th = (SELECT id_th FROM inserted WHERE id_key = @id_key)
    SET @date_end = (SELECT date_end FROM inserted WHERE id_key = @id_key)
    SET @date_beg = (SELECT date_beg FROM inserted WHERE id_key = @id_key)
    
    IF @id_th = 183 
    UPDATE packets 
    SET packets.date_end = CAST('12-05-2014' AS DATE) 
    WHERE id_key =@id_key
    
    IF (CAST(@date_end AS DATE) BETWEEN '08-03-2014' and '10-03-2014') SET @date_end = '07-03-2014'
    IF (CAST(@date_end AS DATE) BETWEEN '01-05-2014' and '04-05-2014') SET @date_end = '30-04-2014'
    IF (CAST(@date_end AS DATE) BETWEEN '09-05-2014' and '11-05-2014') SET @date_end = '08-05-2014'
    IF (CAST(@date_end AS DATE) BETWEEN '12-06-2014' and '15-06-2014') SET @date_end = '11-06-2014'
    IF (CAST(@date_end AS DATE) BETWEEN '02-11-2014' and '04-11-2014') SET @date_end = '01-11-2014'
    IF (CAST(@date_end AS DATE) BETWEEN '01-01-2015' and '08-01-2015') SET @date_end = '31-12-2014'
    IF DATEPART(WEEKDAY, @date_end) = 7 SET @date_end = DATEADD(DAY, -1, @date_end)
    UPDATE packets SET packets.date_end = @date_end WHERE id_key =@id_key
    
    END

    Запостил: kerberos, 07 Апреля 2014

    Комментарии (20) RSS

    • интересно, а автор этих строк знает, что произойдет с его триггером, когда туда вставят больше одной строки? и это не говоря уже о логики :)
      Ответить
    • > SET @id_key = (SELECT id_key FROM inserted)
      Как писали выше - свалится при массовом апдейте.
      Видел решение от продвинутых гуру SQL: SELECT TOP 1 ... И никогда не свалится. Problemz?

      > IF @id_th = 183
      Ммм...магические цифры, да.

      > CAST('12-05-2014' AS DATE)
      Ммм...магические даты, да. Первый рабочий день после отмечания дня победы?

      > IF (CAST(@date_end AS DATE) BETWEEN '08-03-2014' and '10-03-2014') SET @date_end = '07-03-2014'
      > IF (CAST(@date_end AS DATE) BETWEEN '01-05-2014' and '04-05-2014') SET @date_end = '30-04-2014'
      > IF (CAST(@date_end AS DATE) BETWEEN '09-05-2014' and '11-05-2014') SET @date_end = '08-05-2014'
      > IF (CAST(@date_end AS DATE) BETWEEN '12-06-2014' and '15-06-2014') SET @date_end = '11-06-2014'
      > IF (CAST(@date_end AS DATE) BETWEEN '02-11-2014' and '04-11-2014') SET @date_end = '01-11-2014'
      > IF (CAST(@date_end AS DATE) BETWEEN '01-01-2015' and '08-01-2015') SET @date_end = '31-12-2014'

      И действительно, зачем глобальный справочник времени?
      Вот же, все государственные праздники, в самом труЪ месте для этого - триггере! В следующем году обязательно подправим.

      > IF DATEPART(WEEKDAY, @date_end) = 7 SET @date_end = DATEADD(DAY, -1, @date_end)
      А если воскресенье? Тогда суббота.
      Ответить
      • > Как писали выше - свалится при массовом апдейте.
        в MS SQL нет чтоли for each row?..
        Ответить
        • Ну, inserted - можно сказать "виртуальная" таблица. Можно и курсор на ней станцевать и любые другие непристойности с SELECT'ом вытворять.
          Соль в том, что конструкция SET @variable = (SELECT bla bla bla) подразумевает, что SELECT bla bla bla вернёт одно и только одно значение.
          Ответить
          • А в before insert эта таблица по-другому называется?
            Ответить
            • > before insert
              Нет такого :) Есть INSTEAD OF.
              Там такое же название таблицы будет.
              Разница в типах DML.
              Тип DML - доступные временные таблицы в памяти: INSERT - inserted, DELETE - deleted, UPDATE - inserted & deleted.
              Ответить
              • а FOR INSERT тогда что?
                -- SQL Server Syntax 
                Trigger on an INSERT, UPDATE, or DELETE statement to a table or view (DML Trigger)
                
                CREATE TRIGGER [ schema_name . ]trigger_name 
                ON { table | view } 
                [ WITH <dml_trigger_option> [ ,...n ] ]
                { FOR | AFTER | INSTEAD OF } 
                { [ INSERT ] [ , ] [ UPDATE ] [ , ] [ DELETE ] } 
                [ NOT FOR REPLICATION ] 
                AS { sql_statement  [ ; ] [ ,...n ] | EXTERNAL NAME <method specifier [ ; ] > }
                
                <dml_trigger_option> ::=
                    [ ENCRYPTION ]
                    [ EXECUTE AS Clause ]
                
                <method_specifier> ::= 
                    assembly_name.class_name.method_name

                в SQL Server есть только 2 операции над данными - INSERT и DELETE.
                поэтому старые или удаленные данные всегда в DELETED, а новые, или обновленные в INSERTED.
                Ответить
                • > а FOR INSERT тогда что?

                  FOR | AFTER
                  AFTER specifies that the DML trigger is fired only when all operations specified in the triggering SQL statement have executed successfully. All referential cascade actions and constraint checks also must succeed before this trigger fires.
                  AFTER is the default when FOR is the only keyword specified.

                  Пишешь FOR - получаешь AFTER.

                  > в SQL Server есть только 2 операции над данными - INSERT и DELETE.
                  > поэтому старые или удаленные данные всегда в DELETED, а новые, или обновленные в INSERTED.

                  Не вижу противоречий. Я в последнем своём предложении это и написал.
                  Ответить
              • неудобная хрень этот ваш ms sql

                before insert и instead of insert - как бы разные вещи
                Ответить
                • > неудобная хрень этот ваш ms sql
                  Норм, всё что надо - есть.

                  > before insert и instead of insert - как бы разные вещи
                  before insert НЕ НУЖЕН (c) MS
                  Ответить
                  • дьявол кроется в мелочах

                    абстрагируясь от идиотизма подмены дат в триггере, на оракле ОП был бы:
                    1) триггер before insert, которого нет в MS, потому что это глупо сначала инсертить, а потом то же самое апдейтить
                    2) for each row, которого нет в MS, чтобы не думать, сколько строк было затронуто
                    3) select col1, col2, col3 into var1, var2, var3 from foo ...; - этого тоже нет в MS?
                    Ответить
                    • 1. тут уж ничего не поделать, надеюсь скоро добавят триггер
                      2. в действительности очень мало ситуаций, когда нельзя что-то выполнить без for earch row или через курсоры. не вижу в этом смысла, базы данных создавались для работы с массивом данных.
                      3. select @value1 = val1 , @value2 = val2, @value3 = val3 from foo...
                      Ответить
                    • > абстрагируясь от идиотизма подмены дат в триггере, на оракле ОП был бы:
                      За бизнес логику в триггере (в любой СУБД) - расстрел на месте. Если тех. лид говорит "а по другому никак" - это первый звоночек, что архитектура, таки, гавно. И дальше будет только боль для мейнтейнеров солюшена.

                      > 1) триггер before insert, которого нет в MS, потому что это глупо сначала инсертить, а потом то же самое апдейтить
                      Ну пишите полностью свой INSERT в INSTEAD OF триггере с преферансом и поэтессами. И поддерживайте тогда уже всю вставку строки. Зато лишнего апдейта не будет.
                      > 2) for each row, которого нет в MS, чтобы не думать, сколько строк было затронуто
                      Тут у ОП проблема в том, что он ТАК написал код, что он работает с одной строкой только, а не у МС проблемы. Как я уже писал выше - не возбраняется обрабатывать виртуальные таблицы inserted и deleted во все щели, как и обычные статические таблицы.
                      > 3) select col1, col2, col3 into var1, var2, var3 from foo ...; - этого тоже нет в MS?
                      Как выше писали: select @var1 = col1 , @var2 = col2, @var3 = col3 from foo...

                      MS не виноват, что некоторым не дано (это возвращаюсь к ОПу) в T-SQL и реляционную модель.

                      Автор бы написал похожее говнецо и на PL/SQL и ему бы не помогли before insert триггер, for each row и другое написание массового присвоения.
                      Ответить
                      • >Как я уже писал выше - не возбраняется обрабатывать виртуальные таблицы inserted и deleted во все щели, как и обычные статические таблицы.

                        с каких это пор?
                        create table testtable (uniqueidentifier default(newsequentialid()))
                        go
                        create trigger trgtest on testtable
                        after insert
                        as
                        update inserted
                        set g = newid()

                        Msg 286, Level 16, State 1, Procedure trgtest, Line 4
                        Не удалось обновить логические таблицы INSERTED и DELETED.

                        таблицы read only.
                        Ответить
                        • Смотрим на что я ссылался своим "Как я уже писал выше"
                          И находим:
                          "Ну, inserted - можно сказать "виртуальная" таблица. Можно и курсор на ней станцевать и любые другие непристойности с SELECT'ом вытворять."
                          Тут ни слова про модификацию данных в этих таблицах.
                          Не вижу противоречий.
                          Ответить
                          • >Как я уже писал выше - не возбраняется обрабатывать виртуальные таблицы inserted и deleted во все щели, как и обычные статические таблицы.
                            а это тогда как понимать?
                            Ответить
                    • А МС, ещё те пидарасы, провоцируют новичков писать говнокод своими манами:
                      http://msdn.microsoft.com/en-us/library/ms190752(v=sql.105).aspx
                      Ответить
                      • after insert update
                        after update update
                        after update update
                        after update update
                        ...
                        Ответить
      • Как писали выше - свалится при массовом апдейтеинсерте.
        Ответить

    Добавить комментарий