На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! информация о разделе
user posted imageДанный раздел предназначается исключительно для обсуждения вопросов использования языка запросов SQL. Обсуждение общих вопросов, связанных с тематикой баз данных - обсуждаем в разделе "Базы данных: общие вопросы". Убедительная просьба - соблюдать "Правила форума" и не пренебрегать "Правильным оформлением своих тем". Прежде, чем создавать тему, имеет смысл заглянуть в раздел "Базы данных: FAQ", возможно там уже есть ответ.

Модераторы: Akina
  
> Помогите прочесть код , Что точно делает эта SQL функция?
    Добрый день!

    Возникла необходимость писать и понимать SQL. Вникаю потихоньку. Изучаю функции и скрипты в базе с которой надо работать.
    Пока не всё ясно.
    Есть такой вот код:
    ExpandedWrap disabled
      create or replace
      FUNCTION GET_LABEL
        (Clas IN SMF.clas%Type,
          inMask in Integer default 0
         )
      RETURN SMF.name%Type
      IS
       
      BEGIN
      for rec in ( select case inMask
                                when 1 then Decode ( Tabl.TIP, 1, Tabl.NUM, Tabl.NAME )
                                else Tabl.NAME
                                end NAME
                      from base.TABLE_1 Tabl
                      where ( Tabl.CLAS = Clas ) or
                            ( Tabl.FILIAL = Clas ) ) loop
          Return (rec.NAME) ;
      end loop;
      Return ( Null );
      END GET_LABEL;
    Пока не всё тут понятно.
    В принципе основные проблемы с пониманием:
    - кто такой rec?
    - зачем тут for-loop? Что он делает?
    - что такое end NAME?
    - почему два Return?

    Или просто описать алгоритм этой функции обычным русским языком. Там я уже разберусь до конца.
      Что за диалект? Оракл? Никогда с ним не сталкивался.

      В принципе, тут все ясно:

      - rec - это имя переменной, которая хранит текущую запись из итерируемого набора
      - for loop итерирует набор значений, в данном случае строки, возвращенные select-ом
      - end NAME в данном случае это конец блока case (end) и псевдоним для выбираемого значения (NAME)
      - второй возврат нужен потому, что первый не сработает, если в наборе нет записей

      Функция возвращает значение из одной записи из таблицы (если есть хоть одна подходящая), либо null (если такой записи нет). Для этого выбираются значения по критерию, затем цикл обрабатывает выборку (или там, в нутре, не готовая выборка, а курсор дергается?), но на первой же итерации цикл грубо обрывается и возвращается поле первой записи из выборки. Если же выборка пуста, то цикл вообще не выполняется, и срабатывает return (null).

      P. S. Может, рановато еще в рабочий код смотреть? Ораклами, вроде бы, пользуются серьезные фирмы для серьезного бизнеса. Можно серьезно накосячить.
        Если
        Цитата AVA12 @
        на первой же итерации цикл грубо обрывается

        то ето не очень хороший код. Запрос должен возврашать не более одной записи. В код надо добавить TOP 1 или LIMIT 0, 1 или ограничитель количества записей етого диалекта SQL.
          Ну и ORDER BY надо добавить потому, как ета функция недетерминирована. Она может возврашать разные результаты при множественных вызовах на одних и тех же данных.
            Цитата AVA12 @
            Что за диалект? Оракл? Никогда с ним не сталкивался.
            для работы используется Oracle SQL Developer, это всё, что могу сказать. Если есть способы проверить диалект, напишите, сделаю.
            Со знанием названия диалекта гуглить явно станет легче.

            Цитата AVA12 @
            - rec - это имя переменной, которая хранит текущую запись из итерируемого набора
            - for loop итерирует набор значений, в данном случае строки, возвращенные select-ом
            Я когда впервые увидел этот код, загуглил for-loop и мне "повезло": попал на сайт, на котором рассказывалось только о числовой форме for. Вооружившись этими знаниями я конечно наглухо "завис" на разборе этой функции.
            Прочитал ответы, погуглил ещё... А тут курсорная форма :blush:

            Цитата AVA12 @
            Ораклами, вроде бы, пользуются серьезные фирмы для серьезного бизнеса.
            Да, так и есть. Серьёзная фирма для серьёзного бизнеса. Но это обязывает: бардак тут тоже серьёзный :bad:
            И я не разработчик, а пользователь. Так что программисты отмахиваюся: иди нафиг, не мешай, а коллеги знают примерно с моё.
            Цитата AVA12 @
            Может, рановато еще в рабочий код смотреть? Можно серьезно накосячить.
            Нельзя: у меня доступ только на чтение :ph34r:

            Цитата MIF @
            то ето не очень хороший код. Запрос должен возврашать не более одной записи.
            :yes:
            Меня вот тоже такой подход как-то коробит с первого взгляда.
            Таблица из которой делается select - справочник, а параметр функции - идентификатор, который обязан быть уникальным в таблице. Иначе что это за идентификатор такой?
            Цитата MIF @
            В код надо добавить TOP 1 или LIMIT 0, 1 или ограничитель количества записей етого диалекта SQL.
            если правильно помню, здесь это rownum <=1

            Вот так можно переписать?
            ExpandedWrap disabled
              create or replace
              FUNCTION GET_LABEL
                (Clas IN SMF.clas%Type,
                  inMask in Integer default 0
                 )
              RETURN SMF.name%Type
              IS
               
              BEGIN
              ( select case inMask
                       when 1 then Decode ( Tabl.TIP, 1, Tabl.NUM, Tabl.NAME )
                       else Tabl.NAME
                       end NAME
                from base.TABLE_1 Tabl
                where (( Tabl.CLAS = Clas ) or ( Tabl.FILIAL = Clas )) and rownum <=1
              ) ResultTable
               
              Return (ResultTable.NAME) ;
               
              END GET_LABEL;


            Цитата MIF @
            и ORDER BY надо добавить
            Если ограничиваем количество записей одной, то всё равно нужна сортировка?
            Он что, сначала отбирает все записи, а потом выбрасывает лишние, чтобы осталось сколько просили? :blink:
              Цитата SV() @
              Если ограничиваем количество записей одной, то всё равно нужна сортировка?


              Да. SQL движки не гарантируют порядок записей в рекордсете если нет сортировки.
              Цитата SV() @
              Он что, сначала отбирает все записи, а потом выбрасывает лишние, чтобы осталось сколько просили?


              Нет. Движок проводит seek или scan таблицы или индекса и останавливается когда найдено нужное число записей.
                Я по ходу как-то неправильно понимаю параметр ORDER BY.
                я считал, что сначала выполняется собственно SELECT со всеми условиями. В итоге получается некая табличка-результат. И вот она то уже сортируется в соответствии с ORDER BY. Нет?
                  Цитата SV() @
                  я считал, что сначала выполняется собственно SELECT со всеми условиями. В итоге получается некая табличка-результат. И вот она то уже сортируется в соответствии с ORDER BY. Нет?


                  Индекс решает все.
                  Если поле в WHERE фильтре и в ORDER BY и есть TOP N и:
                  1. поле проиндексировано: запрос найдет первую запись в индексе с нужным значением, а потом просканирует индекс пока не найдет нужное количество записей либо пока значение индекса не выйдет за условие WHERE.
                  2. не проиндексировано: запрос просканирует всю таблицу, потом упорядочит найденные записи, пором выберет TOP N из результата.
                  0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                  0 пользователей:


                  Рейтинг@Mail.ru
                  [ Script execution time: 0,0366 ]   [ 16 queries used ]   [ Generated: 29.03.24, 13:56 GMT ]