PANTHEON™ Help

 Категории
 PANTHEON Help - Welcome
[Collapse]PANTHEON
 [Collapse]PANTHEON упатства
  [Expand]Guide for PANTHEON
  [Expand]Ръководство за PANTHEON Търговия
  [Expand]Ръководство за PANTHEON Vet
  [Expand]Ръководство за PANTHEON Фермерство
 [Collapse]PANTHEON потребителски ръководства
  [Collapse]Ръководство за потребителя за PANTHEON
   [Collapse]Започване
     Речник на термините
     Първи стъпки с PANTHEON
    [Expand]Използване на PANTHEON в Tecta, фикционална компания
    [Expand]Инструкции за осигуряване на съответствието на PANTHEON с SAS
    [Expand]Инсталация на ПАНТЕОН
    [Collapse]ПАНТЕОН Система
     [Expand]Данни на системата PANTHEON
     [Expand]MS SQL Server
     [Expand]Утилити на Microsoft Windows
     [Expand]Политика за сигурност
     [Collapse]Администриране на бази данни
       Конвертиране на публикации в различна валута
       ФормулаПарсер
       Поправяне на датата на документа в книгите
      [Expand]Настройка на производителността
    [Expand]Основи на ПАНТЕОН
    [Expand]ПАНТЕОН Помощ
    [Expand]Материали и движение на стоки
    [Expand]Присвояване на идентификатори
    [Expand]Често задавани въпроси за Пантеон (Ч.З.В.)
    [Expand]Архив
   [Expand]Ръководство за потребителя за електронен бизнес
   [Expand]Настройки
   [Expand]Поръчки
   [Expand]Стоки
   [Expand]Производство
   [Expand]Услуга
   [Expand]Помощ
   [Expand]Персонал
   [Expand]Финансови
   [Expand]Анализи
  [Expand]Ръководство за потребителя за PANTHEON Retail
  [Expand]Ръководство за потребителя за PANTHEON Vet
  [Expand]Ръководство за потребителя за PANTHEON Farming
[Collapse]PANTHEON Web
 [Collapse]PANTHEON Web Guides
  [Expand]Ръководство за PANTHEON Web Light
  [Expand]Ръководство за PANTHEON Уеб Терминал
  [Expand]Ръководство за PANTHEON Web Legal
  [Expand]Архив на стари продукти
 [Collapse]PANTHEON Web User Manuals
  [Expand]Започване на PANTHEON Web
  [Expand]User Manual for PANTHEON Web Light
   Ръководство за потребителя за PANTHEON Web Terminal
  [Expand]Ръководство за потребителя за PANTHEON Web Legal
  [Expand]Архив на стари продукти
[Collapse]PANTHEON Гранула
 [Collapse]Ръководство за PANTHEON Гранули
  [Expand]Гранула за служители
  [Expand]Пътни заповеди Гранула
  [Expand]Гранула за документи и задачи
  [Expand]Гранула Табло
  [Expand]Гранула за B2B поръчки
  [Expand]Гранула за обслужване на клиент
  [Expand]Инвентаризация на дълготрайни активи
  [Expand]Гранула за складови наличности
 [Collapse]PANTHEON Granules
   Започване
   Using PANTHEON Granules at Tecta, a fictional company
  [Expand]PANTHEON Granules and activation
  [Expand]PANTHEON Granule Work records
  [Expand]PANTHEON Granule Travel orders
  [Expand]PANTHEON Granule Documents and Tasks
  [Expand]PANTHEON Granule B2B orders
  [Expand]PANTHEON Granule Dashboard
  [Expand]Полеви сервизен гранул
   PANTHEON Granules - FAQ
  [Expand]Инвентаризация на дълготрайни активи
  [Expand]Инвентаризация на склада Гранула
   Архив
[Expand]Потребителски сайт

Load Time: 718,7749 ms
"
  2709 | 3106 | 443799 | AI translated
Label

ФормулаПарсер

ФормулаПарсер

ФормулаПарсер

Този пример не е толкова свързан с SQL-InterActive, а по-скоро с начина на програмиране на T-SQL. Тъй като знаем колко ценни са програмните примери, ние все пак го включихме в инструкциите.

Примерът добре илюстрира рекурсии, съхранени процедури. Главната процедура е предназначена за изчисляване на математически изрази, които въвеждаме под формата на низ от алфанумерични знаци.

