powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Преобразование текстового выражения в число
16 сообщений из 16, страница 1 из 1
Преобразование текстового выражения в число
    #39309598
bssat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Господа, приветствую всех!
Уже весь мозг изломал. Имеется поле в бд, в котором есть строки типа
Код: sql
1.
3.9*3.79-2.56*2.52-0.23*0.25


Если я выполняю выражение
Код: sql
1.
SELECT CAST((3.9*3.79-2.56*2.52-0.23*0.25) AS decimal(10, 2)) AS plosh


То все нормально и я получаю знпчение выражения, т.е. 8,27
Но как мне выполнить запрос для поля?
Выражение
Код: sql
1.
 SELECT CAST(explicatitems.fname AS DECIMAL(10, 2)) AS plosh


в результате получаю только первое число, т.е. 3,9
Помогите пожалуйста...
...
Рейтинг: 0 / 0
Преобразование текстового выражения в число
    #39309642
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Напрямую - никак.
Можно в обход - написать свою функцию, которая будет собирать из этого выражения SQL-запрос и выполнять через prepared statement.
...
Рейтинг: 0 / 0
Преобразование текстового выражения в число
    #39309718
bssat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
miksoftНапрямую - никак.
Можно в обход - написать свою функцию, которая будет собирать из этого выражения SQL-запрос и выполнять через prepared statement.
Это будет сильно тормозить систему. Это некое подобие вычисляемых полей в Delphi.
...
Рейтинг: 0 / 0
Преобразование текстового выражения в число
    #39309746
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bssatЭто будет сильно тормозить систему.Смотря как и для чего применять.
bssatЭто некое подобие вычисляемых полейА почему бы не использовать настоящие вычисляемые поля в MySQL?
...
Рейтинг: 0 / 0
Преобразование текстового выражения в число
    #39309767
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bssatИмеется поле в бд, в котором есть строки типа
Код: sql
1.
3.9*3.79-2.56*2.52-0.23*0.25

Кто мешает добавить в таблицу поле с результатом вычисления выражения? Его можно вычислять в момент вставки/изменения записи (причём считая как на стороне сервера, так и на стороне клиента), а можно и по шедулеру (ну а если он не успел, тогда в процедуре будет не прямой SELECT, а препарированный - или вычисление, занесение результата в таблицу, а потом прямой SELECT). А заодно и нужную точность результата обеспечишь.
...
Рейтинг: 0 / 0
Преобразование текстового выражения в число
    #39309863
bssat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
AkinabssatИмеется поле в бд, в котором есть строки типа
Код: sql
1.
3.9*3.79-2.56*2.52-0.23*0.25

Кто мешает добавить в таблицу поле с результатом вычисления выражения? Его можно вычислять в момент вставки/изменения записи (причём считая как на стороне сервера, так и на стороне клиента), а можно и по шедулеру (ну а если он не успел, тогда в процедуре будет не прямой SELECT, а препарированный - или вычисление, занесение результата в таблицу, а потом прямой SELECT). А заодно и нужную точность результата обеспечишь.

Да. Но таблица уже существует, причем весьма не маленькая для ручного добавления итоговых данных. Процедур никаких нет, скорее всего все считалось на клиенте. Тормоза дикие. Придется писать изменялку, а уж потом мудрить. В любом случае - спсибо всем, принимавшим участие и тем, кто еще, возможно, примет.
...
Рейтинг: 0 / 0
Преобразование текстового выражения в число
    #39309866
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bssatтаблица уже существует, причем весьма не маленькая для ручного добавления итоговых данных.А ручного-то занафига? добавить поле и один раз пройтись по таблице, пересчитать все выражения:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
procedure recalc()
declare cursor cur for select id, formula from table;
open cur;
do
  fetch cur into @id, @formula;
  prepare stmt from concat('select (',@formula,') into @result from dual;');
  execute stmt;
  deallocate stmt;
  update table set result=@result where id=@id;
