使用列与另一列的Oracle

问题描述:

我有3个字段的表评估有这样的值:1,2,50,40使用列与另一列的Oracle

字段2(VARCHAR):有值,如: “+”, “ - ”, “*”

字段3(NUMBER):像字段1:5,65.4,90

如何与该字段的内容评价2.

示例

|field1| field2| field3| RESULT 
------------------------------- 
|  1|  +|  5| 6 
|  1|  *|  5| 5 
|  1|  -|  5| -4 
+0

这对您[Oracle文档](http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/) dynamic.htm#i13130)结合[This ref cursor article](http://www.oracle.com/technetwork/articles/dotnet/williams-refcursors-092375.html) – xQbert 2013-03-12 21:06:49

正如Annjawn在this answer中解释的那样,您可以使用XMLQuery的某些内置功能,特别是.getnumberval()来伪造公式。这将比CASE声明慢得多,但它更清洁。

假设表:

create table tmp_test (
    field1 number not null 
, field2 varchar2(1) not null 
, field3 number not null); 

insert all 
    into tmp_test values (1, '+', 5) 
    into tmp_test values (1, '*', 5) 
    into tmp_test values (1, '-', 5) 
select * from dual; 

您的查询应该是这样的:

SQL> select xmlquery(field1 || field2 || field3 returning content 
    2     ).getnumberval() as field4 
    3 from tmp_test; 

    FIELD4 
---------- 
     6 
     5 
     -4 

SQL Fiddle

我会强烈反对在数据库中存储计算列虽然建议。它只会导致问题,因为如果您更新列没有更新的数据库。做到这一点的正确方法是要么有一个视图,包括计算的定义,并始终从该视图中选择或使用create table documentation中定义的VIRTUAL column

然后,您可以使用XMLQueryDETERMINISTIC function(例如the one provided by APC)自动计算您的列。

如果在创建表,如下所示:

create table tmp_test (
    field1 number not null 
, field2 varchar2(1) not null 
, field3 number not null 
, field4 number generated always as (
      xmlquery(field1 || field2 || field3 returning content 
       ).getnumberval() 
      ) virtual 
    ); 

然后一个更简单的查询会得到你的结果

SQL> select * from tmp_test; 

    FIELD1 F  FIELD3  FIELD4 
---------- - ---------- ---------- 
     1 +   5   6 
     1 *   5   5 
     1 -   5   -4 

SQL Fiddle

这样做的另一个好处是,你的计算是总是以完全相同的方式完成。对于需要此计算列的每个单独代码段,它们的实现方式不同

SELECT 
    field1, 
    field2, 
    field3, 
    Case 
    When field2='+' then field1+field3 
    When field2='*' then field1*field3 
    When field2='-' then field3-field1 
    else 0 
    end as Result 
FROM table 

http://www.techonthenet.com/oracle/functions/case.php

我不知道在PL/SQL外EXECUTE IMMEDIATE任何EVAL类型的功能,而这仅限于一个语句在同一时间。你不能建立一个会增加一行,增加另一个,减去另一个,但你可以创建一个游标,通过它循环,并建立一个EXECUTE IMMEDIATE来评估每个游标行上的值。当然,如果你考虑的操作比使用两个操作数的简单数学更复杂,那么肯定会研究一下。

下面的查询会做你问什么,但如果你希望做任何事情,两列之间的操作更加复杂,将很麻烦很快:

SELECT 
    CASE field2 
    WHEN '+' THEN field1 + field3 
    WHEN '*' THEN field1 * field3 
    WHEN '-' THEN field1 - field3 
    END 
FROM ... 

你可以建立一个评价函数

create or replace function eval 
    (n1 in number 
    , n2 in number 
    , op in varchar2) 
return number deterministic 
as 
    result number; 
begin 
    execute immediate ' select :1 '|| op || ' : 2 from dual' 
     into result 
     using n1, n2; 
    return result; 
end; 
/

然后,您可以把它在一个SELECT语句:

select eval (field1, field3, field2) as result 
from your_table; 

这将应付简单的算术,但对于更复杂的公式不是一个好方法。如果你想要走这条路线,我建议你在我的答案中关注另一个关于在PL/SQL中进行数学问题的链接。 Find out more