Процедурите са направени така, че ако премахнем --!! пред print командите, виждаме хода на изпълнението и рекурсиите.

Помощна процедура, която връща аргументите

създайте процедура [dbo].[dl_PA_ParserGetArg]
  @sExpression varchar(8000),
  @lLeft bit,
  @iOperand int,
  @iLimit integer output,
  @mResult float output,
  @sEr varchar(8000) output

-- тестови параметри
-- декларирайте
--   @sExpression varchar(8000),
--   @lLeft bit,
--   @iOperand int,
--   @iLimit integer,
--   @mResult money,
--   @sEr varchar(8000)
-- 
-- задайте @sExpression='2*3'
-- задайте @lLeft=1
-- задайте @iOperand=2
-- exec dl_PA_GetArg @sExpression, @lLeft, @iOperand, @iLimit output,@mResult output, @sEr output
--  --!! print '-----'
--  --!! print @iLimit 
--  --!! print cast(@mResult as char)
--  --!! print @sEr

както

декларирайте
  @sTempArg varchar(8000)

set nocount on
set @sTempArg = ' '+@sExpression+' '  -- това е само за да се погрижи за лимитите в цикъла (да не получим j[0])
set @iOperand = @iOperand + 1
--!! print '    @sTempArg='+@sTempArg+'#'
--!! print '    @iOperand=' + Str(@iOperand) + '#' + SubString(@sTempArg,@iOperand,1) 
if @lLeft=1
  begin  -- ляв аргумент
   set @iLimit = @iOperand - 1
   --!! print '      ляв аргумент'
   --!! print '      @iLimit=' + Str(@iLimit) + '#' + SubString(@sTempArg,@iLimit,1) 
   while (@iLimit > 0) and not (SubString(@sTempArg,@iLimit,1) in ('+','-','/','*','\','|'))
     set @iLimit = @iLimit-1
   -- нека проверим за водещ "-" за левия аргумент.
   if @iLimit > 1 
     if SubString(@sTempArg,@iLimit,1) = '-'
        set @iLimit = @iLimit-1
   --!! print '      @iLimit=' + Str(@iLimit) + '#' + SubString(@sTempArg,@iLimit,1) 
   --!! print '      @iLimitg='+cast(@iLimit as varchar)
   set @sTempArg = SubString(@sTempArg,@iLimit+1,@iOperand-@iLimit-1)
   --!! print '      изход ляв @sTempArg='+@sTempArg
  end
else
  begin  -- десен аргумент
    set @iLimit = @iOperand + 1
    --!! print '      десен аргумент'
    --!! print '      @iLimit=' + Str(@iLimit) + '#' + SubString(@sTempArg,@iLimit,1) 
    set @iLimit = @iLimit+1
    --!! print '      Изчисляване...'
    while (@iLimit <= Len(@sTempArg)) and not (SubString(@sTempArg,@iLimit,1) in ('+','-','/','*','\','|'))
      set @iLimit = @iLimit+1
    --!! print '      @iLimit=' + Str(@iLimit) + '#' + SubString(@sTempArg,@iLimit,1) 
    set @sTempArg = SubString(@sTempArg,@iOperand+1,@iLimit-@iOperand-1)
    --!! print '    изход десен @sTempArg='+@sTempArg
  end
if @sTempArg = '' 
  begin
    if SubString(@sExpression,@iOperand,1) in ('+','-')  -- това е за обработка на -x / +x
      set @mResult = 0
    else
      set @sEr = 'Невалидна употреба на оператори в '+@sExpression
  end
else
  begin
    --!! print '    изход @sTempArg='+@sTempArg
    set @mResult = Convert(float,@sTempArg,2)
    --!! print '    изход @mResult='+Str(@mResult,35,15)
    -- !! проверка за грешка тук !! Обработка на изключения !!
    --    if code <> 0 then
    --      er = @sExpression+'не е число!'
    --    else
    --      begin
    set @iLimit = @iLimit - 1
    --      end
  end

Главна процедура, която изчислява израза

създайте процедура [dbo].[dl_PA_ParseAritNew]
  @sExpression varchar(8000),
  @rResult float output,
  @sEr varchar(8000) output -- @sEr = ''<- без грешка, @sEr <> '' <- грешка в израза

-- Внимание ! ---
-- Винаги извиквайте функцията като ParseArit(0,израз,'+',er) !!!!!
-- В израза не трябва да има интервали "2+3" = ОК / "2 + 3" <> ОК !!!!
-- В израза не трябва да има небалансирани скоби (виж тест 2)!
-- (c) А. Мертел, 1997, 2002

както

декларирайте
  @iBrackets int,       -- брояч на скобите ()
  @i int,               -- брояч 1
  @j int,               -- брояч 2
  @iLen int,            -- дължина на @sExpression 
  @iLeftLimit int,      -- лимит на левия аргумент
  @iRightLimit int,     -- лимит на десния аргумент
  @rLeft float,         -- стойност на левия аргумент
  @rRight float,        -- стойност на десния аргумент
  @lOperatorsExist bit, -- имаше ли оператор в израза
  @sOrigExpression varchar(8000),
  @sTemp varchar(8000)  -- временно променлива

set nocount on  

set @iLen = Len(@sExpression)
set @sOrigExpression = @sExpression
-- коригирайте "+x" в "x"
if SubString(@sExpression,1,1) = '+'
  set @sExpression = Right(@sExpression,@iLen-1)
-- коригирайте "--x" в "x"
set @sExpression = Replace(@sExpression,'--','')
--!! print 'в функция exp = ' +@sOrigExpression
if @sEr = '' 
  begin   -- без грешка при вход
    set @lOperatorsExist = 0
    -- обработка на скоби ()
    set  @i = Charindex('(',@sExpression)
    if @i > 0 -- @i > 0?
      begin -- има (,)
        --!! print '  -- има скоби'
        set @lOperatorsExist = 1
        set @iBrackets = 1
        set @j = @i + 1  
        while (@j <= @iLen) and (@iBrackets > 0) -- намерете първото съвпадение
          begin
            if SubString(@sExpression,@j,1) = ')'
              set @iBrackets = @iBrackets-1
            if SubString(@sExpression,@j,1) = '('
              set @iBrackets = @iBrackets+1
            set @j = @j + 1
          end
        set @sTemp = SubString(@sExpression,@i+1,@j-@i-2)
        -- изчислете външната двойка
        exec dl_PA_ParseAritNew @sTemp,@rResult output,@sEr output 
        --!! print '    ()@rResult='+Str(@rResult,25,10)
        set @sTemp = LTrim(Str(@rResult,35,15))
        --!! print '    ()@sTemp='+@sTemp
        set @sTemp = Replace(@sTemp,',','.')  -- сменете възможно ',' с '.'
        --!! print '    ()@sTemp, след замяна ='+@sTemp
        -- заменете външната двойка с резултата
        set @sExpression = SubString(@sExpression,1,@i-1)+@sTemp+SubString(@sExpression,@j,@iLen-@j+1)  
        --!! print '    ()@sExpression=' + @sExpression 
      end -- има (,)
    else  -- @i > 0? не, няма (,)
      begin -- проверка за *,/
        set @i = 1
        while not (SubString(@sExpression,@i,1) in ('*','/')) and (@i < @iLen) 
          set @i = @i + 1
        if SubString(@sExpression,@i,1) in ('*','/') 
          begin  -- *,/ намерени
            --!! print '  -- намерени *,/ на позиция ' + Str(@i)
            set @lOperatorsExist = 1
            exec dl_PA_ParserGetArg @sExpression,1,@i,@iLeftLimit output,@rLeft output,@sEr output
            exec dl_PA_ParserGetArg @sExpression,0,@i,@iRightLimit output,@rRight output,@sEr output
            --!! print '    */@rLeft='+Str(@rLeft,25,15)
            --!! print '    */@rRight='+Str(@rRight,25,15)
            --!! print '    */@sEr='+@sEr
            if @sEr = '' 
              begin
                if SubString(@sExpression,@i,1) = '*' 
                  set  @rResult = @rLeft*@rRight
                else
                  if SubString(@sExpression,@i,1) = '/'
                    exec dl_DivT @rLeft,@rRight,@rResult output
                set @sTemp = LTrim(Str(@rResult,35,15))
                --!! print '    */@rResult='+Str(@rResult,25,10)
                --!! print '    */@sTemp='+@sTemp
                set @sTemp = Replace(@sTemp,',','.')  -- сменете възможно ',' с '.'
                --!! print '    */@sTemp, след замяна ='+@sTemp
                --!! print '    */Десен дел=#'+ SubString(@sExpression,@iRightLimit,Len(@sExpression)-@iRightLimit+1) + '#'
                -- заменете *,/ с резултата
                if @iLeftLimit > 0
                   set @sExpression = SubString(@sExpression,1,@iLeftLimit) + @sTemp + SubString(@sExpression,@iRightLimit,Len(@sExpression)-@iRightLimit+1)
                else
                   set @sExpression = @sTemp + SubString(@sExpression,@iRightLimit,Len(@sExpression)-@iRightLimit+1)
		--!! print '    */@sExpression(Финал)=' + @sExpression 
              end
          end  -- *,/ намерени
        else
          begin -- проверка за div, mod
            set @i = 1
            while not (SubString(@sExpression,@i,1) in ('\','|')) and (@i < @iLen)
              set @i = @i + 1
            if SubString(@sExpression,@i,1) in ('\','|')
              begin  -- div, mod намерени
                --!! print '  -- намерени \,| (div,mod) на позиция ' + Str(@i)
                set @lOperatorsExist = 1
                exec dl_PA_ParserGetArg @sExpression,1,@i,@iLeftLimit output,@rLeft output,@sEr output
                exec dl_PA_ParserGetArg @sExpression,0,@i,@iRightLimit output,@rRight output,@sEr output
                --!! print '    \,|@rLeft='+Str(@rLeft,25,15)
                --!! print '    \,|@rRight='+Str(@rRight,25,15)
                --!! print '    \,|@sEr='+@sEr
                if @sEr = ''
                  begin
                    if SubString(@sExpression,@i,1) = '\'
                      begin
                        if @rRight <> 0
                          set @rResult = cast((@rLeft / @rRight + 0.0) as int)
                        else
                          set @rResult = 0
                      end
                    else
                      if SubString(@sExpression,@i,1) = '|'
                        begin
                          if @rRight <> 0
                            set @rResult = cast(@rLeft as int) % cast(@rRight as int)
                          else
                            set @rResult = 0
                        end
                    set @sTemp = LTrim(Str(@rResult,35,15))
                    set @sTemp = Replace(@sTemp,',','.')  -- сменете възможно ',' с '.'
                    -- заменете div, mod с резултата
                    if @iLeftLimit > 0
                      set @sExpression = SubString(@sExpression,1,@iLeftLimit) + @sTemp + SubString(@sExpression,@iRightLimit,Len(@sExpression)-@iRightLimit+1)
                    else
                      set @sExpression = @sTemp + SubString(@sExpression,@iRightLimit,Len(@sExpression)-@iRightLimit+1)
                  end
              end  -- div, mod намерени
            else
              begin -- проверка за събирания и изваждания
                set @i = 1
                if SubString(@sExpression,@i,1) = '-'
                  set @i = @i + 1
                while not (SubString(@sExpression,@i,1) in ('+','-'))  and (@i < @iLen)
                  set @i = @i + 1
                --!! print '    +,- @i='+cast(@i as varchar)
                if SubString(@sExpression,@i,1) in ('+','-')
                  begin  -- +,- намерени  
                    --!! print '  -- намерени +,- на позиция ' + Str(@i)
                    set @lOperatorsExist = 1
                    exec dl_PA_ParserGetArg @sExpression,1,@i,@iLeftLimit output,@rLeft output,@sEr output
                    exec dl_PA_ParserGetArg @sExpression,0,@i,@iRightLimit output,@rRight output,@sEr output
                    --!! print '    +,- @rLeft='+Str(@rLeft,25,15)
                    --!! print '    +,- @rRight='+Str(@rRight,25,15)
                    --!! print '    +,- @sEr='+@sEr
                    if SubString(@sExpression,@i,1) = '+'
                       set @rResult = @rLeft + @rRight
                    else
                      if SubString(@sExpression,@i,1) = '-'
                        set @rResult = @rLeft - @rRight
                    set @sTemp = LTrim(Str(@rResult,35,15))
                    --!! print '    +-@rResult='+Str(@rResult,25,10)
                    --!! print '    +-@sTemp='+@sTemp
                    set @sTemp = Replace(@sTemp,',','.')  -- сменете възможно ',' с '.'
                    --!! print '    +-@sTemp, след замяна ='+@sTemp
                    -- заменете +,- с резултата
                    if @iLeftLimit > 0
                      set @sExpression = SubString(@sExpression,1,@iLeftLimit) + @sTemp + SubString(@sExpression,@iRightLimit,Len(@sExpression)-@iRightLimit+1)
                    else
                      set @sExpression = @sTemp + SubString(@sExpression,@iRightLimit,Len(@sExpression)-@iRightLimit+1)
                    --!! print '    +-@sExpression=' + @sExpression 
                  end -- +,- намерени
              end  -- проверка за събирания и изваждания
          end  -- проверка за div, mod
        end  -- проверка за умножения, деления
    if @sEr = ''
      begin  -- без грешка досега
        if @lOperatorsExist = 1
          begin
            --!! print '  изход за рекурсия оригинал. @sExpression='+@sExpression+' @sExpression=' + @sExpression
            exec dl_PA_ParseAritNew @sExpression,@rResult output,@sEr output -- парсинг с стойност
          end
        else
          begin
            --!! print '  изход за оригинал. @sExpression='+@sExpression+' @sExpression=' + @sExpression
            set @rResult = Convert(float,@sExpression,2)
          end
      end -- без грешка досега
  end -- без грешка при вход

Тестови примери

-- тестов случай 1
 декларирайте
   @sExpression varchar(8000),
   @mResult money,
   @sEr varchar(8000)
 set @sExpression='2*3'
 set @sEr = ''
 --!! print @sExpression
 exec dl_PA_ParseAritNew @sExpression, @mResult output,@sEr output
 --!! print '-----'
 --!! print Str(@mResult,35,15)
 --!! print @sEr
--тестов случай 2
 създайте таблица _TEST_PARSER
 (
    ФОРМУЛА varchar(300),
    ТЕСТ money,
    ГРЕШКА varchar(500),
    РЕЗУЛТАТ money
 )
 декларирайте
    @sExpression varchar(8000),
    @mTest float,
    @mResult float,
    @i int,
    @iBrackets int,
    @sEr varchar(8000)
  set nocount on 
  декларирайте crKurzor курсор local fast_forward за 
    select ФОРМУЛА,ТЕСТ
      от _TEST_PARSER
  отворете crKurzor
  fetch next от crKurzor в @sExpression,@mTest
  while @@fetch_status = 0 
  while @@fetch_status = 0 
    begin
      -- проверка за баланс на скобите
      print '--------------------------------------------------------'
      print ' Тест: ' + @sExpression
      print ' Очакван резултат = ' + Str(@mTest)
      set @i = 1  
      set @iBrackets = 0
      while (@i <= Len(@sExpression))  -- проверка на целия израз
        begin
          if SubString(@sExpression,@i,1) = ')'
            set @iBrackets = @iBrackets-1
          if SubString(@sExpression,@i,1) = '('
            set @iBrackets = @iBrackets+1
          set @i = @i + 1
        end
      if @iBrackets <> 0
        set @sEr = 'Небалансирани скоби в ' + @sExpression
      else
        begin
          set @sEr = ''
          exec dl_PA_ParseAritNew @sExpression, @mResult output,@sEr output
        end
      print ' Изчислен резултат = ' + Str(@mResult)
      if (@mResult = @mTest)
        print ' ОК'
      else
        print ' Грешка (@mResult - @mTest) = ' + Str(@mResult - @mTest)
      print '--------------------------------------------------------'
      update _TEST_PARSER
        set РЕЗУЛТАТ = @mResult,
            ГРЕШКА = @sEr
        where LTrim(RTrim(ФОРМУЛА)) = LTrim(RTrim(@sExpression))
      fetch next от crKurzor в @sExpression,@mTest
    end
  close crKurzor
  deallocate crKurzor
  select LTrim(RTrim(ФОРМУЛА)) as 'Формула',ТЕСТ,РЕЗУЛТАТ,LTrim(RTrim(ГРЕШКА)) as 'ErrorMsg'
    от _TEST_PARSER
      where (ТЕСТ <> РЕЗУЛТАТ) or (ТЕСТ is null)


 

Оценете темата
Темата беше ли ви полезна?
Коментар
Вашият коментар ще бъде видим и във форума!