loop;
close cur;
end proc;


А потом навесить на таблицу триггер, который будет (пере)считывать это дело при insert/update
...
Рейтинг: 0 / 0
Преобразование текстового выражения в число
    #39310250
bssat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Akina,
Интересно, но на конкатенации вылетает ошибка
...
Рейтинг: 0 / 0
Преобразование текстового выражения в число
    #39310272
bssat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Akina,
Код: sql
1.
2.
3.
fetch cur into _id, _formula;
  SET @formula=_formula;
  SET @s = concat('select (',@formula,') into @result from explicatitems where num=',_id,';');


Решил проблему вот так, спасибо большое!
...
Рейтинг: 0 / 0
Преобразование текстового выражения в число
    #39312718
bssat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
bssat,
Кидаю полностью, может надо кому.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
PROCEDURE explication.functoreal()
BEGIN
  DECLARE _id integer;
  DECLARE _formula char(100);
  DECLARE done integer DEFAULT 0;
  DECLARE CUR CURSOR FOR
  SELECT
    num,
    fname
  FROM explication.explicatitems;
  DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
  OPEN cur;
  WHILE done = 0 DO
    FETCH cur INTO _id, _formula;
    SET @result = 0;
    IF _formula <> '' THEN
      SET @formula = _formula;
      SET @s = CONCAT('select (', @formula, ') into @result from explicatitems where num=', _id, ';');
      PREPARE stmt FROM @s;
      EXECUTE stmt;
      DEALLOCATE PREPARE stmt;
      UPDATE explication.explicatitems
      SET plosh = @result
      WHERE num = _id;
    END IF;
  END WHILE;
  CLOSE cur;
END
...
Рейтинг: 0 / 0
Преобразование текстового выражения в число
    #39312720
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bssat,

А почему бы прямо в PREPARE не делать UPDATE, без промежуточного SELECT-а?
Да и ошибки надо бы обрабатывать на случай, если выражение некорректное окажется.
...
Рейтинг: 0 / 0
Преобразование текстового выражения в число
    #39313086
bssat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
miksoftbssat,

А почему бы прямо в PREPARE не делать UPDATE, без промежуточного SELECT-а?
Да и ошибки надо бы обрабатывать на случай, если выражение некорректное окажется.

Там не может быть ошибок. У меня обработка на этапе ввода выражения производится. Нельзя ввести, скажем 2 скобки закрывающие и открывающие, например. Да и вообще, там куча правил описана. А насчет UPDATE, надо подумать. Просто времени не было.
...
Рейтинг: 0 / 0
Преобразование текстового выражения в число
    #39313197
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bssatТам не может быть ошибок. У меня обработка на этапе ввода выражения производится.Такая убеждённость - это хорошо... но если она не базируется на проверке выражения попыткой его выполнения (или полной формализации - скажем, в польскую нотацию,- с контролем всех лексем), то скорее всего какая-нибудь лазейка найдётся.
...
Рейтинг: 0 / 0
Преобразование текстового выражения в число
    #39313203
bssat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
AkinabssatТам не может быть ошибок. У меня обработка на этапе ввода выражения производится.Такая убеждённость - это хорошо... но если она не базируется на проверке выражения попыткой его выполнения (или полной формализации - скажем, в польскую нотацию,- с контролем всех лексем), то скорее всего какая-нибудь лазейка найдётся.
Это не исключено. Но задача совсем не военного масштаба, да и люди, которые работают с программой совсем не заинтересованы в неверном вводе формул. Им же потом геморрой будет. А потом, все взято в try ... except.
...
Рейтинг: 0 / 0
Преобразование текстового выражения в число
    #39313238
bssat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Нашел то, что искал долгое время...
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
(* Получение приоритета *)
function GetPriority( c: char ): byte;
begin
   Result := 0;
   case c of
      '(': Result := 1;
      '+', '-': Result := 2;
      '*', '/': Result := 3;
      '^', '!': Result := 4;
      'c', 's', 'l', 'e': Result := 5;
      'n': Result := 6;
   end;
