Oracle 中的动态指标计算 SQL

Dynamic Metric Calculations In Oracle SQL

我正在尝试在 Oracle 中自动执行一些指标计算。我确实有大约 50 个指标需要根据一些底层信息进行计算。每个指标都有不同的计算逻辑,尽管它们可以共享基础数据点。我在一个字段中捕获了所有计算文本以及 table.

中的基础数据点

我正在尝试使用动态 SQL 编写函数来完成工作。下面只是我所遵循的方法的代码块。可以肯定的是,我没有以正确的方式进行操作,因此提示错误:

DECLARE
    A NUMBER :=10;
    B NUMBER :=20;
    C NUMBER :=40;
    D NUMBER :=35;
    OUTPUT_VAR NUMBER;
    SQL_TEXT VARCHAR2(50);
BEGIN
--    SQL_TEXT:='OUTPUT_VAR:=A+B;';
--    SQL_TEXT:='OUTPUT_VAR:=A+B+C;';
--    SQL_TEXT:='OUTPUT_VAR:=A/D;';
--    SQL_TEXT:='OUTPUT_VAR:=A*B;';
--    SQL_TEXT:='OUTPUT_VAR:=B+C;';
--    SQL_TEXT:='OUTPUT_VAR:=C/D;';
--    SQL_TEXT:='OUTPUT_VAR:=B/C;';
    SQL_TEXT:='OUTPUT_VAR:=A+D;';
    
    EXECUTE IMMEDIATE SQL_TEXT;
    DBMS_OUTPUT.PUT(OUTPUT_VAR);
END;

这是我遇到的错误:

Error starting at line : 1 in command -
DECLARE
    A NUMBER :=10;
    B NUMBER :=20;
    C NUMBER :=40;
    D NUMBER :=35;
    OUTPUT_VAR NUMBER;
    SQL_TEXT VARCHAR2(50);
BEGIN
--    SQL_TEXT:='OUTPUT_VAR:=A+B;';
--    SQL_TEXT:='OUTPUT_VAR:=A+B+C;';
--    SQL_TEXT:='OUTPUT_VAR:=A/D;';
--    SQL_TEXT:='OUTPUT_VAR:=A*B;';
--    SQL_TEXT:='OUTPUT_VAR:=B+C;';
--    SQL_TEXT:='OUTPUT_VAR:=C/D;';
--    SQL_TEXT:='OUTPUT_VAR:=B/C;';
    SQL_TEXT:='OUTPUT_VAR:=A+D;';

    EXECUTE IMMEDIATE SQL_TEXT;
    DBMS_OUTPUT.PUT(OUTPUT_VAR);
END;
Error report -
ORA-00900: invalid SQL statement
ORA-06512: at line 18
00900. 00000 -  "invalid SQL statement"
*Cause:    
*Action:

请求帮助以完成这项工作。感谢您的回复,谢谢!

DECLARE
    A NUMBER :=10;
    B NUMBER :=20;
    C NUMBER :=40;
    D NUMBER :=35;
    OUTPUT_VAR NUMBER;
    SQL_TEXT VARCHAR2(50);
function calc(p_cmd in varchar2) return number as
   res number;
begin
    execute immediate '
       Declare
           A NUMBER :=:a;
           B NUMBER :=:b;
           C NUMBER :=:c;
           D NUMBER :=:d;
           OUTPUT_VAR number;
        Begin 
           '||p_cmd||'  
           :res:= output_var; 
        end;' 
        Using a, b, c, d, out res;
     Return res;
End;
BEGIN
--    SQL_TEXT:='OUTPUT_VAR:=A+B;';
--    SQL_TEXT:='OUTPUT_VAR:=A+B+C;';
--    SQL_TEXT:='OUTPUT_VAR:=A/D;';
--    SQL_TEXT:='OUTPUT_VAR:=A*B;';
--    SQL_TEXT:='OUTPUT_VAR:=B+C;';
--    SQL_TEXT:='OUTPUT_VAR:=C/D;';
--    SQL_TEXT:='OUTPUT_VAR:=B/C;';
    SQL_TEXT:='OUTPUT_VAR:=A+D;';
    
    OUTPUT_VAR:=calc(SQL_TEXT) ;
    DBMS_OUTPUT.PUT_LINE(OUTPUT_VAR);
END; 

在没有 PL/SQL 的 SQL 中实现的另一种方法是使用 XMLTABLE 或 XMLQUERY。 XQUERY 让你可以很容易地进行简单的计算,例如:

select * 
from xmltable(
       '$A + $B - $C'
       passing 1 as A, 2 as B, 3 as C
       columns res number path '.'
     );

       RES
----------
         0

select * 
from xmltable(
       '$A + $B * $C'
       passing 1 as A, 2 as B, 3 as C
       columns res number path '.'
     );

       RES
----------
         7

所以你可以很容易地进行动态计算,你只需要在变量名前加上'$':

with
data(a,b,c,d) as (
   select 1,1,1,1 from dual union all
   select 1,2,3,4 from dual union all
   select 5,5,5,5 from dual 
)
,calc(id, expression) as (
    select 1, 'A + B' from dual union all
    select 2, 'A + B - C' from dual union all
    select 3, 'A * B * C' from dual union all
    select 4, '(A + B) * C - D' from dual
)
select
   *
from
    data d
   ,calc c
   ,xmltable(
        (regexp_replace(c.expression,'(\w)','$'))
        passing
            d.A as A,
            d.B as B,
            d.C as C,
            d.D as D
        columns
            res number path '.'
   ) x;

         A          B          C          D         ID EXPRESSION             RES
---------- ---------- ---------- ---------- ---------- --------------- ----------
         1          1          1          1          1 A + B                    2
         1          1          1          1          2 A + B - C                1
         1          1          1          1          3 A * B * C                1
         1          1          1          1          4 (A + B) * C - D          1
         1          2          3          4          1 A + B                    3
         1          2          3          4          2 A + B - C                0
         1          2          3          4          3 A * B * C                6
         1          2          3          4          4 (A + B) * C - D          5
         5          5          5          5          1 A + B                   10
         5          5          5          5          2 A + B - C                5
         5          5          5          5          3 A * B * C              125
         5          5          5          5          4 (A + B) * C - D         45

12 rows selected.


PS 请注意,您需要在“-”符号之前添加一个 space,否则它将被视为 'B-' 变量:

SQL> select * from xmltable('$A+$B-$C' passing 1 as A, 2 as B, 3 as C columns res number path '.');
select * from xmltable('$A+$B-$C' passing 1 as A, 2 as B, 3 as C columns res number path '.')
                               *
ERROR at line 1:
ORA-19228: XPST0008 - undeclared identifier: prefix 'B-' local-name ''