Oracle View条件逻辑

时间:2018-04-09 08:52:45

标签: oracle plsql sql-view

我有一个货币换算应用,当您从货币和货币给它时,它会返回汇率,例如: 从美元到欧元,费率= 2.10

货币保持在MY_TABLE。

我想扩展此应用以处理转换不存在的情况。为此,我将反转计算,例如

如果从美元开始,到欧元确实不存在 返回美元,欧元,费率= 1 / 2.10。

我将创建一个自动执行此转换的视图。我是新手,我现在要求引导他们这样做。这是我的伪代码。我知道它不对,但我是在正确的轨道上吗?

CREATE OR REPLACE VIEW MY_VIEW (FROM_CURR, TO_CURR, RATE) AS
DECLARE
  rates_found number;
BEGIN
      select count(*)
      into   rates_found
      from   MY_TABLE
      where  rownum = 1
      and FROM_CURR = ? and TO_CURR = ?

      if rates_found = 1 then
        select FROM_CURR, 
               TO_CURR, 
               RATE
        from   MY_TABLE
        and FROM_CURR = ? and TO_CURR = ?

      else
        select FROM_CURR, 
               TO_CURR, 
               1 / RATE AS RATE
        from   MY_TABLE
        and FROM_CURR = ? and TO_CURR = ?
END;

2 个答案:

答案 0 :(得分:1)

如果您只想要一个外汇汇率查询功能,您可以尝试这样的事情:

create or replace function fx_rate
    ( p_from_curr my_table.from_curr%type
    , p_to_curr   my_table.to_curr%type )
    return my_table.rate%type
    deterministic
as
    pragma udf;
    l_rate my_table.rate%type;
begin
    select min(rate) into l_rate
    from   my_table r
    where  r.from_curr = p_from_curr
    and    r.to_curr = p_to_curr;

    if l_rate is null then
        select 1/rate into l_rate
        from   my_table r
        where  r.from_curr = p_to_curr
        and    r.to_curr = p_from_curr;
    end if;
exception
    when no_data_found then
        return null;
end;

min(rate)有点减少所需的异常处理代码量,因为如果没有找到速率,它会留下l_rate null。我假设每种货币组合实际上只保留一种外汇汇率。

pragma udf减少了上下文切换(需要Oracle 12.1或更高版本)。

deterministic提供缓存 - 但由于该函数不是严格确定的,因此可能会被某些人视为作弊。

(总结一下我的评论,这可能是我们可以合理地要求Oracle 视为确定性的,即使严格来说没有真正的查找功能,所以如果是汇率在查询运行时会更新,我们明确地希望它返回旧的缓存结果而不是更新版本,这毕竟是SQL查询的功能。如果Oracle在未来实施更积极的缓存,当然会出现问题释放,或者如果不同值的数量超过隐式缓存,则无论如何都返回更新的值,因为deterministic不做任何保证。)

result_cache是另一种选择,但我建议测试性能,因为存在与缓存有效性检查机制等相关的一些开销,这可能会产生比执行查询更慢的最小响应时间。 result_cache更适合占用大量资源的功能。

答案 1 :(得分:0)

正如其他人的评论所述,您无法在PLSQL中使用view代码。因此,您需要编写如下函数来满足您的要求。

CREATE OR REPLACE TYPE CUR_CON IS OBJECT
(
 col1 VARCHAR2(100),
 col2 VARCHAR2(100),
 col3 number
);

CREATE OR REPLACE TYPE V_CUR_CON IS TABLE OF CUR_CON;

CREATE OR REPLACE FUNCTION MY_VIEW (FROM_CURR VARCHAR2, TO_CURR VARCHAR2, RATE NUMBER)  
RETURN V_CUR_CON 
AS
  rates_found NUMBER;
  var  V_CUR_CON:=V_CUR_CON();
BEGIN
      select count(*)
      into   rates_found
      from   MY_TABLE
      where  rownum = 1
      and FROM_CURR = ? and TO_CURR = ?

      if rates_found = 1 then
        select CUR_CON (FROM_CURR, 
               TO_CURR, 
               RATE)
        BULK COLLECT INTO var       
        from   MY_TABLE
        and FROM_CURR = ? and TO_CURR = ?

      else
        select CUR_CON (FROM_CURR, 
               TO_CURR, 
               1 / RATE AS RATE)
        BULK COLLECT INTO var
        from   MY_TABLE
        AND FROM_CURR = ? AND TO_CURR = ?

     Return var;   
END;

视图定义:因为您要创建视图。

CREATE OR REPLACE VIEW my_orig_view
as
select * from table(MY_VIEW);

选择:

Select * from my_orig_view