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 ''
我正在尝试在 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 ''