Другой способ сделать это в SQL без PL / 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
Таким образом, вы можете легко выполнять вычисления динамического c, вам просто нужно добавить '$' к именам переменных:
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)','$\1'))
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 Обратите внимание, перед знаком «-» нужно поставить пробел, иначе он будет считаться переменной «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 ''