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

    −163

    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
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    67. 67
    68. 68
    CREATE PROCEDURE DEPTORS_EURO AS	-- Но сначала отключу ТРИГГЕРА 
       ALTER TABLE DEPTORS_REFERENCE DISABLE  TRIGGER Tr_for_DEPTORS_REFERENCE
       ALTER TABLE DEPTORS_DOC_EURO DISABLE  TRIGGER Tr_for_DEPTORS_DOC_EURO
       ALTER TABLE DEPTORS_Remander DISABLE  TRIGGER Tr_for_DEPTORS_REMANDER
       ALTER TABLE DEPTORS_Payment DISABLE  TRIGGER Tr_for_DEPTORS_Payment -- Создаю документ DEPTORS_DOC_EURO_old
                         Она будет нужна для поиска оплативших долги АК и появившихся новых */
     IF EXISTS(SELECT name  -- Удаляю, если существует в БД
    	  FROM 	 sysobjects WHERE  name = N'DEPTORS_DOC_EURO_old' AND 	 type = 'U') DROP TABLE DEPTORS_DOC_EURO_old
                SELECT * INTO DEPTORS_DOC_EURO_old -- Это DEPTORS за предыдущий месяц
                FROM DEPTORS_DOC_EURO     -- После копирования данных - уничтожим DEPTORS_DOC_EURO
    DELETE  DEPTORS_DOC_EURO -- Т.О. по FK-PK обнуляютя таблицы  
    DELETE FROM STATEMENT_UKRSTA WHERE mvt_date = 
    (SELECT DISTINCT LATEST__DATE -- выбираю дату 
    FROM STATEMENT_UKRSTA , CALENDAR_BILL_DATE WHERE
     DATEPART(mm,FLIGHT_PERIOD) = DATEPART(mm, (SELECT DATEADD(mm,-1, MAX(stac_date)) FROM STATEMENT_UKRSTA WHERE type = 'FB'))  and
     DATEPART(yy,FLIGHT_PERIOD) = DATEPART(yy, (SELECT DATEADD(mm,-1, MAX(stac_date)) FROM STATEMENT_UKRSTA WHERE type = 'FB'))  and
     type = 'FB') -- Удаляю из таблицы STATEMENT_UKRSTA  все АК, которые не имеют долгов
    DELETE FROM STATEMENT_UKRSTA WHERE corr IN (SELECT corr FROM STATEMENT_UKRSTA a GROUP BY a.corr HAVING Sum(a.saldo) <= 0 ) 
    -- Создаю псевдовременную таблицу по выборке DEPTORS_REFERENCE_Vrem
    IF EXISTS(SELECT name  -- Удаляю, если существует в БД
    	  FROM 	 sysobjects WHERE  name = N'DEPTORS_REFERENCE_Vrem' AND type = 'U') DROP TABLE DEPTORS_REFERENCE_Vrem  
    SELECT  corr, type, SUBSTRING(reference,1,6) AS Account, Sum(saldo) AS Saldo INTO DEPTORS_REFERENCE_Vrem FROM STATEMENT_UKRSTA GROUP BY corr, type, reference HAVING SUM(saldo) > 0  
    -- Т.К. FK-PK то сначала внесем User_Ref всех должников в DEPTORS_DOC_EURO
    IF EXISTS(SELECT name  -- Удаляю, если существует в БД
    	  FROM 	 sysobjects WHERE  name = N'USER_REF' AND 	 type = 'U')
        DROP TABLE USER_REF  
    SELECT DISTINCT corr INTO USER_REF FROM DEPTORS_REFERENCE_Vrem 
    INSERT INTO DEPTORS_DOC_EURO SELECT User_Ref=a.corr,DEBT_AMOUNT=Null,Name= Null,Country=Null,Code_ICAO=Null,Final_Date=Null,Period_of_Dept=Null,Saldo_D_Facte=0,Saldo_D_Ure=0 FROM USER_REF a  
    DROP TABLE USER_REF -- Заполняю таблицу DEPTORS_REFERENCE (User_Ref уже есть - поэтому позволит внести)
    INSERT INTO DEPTORS_REFERENCE SELECT User_Ref=a.corr,reference=a.Account,type=a.type,Old_Saldo=a.Saldo,Saldo_D_Facte =0,Saldo_D_Ure=0 -- первично  
     FROM DEPTORS_REFERENCE_Vrem a   -- Удалим псевдовременную таблицу DEPTORS_REFERENCE_Vrem
    DROP TABLE  DEPTORS_REFERENCE_Vrem -- Корректирую счета (Выставлено - Оплачено)
    IF EXISTS(SELECT name  -- Удаляю, если существует в БД
    	  FROM 	 sysobjects WHERE  name = N'Vrem_Stat_Negativ_Saldo' AND 	 type = 'U') DROP TABLE Vrem_Stat_Negativ_Saldo  
    SELECT  corr, type, SUBSTRING(reference,1,6) AS Account, Sum(saldo) AS Saldo INTO Vrem_Stat_Negativ_Saldo FROM STATEMENT_UKRSTA GROUP BY corr, type, reference HAVING SUM(saldo) < 0  -- Сравниваю две таблицы (DEPTORS_REFERENCE и Vrem_Stat_Negativ_Saldo)
    UPDATE a SET Old_Saldo = a.Old_Saldo + b.Saldo FROM DEPTORS_REFERENCE a INNER JOIN Vrem_Stat_Negativ_Saldo b ON a.User_Ref = b.corr and a.reference = b.Account
    DROP TABLE Vrem_Stat_Negativ_Saldo      -- Создаю новый документ DEPTORS_DOC_EURO 
    IF EXISTS(SELECT name  -- Удаляю, если существует в БД
    	  FROM 	 sysobjects WHERE  name = N'Vrem_DEPTORS_DOC_EURO' AND 	 type = 'U')    DROP TABLE Vrem_DEPTORS_DOC_EURO
       SELECT User_Ref, SUM(Old_Saldo) AS Old_Saldo,SUM(Saldo_D_Facte) AS Saldo_D_Facte,SUM(Saldo_D_Ure)   AS Saldo_D_Ure
     INTO Vrem_DEPTORS_DOC_EURO FROM DEPTORS_REFERENCE GROUP BY User_Ref 
    UPDATE b
    SET 
      DEBT_AMOUNT  = a.Old_Saldo, Saldo_D_Facte = a.Old_Saldo, Saldo_D_Ure   = a.Old_Saldo  FROM Vrem_DEPTORS_DOC_EURO a INNER JOIN DEPTORS_DOC_EURO b ON a.User_Ref = b.User_Ref
      DROP TABLE  Vrem_DEPTORS_DOC_EURO
    UPDATE a SET Name= b.corr_name  FROM DEPTORS_DOC_EURO a INNER JOIN STATEMENT_UKRSTA b 
               ON a.User_Ref = b.corr              
    UPDATE a SET Code_ICAO = ICAO_CODE FROM DEPTORS_DOC_EURO a INNER JOIN AIRCOMPANYS b
         ON (a.User_Ref = b.CRCO_NUMBER) OR (a.User_Ref = b.CRCO3)
    UPDATE a SET Country = c.FULL_NAME FROM DEPTORS_DOC_EURO a INNER JOIN AIRCOMPANYS b 
         ON (a.User_Ref = b.CRCO_NUMBER) OR (a.User_Ref = b.CRCO3)
                            INNER JOIN COUNTRYS c ON b.COUNTRY_ID = c.ID
     IF EXISTS(SELECT name  -- Удаляю, если существует в БД
    	  FROM 	 sysobjects WHERE  name = N'DEPTORS_DOC_EURO_NewDolg' AND 	 type = 'U')
        DROP TABLE DEPTORS_DOC_EURO_NewDolg
                   SELECT * -- Делаю выборку в таблицу   
                   INTO DEPTORS_DOC_EURO_NewDolg FROM DEPTORS_DOC_EURO
    WHERE User_Ref Not IN (SELECT User_Ref FROM DEPTORS_DOC_EURO_old)
    IF EXISTS(SELECT name  -- Удаляю, если существует в БД
    	  FROM 	 sysobjects WHERE  name = N'DEPTORS_DOC_EURO_OplatDolg' AND 	 type = 'U')
        DROP TABLE DEPTORS_DOC_EURO_OplatDolg
                   SELECT * -- Делаю выборку в таблицу   
                   INTO DEPTORS_DOC_EURO_OplatDolg FROM DEPTORS_DOC_EURO_old
    WHERE User_Ref Not IN (SELECT User_Ref FROM DEPTORS_DOC_EURO)
       ALTER TABLE DEPTORS_REFERENCE ENABLE  TRIGGER Tr_for_DEPTORS_REFERENCE
       ALTER TABLE DEPTORS_DOC_EURO ENABLE  TRIGGER Tr_for_DEPTORS_DOC_EURO
       ALTER TABLE DEPTORS_Remander ENABLE  TRIGGER Tr_for_DEPTORS_REMANDER
       ALTER TABLE DEPTORS_Payment ENABLE  TRIGGER Tr_for_DEPTORS_Payment

    курсор головного мозга 2.2

    Запостил: bahamot, 24 Февраля 2014

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

    • показать все, что скрытоТак, я первый комментатор.
      Все, кто после меня - педерасты и хуегасы.
      Ответить
    • какой пиздец, нет слов

      btw, странная мешанина из drop table (прямой ddl в процедуре-то?) и синтаксис select ... into just_deleted_table (так можно?)

      что-то не так в вашем датском королевстве
      это MS SQL?
      Ответить
      • Блин, ты это еще и прочитал?

        У меня горизонтальный скролл отбил все желание ;(
        Ответить
      • Почему курсор?
        Ответить
        • патамучта поциент ползёт на поправку (?)
          Ответить
        • Кстати, поддержу гуэста, курсора-то в данном ГК нет...
          Описалово надо подправить.
          Ответить
          • поциент истчо ни завершыл личебные працедуры
            каквирнёцо, нараз и падправим
            Ответить
      • > это MS SQL?
        Полагаю, вопрос риторический. :)
        Ответить
        • Странно, но футболка совсем не пахнет квадратных скобок нигде нет.
          Ответить
          • С тем нейминг конвеншином, что у них в БД, можно ничего не экранировать.
            Ответить
        • Ответить
      • > btw, странная мешанина из drop table (прямой ddl в процедуре-то?) и синтаксис select ... into just_deleted_table (так можно?)
        Да, таблица создастся со структурой селекта (только типы данных, никаких констрейнтов, индексов и т.п.). Вообще, это - грязный хак. Использовать в крайнем случае.

        > что-то не так в вашем датском королевстве
        Проекту, скорее всего, овер 10 лет, начиналось всё на МС СКЛ 2000, гениальный рахитектор того времени решил запихнуть всю бизнес логику в СУБД (ибо перформанс) и никто не хочет это говно переписывать.

        > это MS SQL?
        Такую простыню можно и на PL/SQL состряпать.
        Ответить
        • на pl/sql ты слегка заебешься делать DDL через execute immediate, что уже будет намекать на то, что уже что-то пошло не так
          именно об этом я и спросил, что в MSSQL у вас что-то не то

          select ... into unknown_name - это полный пиздец
          вместо ошибки, что такой переменной нет, он берёт и создает таблицу с этим именем?
          что за ад

          в оракле есть конструкция
          create table foobar as select ... - всё понятно, конфликтов с переменными нет
          Ответить
          • >на pl/sql ты слегка заебешься делать DDL через execute immediate, что уже будет намекать на то, что уже что-то пошло не так
            >именно об этом я и спросил, что в MSSQL у вас что-то не то
            Ну я же сказал, что SELECT ... INTO - это грязный хак, и его использование - это какбэ сигнал, что что-то пошло не так.

            > select ... into unknown_name - это полный пиздец
            ммм... почему?
            Такая конструкция работает ТОЛЬКО на создание новой таблицы и всё.

            > вместо ошибки, что такой переменной нет, он берёт и создает таблицу с этим именем?
            С переменными так нельзя. Если хочешь присвоить какое-то поле в переменную, то делаешь SELECT @myVariable = someField FROM ... .

            > что за ад
            Ну тут главное помнить, что переменные должны начинаться с пёсика и всё будет ок.
            В говнокоде ад в бизнес логике, завёрнутую в простыню.
            Ответить
            • ок, одинаковые ключевые слова для разной семантики в разных СУБД вносят сумятицу

              просто для справки, в MSSQL можно сделать вот так? (сорри, sqlfiddle сегодня не работает...)
              declare
                foo footable%rowtype; -- foo имеет тип record с полями, идентичными строке таблицы rowtype
              
                type bartype is record (
                  id number(10),
                  name varchar2(255 char),
                  born date
                );  -- запись
                bar bartype;
              begin
                select * into foo from footable where rownum = 1; -- селектим всю строку
                select id, name, born into bar from footable where rownum = 1; -- селектим отдельные поля
              end;
              Ответить
              • > foo footable%rowtype;
                Вот так нельзя. Т.е. возьми поля того типа, что вооон в той таблице. Удобно, конечно. Но, как-то без этого можно жить.

                > тип record с полями
                Такого понятия нет. У тебя либо скалярная переменная либо табличного типа.

                > select * into foo from footable where rownum = 1;
                Просто пишем такой запрос и получаем таблицу foo со структурой как footable с данными по условию.
                Скоуп видимости можно задавать решёточками перед именем таблицы:
                foo - статическая таблица;
                #foo - временная таблица (хранится в темпдб, удалится по окончанию сессии ) с локальной видимостью;
                ##foo - временная таблица с глобальной видимостью, доступна из других сессий.

                > select id, name, born into bar from footable where rownum = 1;
                Вместо этого объявляем отдельно переменных столько, сколько полей.
                DECLARE @id number(10), @name varchar(255), @born datetime;
                Записываем значения в переменные.
                select @id = id, @name = name, @born = born from footable where rownum = 1;

                Как-то так. Может оно и выглядит как через одно место, но функции свои выполняет и дискомфорта не испытываешь.
                Ответить
                • эм, если нет record, то как объявить кортеж?
                  ну, в частности, какой результат имеет fetch из курсора?
                  Ответить
                  • По скаляркам распихиваешь поля запроса.
                    http://technet.microsoft.com/en-us/library/ms180169(v=sql.105).aspx
                    Последний пример с вложенными курсорами.
                    ...
                    FETCH NEXT FROM vendor_cursor
                    INTO @vendor_id, @vendor_name;
                    ...
                    FETCH NEXT FROM product_cursor INTO @product;
                    ...
                    Специально усложняем использование курсора, чтоб не повадно было юзать :)
                    Ответить
                    • > не повадно
                      но... ведь... курсор...

                      кстати, в мсдновском примере можно было бы вообще без курсоров обойтись :-P
                      Ответить
                      • скажем нет курсорам!
                        http://www.sqlfiddle.com/#!4/40a7ae/2
                        * смотреть Plaintext output
                        Ответить
                      • > кстати, в мсдновском примере можно было бы вообще без курсоров обойтись :-P

                        Угу, курсор - это вообще крайняя мера.
                        В основном, я к нему прибегал только когда надо что-то по метаданным сконструировать хитрое с динамическим SQL.
                        Ответить
    • -- Но сначала отключу ТРИГГЕРА

      Вот кому нельзя работать на атомных электростанциях...
      Ответить

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