Как оценить выражение в одном поле таблицы в другое? - PullRequest
1 голос
/ 11 июня 2019

У меня есть таблица, внутри есть поле с именем x, поле x содержит значения «1 + 2», «1 + 3» и т. Д., Как получить это значение, рассчитать его и сохранить в другом поле?

Ответы [ 3 ]

1 голос
/ 11 июня 2019

Для простых арифметических выражений - и в зависимости от вашей версии Oracle - вы можете использовать xmlquery для оценки.Обратите внимание, что / имеет особое значение в xml, оператором деления является ключевое слово div - поэтому вам нужно replace на случай, если в арифметическом выражении может быть косая черта.(Если у вас нет делений, вы можете упростить запрос, убрав вызов replace.)

Вот пример - включая тестовые данные вверху, в предложении with( не часть решения!)

with
  test_data (str) as (
    select '1 + 3'       from dual union all
    select '3 * 5 - 2'   from dual union all
    select '2/4*6'       from dual union all
    select '3 * (1 - 3)' from dual
  )
select str, xmlquery(replace(str, '/', ' div ') returning content).getNumberVal() 
            as evaluated_expression
from   test_data;


STR         EVALUATED_EXPRESSION
----------- --------------------
1 + 3                          4
3 * 5 - 2                     13
2/4*6                          3
3 * (1 - 3)                   -6
0 голосов
/ 11 июня 2019

Если необходимо рассмотреть упомянутый вами случай, я предлагаю вам использовать следующий запрос:

select
  xmlquery('3+4'
     returning content
  ).getNumberVal()
from
dual;

Если задействовано больше операторов, кроме деления, вышеупомянутый запрос будет работать, но если оператор делениятакже необходимо заменить ключевое слово "/" на "div".Что-то вроде следующего:

select
  xmlquery(
  replace( '20/5', '/', ' div ')
     returning content
  ).getNumberVal()
from
dual;

Теперь вы можете использовать его в своем заявлении об обновлении или в любом другом месте.

update tab 
set tab.result_column_name = xmlquery(t.your_expr_column_name
         returning content
      ).getNumberVal()

update tab 
set tab.result_column_name = xmlquery(
      replace( t.your_expr_column_name, '/', ' div ')
         returning content
      ).getNumberVal()

Демо

Ура !!

0 голосов
/ 11 июня 2019

Если в ваших формулах есть только действительные арифметические выражения PL / SQL, вы можете использовать EXECUTE IMMEDIATE для их оценки.

Для этого вам нужно создать функцию:

create or replace function eval_expression(p_expression in varchar2)
  return number is
  query  varchar2(100);
  result number;
begin
  query := 'select ' || p_expression || ' from dual';
  execute immediate query
    into result;
  return result;
end eval_expression;

Затем вы можете использовать эту функцию в UPDATE запросе:

update t 
--val is another field
set t.val = eval_expression(t.x)

Естественно, с EXECUTE IMMEDIATE этот запрос не будет чрезвычайно эффективным, но он будет работать. Кроме того, с динамическими запросами мы попадаем на небезопасную территорию, поэтому убедитесь, что в ваших формулах нет вредоносного кода.

Также см. « Оценка выражения » в Ask TOM. Том Кайт использовал немного более цивилизованный подход (пакет dbms_sql) и создал пакет с поддержкой одной переменной.

...