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

    −174

    1. 1
    2. 2
    3. 3
    4. 4
    create table #tt( value int )
    declare @v int = 1
    select @v = value from #tt
    select @v

    вот это поворот.. почему 1? null же должен быть по здравой логике!
    написал сейчас цикл

    declare @FileId int
    Select @fileid = fileid from #tmp
    while @FileId is not null
    begin
    exec dsd.process_File_RollBack @FileId
    delete from #tmp where fileid = @fileid
    Select @fileid = fileid from #tmp
    end

    а он оказывается минут 20 удаляет один и тот же файл :(

    Запостил: Lokich, 09 Апреля 2014

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

    • С курсорами не сложилось по жизни?
      Ответить
      • чем этот цикл хуже курсора?
        Ответить
        • Ты забыл обNULLять переменную перед получением следующего @fileid.
          Ответить
    • > почему 1?
      Скорее всего просто не меняет значение, и остается единичка от предыдущей итерации.
      Ответить
    • Присваивание переменной @v происходит для каждой выбранной строки, т.е. 0 раз.
      Ответить
      • клёвая логика в СУБД ынтерпрайз-класса
        а если бы было 3 строки, то какое бы значение сохранилось в переменной?
        Ответить
        • последнее
          create table #tt( value int )
          insert into #tt (value) values (2)
          insert into #tt (value) values (3)
          insert into #tt (value) values (4)
          declare @v int 
          set @v= 1
          select @v = value from #tt
          select @v

          возвращает 4, если конечно сортировок не задавать
          Ответить
          • > если конечно сортировок не задавать
            Если сортировок не задавать - оно возвращает не 4, а некое значение. Которое зависит от того, с какой ноги встал разраб СУБД, фазы луны и популяции шушпанчиков в созвездии альфа-центавра. Юзать такую конструкцию без сортировок или лимита на 1 строку - ССЗБ.
            Ответить
    • > null же должен быть по здравой логике!
      пф
      exception no_data_found должно быть по здравой логике!
      Ответить
      • и наверное при агрегации по null тоже такой exception бросать надо?
        Ответить
        • Зачем?
          Ответить
          • вот и я не понимаю зачем exception при том, когда значение не присвоилось переменной
            Ответить
            • > зачем exception при том, когда значение не присвоилось переменной
              Затем, что тебе нужна ровно одна строка. И если запрос не вернул ни одной строки, или вернул 2, 42 или 100500 строк - это ошибка. А на ошибку вполне логично кидать исключение.
              Ответить
            • потому что оно ей не присвоилось
              как ты различишь select null into v1 from dual; от select real_value into v1 from foobar where real_condition_failed;

              по побочной переменой rowcount (подозреваю, что в ms-sql такая тоже должна быть)?
              зачем, когда есть верный механизм исключений

              аналогично и про too_many_rows - ты не имеешь право задать последнее или любое другое значение в переменную, если у тебя в результате более одной строки - они все равноправны, и попытка их занести в одну переменную свидетельствует об исключительной ситуации
              Ответить
              • ладно, уговорили, я говнокодер
                Ответить
                • Не благодарите.
                  Ответить
                • не ты такой
                  это мелкософт тебя принудил
                  именно с этого я и начал - что это задача СУБД кинуть исключение, а не позволять творить всякую непотребщину
                  Ответить
                  • это особенности СУБД, а не зеленый свет на всякую непотребщену
                    Ответить
                    • > Select @fileid = fileid from #tmp
                      Вот это вот самая настоящая непотребщина ;) Мало того, что возвращает хрен-бы-знал-что. Так еще поди и пробегается по всему результсету перед этим...
                      Ответить
              • > real_condition_failed
                Дайте угадаю, под фейлом подразумевается возвращаемый пустой набор данных?
                Ответить
                • ну да, типа where 1=0.
                  и кстати да, тупо получится. скажем юзер фильтрует что-то в интерфейсе, указал предикаты, по которым нет данных, и словил эксепшн :)
                  Ответить
                  • > указал предикаты, по которым нет данных, и словил эксепшн
                    Да нет же, ты не понял мысль :) Зачем на любой пустой набор кидать экцепшн? Если юзеру показывают грид или оббегают результсет курсором - исключение не нужно, т.к. прога готова принять и 0 и 100500 строк. Если там аггрегация - тоже не нужно исключение, т.к. все аггрегирующие функции нормально работают с пустыми множествами.

                    Если же в коде явно написано, что нужно выбрать ровно одну строку и распихать ее поля по переменным - то исключение при количестве строк != 1 спасет от головной боли в будущем :)
                    Ответить
                    • я честно говоря не вижу в этом проблемы :) в моем случае проверку надо было делать на while exists ( select 1 from #tt), а не while @FileId is not null
                      Ответить
                      • > надо было делать на while exists ( select 1 from #tt)
                        Фе, еще один лишний запрос... Тогда уж просто обNULLи переменную перед select'ом, как советует выше bliznezz. Ну и в самом селекте не помешал бы limit 1, ибо нафиг нам оббегать все записи, если мы возьмем только одну...

                        P.S. Вот если честно, я никак не пойму, зачем удалять файлы именно sql серваком. Может проще сделать это с прикладной стороны? ;)
                        Ответить
    • что, комментарии тереть нельзя?
      Ответить
      • Боюсь, джинн всё равно не вылезет.
        Ответить
    • create table #tt( value int )
      declare @v int 
      set @v= 1
      SET @v = (select value from #tt)
      select @v

      NULL
      create table #tt( value int )
      insert into #tt (value) values (2)
      insert into #tt (value) values (3)
      insert into #tt (value) values (4)
      declare @v int 
      set @v= 1
      SET @v = (select value from #tt)
      select @v

      Msg 512, Level 16, State 1, Line 7
      Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

      Хватит использовать микроскоп вместо молотка!
      Ответить
      • неистово плюсую такое поведение.
        а то понапридумывали циклов по множеству с ручным недоуправлением.
        Ответить

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