如何将一个 table 字段中的表达式计算为另一个字段?

How to evaluate an expression in one table field into another?

我有一个table,里面有一个叫做x的字段,x字段包含'1+2','1+3'等值,如何获取这些值并计算它以及保存到另一个字段?

如果您的公式中只有 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 上的“Evaluate Expression”。 Tom Kyte 使用了一种稍微文明一些的方法(dbms_sql 包)并创建了一个具有单一变量支持的包。

对于简单的算术表达式 - 并且取决于您的 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

如果您提到的情况需要考虑,那么我建议您使用以下查询:

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

如果涉及除 division 以外的更多运算符,则上述查询将有效,但如果还涉及 division 运算符,则必须将“/”替换为“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()

Demo

干杯!!