end;
 
(* Переводим строку с формулой в обратную польскую запись *)
procedure ParseString( s: AnsiString; var _Stack: TStringList );
var
  Ms: TMemoryStream;
  Temp: TStringList; // Временный стек для знаков и геометрических функций
  flag: boolean;
begin
   Temp := TStringList.Create;
   Ms := TMemoryStream.Create;
   Ms.WriteBuffer( s[1], Length( s ) );
   Ms.Position := 0;
   with TParser.Create( Ms ) do
   begin
      while Token <> toEof do
      begin
         // Если это число, помещаем его в выходной стек
         if ( TokenString[1] in ['0'..'9'] ) then
            if flag then
            begin
               _Stack[_Stack.Count-1] := _Stack[_Stack.Count-1] + TokenString;
               flag := false;
            end
            else
               _Stack.Add( TokenString );
         // Если это разделитель дробной части
         if ( TokenString[1] in [DecimalSeparator] ) then
         begin
            _Stack[_Stack.Count-1] := _Stack[_Stack.Count-1] + TokenString;
            flag := true;
         end;
         // Если это знак (или геометрическая функция), то...
         if ( TokenString[1] in ['+','-','/','*','^','!','c','s','l','n','e'] ) then
         begin
            // ...если стек пустой, помещаем знак в стек ...
            if Temp.Count = 0 then
               Temp.Add( TokenString )
            else
            begin
               // ... если приоритет текущей операции выше, чем приоритет
               // последней операции в стеке, помещаем знак в стек ...
               if GetPriority( TokenString[1] ) > GetPriority( Temp.Strings[Temp.Count-1][1] ) then
                  Temp.Add( TokenString )
               else
               begin
                  // ... иначе извлекаем из стека все операции, пока
                  // не встретим операцию с более высшим приоритетом
                  while true do
                  begin
                     _Stack.Add( Temp.Strings[Temp.Count-1] );
                     Temp.Delete( Temp.Count-1 );
                     if Temp.Count = 0 then Break;
                     if GetPriority( TokenString[1] ) > GetPriority( Temp.Strings[Temp.Count-1][1] ) then
                        Break;
                  end;
                  // Не забываем добавить в стек текущую операцию
                  Temp.Add( TokenString );
               end;
            end;
         end;
         // Если это открывающая скобка, помещаем ее в стек операций
         if ( TokenString[1] in ['('] ) then
            Temp.Add( TokenString );
         // Если это закрывающая скобка, извлекаем из стека операций в
         // выходной стек все операции, пока не встретим открывающую скобку.
         // Сами скобки при этом уничтожаются.
         if ( TokenString[1] in [')'] ) then
         while true do
         begin
            if Temp.Count = 0 then Break;
            if Temp.Strings[Temp.Count-1] = '(' then
            begin
               Temp.Delete( Temp.Count-1 );
               Break;
            end;
            _Stack.Add( Temp.Strings[Temp.Count-1] );
            Temp.Delete( Temp.Count-1 );
         end;
         NextToken;
      end;
   end;
   Ms.Free;
   // Если по окончании разбора строки с формулой, в стеке операций
   // еще чтото осталось, извлекаем все в выходной стек
   if Temp.Count <> 0 then
      while Temp.Count <> 0 do
      begin
         _Stack.Add( Temp.Strings[Temp.Count-1] );
         Temp.Delete( Temp.Count-1 );
      end;
   Temp.Free;
end;
...
Рейтинг: 0 / 0
Преобразование текстового выражения в число
    #39313275
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bssatУ меня обработка на этапе ввода выражения производится.Помимо некорректного синтаксиса еще бывает переполнение и деление на ноль.
...
Рейтинг: 0 / 0
16 сообщений из 16, страница 1 из 1
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Преобразование текстового выражения в число
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]