【问题标题】:How to evaluate an expression in one table field into another?如何将一个表字段中的表达式计算为另一个?
【发布时间】:2019-06-11 04:18:02
【问题描述】:

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

【问题讨论】:

  • 这些值总是 x+y 还是有其他数学运算符?等式中可以包含两个以上的值吗?您需要考虑操作顺序吗?您的问题实际上是“我如何编写数学解析器和计算器?”,而不是一件小事。
  • @SamM - 不一定。 OP 也可能会询问这样的解析器是否已经存在——而不是从头开始编写。这样的解析器确实存在。

标签: oracle plsql expression-evaluation


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    如果您的公式中只有有效的 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 包)并创建了一个支持单变量的包。

    【讨论】:

      【解决方案3】:

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

      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()
      

      Demo

      干杯!!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多