使用功能获取Oracle中的帐户详细信息

时间:2018-08-01 12:09:48

标签: oracle oracle11g oracle10g oracle-sqldeveloper

我们有两个表帐户和部门,其中accunt级别1将来自帐户表,而级别2和3帐户级别则来自部门。桌子

现在,基于输入,我们需要找到两个表中的accountkey,并且应该根据源帐户ID,数据库ID和帐户级别显示哪个accountkey。

输入:     [112].[22].[1],[113].[23].[1],[245].[21].[2],[289].[20].[2],[301].[21].[3], [304].[20].[3]

说明:

  

112-帐户ID(1级帐户ID或2级帐户ID或3级帐户ID),
    22-数据库ID,
    1或2或3个帐户级别

例如:

帐户表:

DIM_CUST_KEY level1 account id databaseid 1123 112 22 1234 113 23

部门表:

DIM_CUST_KEY level2 account id level3 account id databaseid 1587 245 301 21 1576 289 304 20

我尝试过的事情:

`create or replace function get_accountdetails (par_input in varchar2) return 
varchar2 is
v_ret varchar2(20) := '';
begin
select dim_cust_key from dim_cust_acnt a
inner join dim_cust_dept d using (dim_cust_key)

where ( 1 = regexp_substr(par_input, '\d+', 1, 3)  
       and regexp_substr(par_input, '\d+', 1, 1) = level1_account_id 
       and regexp_substr(par_input, '\d+', 1, 2) = a.database_id )
or    ( 2 = regexp_substr(par_input, '\d+', 1, 3)  
      and regexp_substr(par_input, '\d+', 1, 1) = level2_account_id 
      and regexp_substr(par_input, '\d+', 1, 2) = d.database_id )
or    ( 3 = regexp_substr(par_input, '\d+', 1, 3)  
      and regexp_substr(par_input, '\d+', 1, 1) = level3_account_id 
      and regexp_substr(par_input, '\d+', 1, 2) = d.database_id )
  return v_ret;
end;`

1 个答案:

答案 0 :(得分:2)

您似乎对问题的描述有些混乱,请格式化问题并使其更具可读性。无论如何,解决方案很简单。您只需要一个if语句, 在哪个位置(取决于级别)在第一或第二个表以及适当的列中进行搜索:

create or replace function get_accountdetails (par_input in varchar2) return varchar2 is
  v_aid varchar2(10);
  v_db  varchar2(10);
  v_lvl varchar2(10);
  v_ret varchar2(20) := '';
begin
  v_aid := regexp_substr(par_input, '\d+', 1, 1);
  v_db  := regexp_substr(par_input, '\d+', 1, 2);
  v_lvl := regexp_substr(par_input, '\d+', 1, 3);

  if v_lvl = 1 then
     select dim_cust_key
       into v_ret
       from dim_cust_acnt
       where level1_account_id = v_aid and database_id = v_db;
  elsif v_lvl = 2 then
     select dim_cust_key
       into v_ret
       from dim_cust_dept
       where level2_account_id = v_aid and database_id = v_db;
  else
     select dim_cust_key
       into v_ret
       from dim_cust_dept
       where level3_account_id = v_aid and database_id = v_db;
  end if;
  return v_ret;
end;

以下是表和示例函数调用:

create table dim_cust_acnt (dim_cust_key, level1_account_id, database_id) as (
    select 1123, 112, 22 from dual union all
    select 1234, 113, 23 from dual );

create table dim_cust_dept (dim_cust_key, level2_account_id, level3_account_id, database_id) as (
    select 1587, 245, 301, 21 from dual union all
    select 1576, 289, 304, 20 from dual);

select get_accountdetails('[112].[22].[1]') from dual;     -- result: 1123
select get_accountdetails('[289].[20].[2]') from dual;     -- result: 1576
select get_accountdetails('[301].[21].[3]') from dual;     -- result: 1587

请使用真实数据中使用的适当列名称,并根据需要调整变量类型和长度。我认为您也可以使用一个联合查询,不需要特殊功能,如下所示。我使用full join,因为您的示例不包含匹配的行。只需简单的join就足够了。

with t(par_input) as (select '[112].[22].[1]' from dual)
select dim_cust_key
  from dim_cust_acnt a
  full join dim_cust_dept d using (dim_cust_key) 
  cross join t
  where ( 1 = regexp_substr(par_input, '\d+', 1, 3)  
          and regexp_substr(par_input, '\d+', 1, 1) = level1_account_id 
          and regexp_substr(par_input, '\d+', 1, 2) = a.database_id )
     or ( 2 = regexp_substr(par_input, '\d+', 1, 3)  
          and regexp_substr(par_input, '\d+', 1, 1) = level2_account_id 
          and regexp_substr(par_input, '\d+', 1, 2) = d.database_id )
     or ( 3 = regexp_substr(par_input, '\d+', 1, 3)  
          and regexp_substr(par_input, '\d+', 1, 1) = level3_account_id 
          and regexp_substr(par_input, '\d+', 1, 2) = d.database_id )

结果:

DIM_CUST_KEY
------------
        1123

如果删除withcross join部分并添加into子句,则可以在函数中使用此查询而不是if语句。


编辑:

对不起,我最近没看堆栈溢出。这是两个如何编写函数的示例:

此函数返回串联的字符串:

select get_details_1('[112].[22].[1],[289].[20].[2],[301].[21].[3]') as list from dual;

LIST
------------------
1123,1576,1587

第二个函数进行了流水线处理,并以字符串的预定义集合形式返回数据,因此值位于单独的行中。

select column_value 
  from table(get_details_2('[112].[22].[1],[289].[20].[2],[301].[21].[3]'));

COLUMN_VALUE
------------
        1123
        1576
        1587

您还可以首先解析所有输入数据,将它们存储在某个集合中,然后在一个查询中使用批量收集。有很多解决方案和可能性,就我个人而言,我将使用流水线函数,但它取决于您需要哪种输出形式(集合或串联字符串)。您还可以添加begin ... end块并处理异常when no_data_found。您可以随后显示特殊信息或中断执行,这取决于在这种情况下预期的行为。

功能1:

create or replace function get_details_1 (par_input in varchar2) return varchar2 is
    v_aid varchar2(10);
    v_db  varchar2(10);
    v_lvl varchar2(10);
    v_ret varchar2(20);
    v_all varchar2(200) := '';

    i_cnt int := 0;
begin
    loop
        v_aid := regexp_substr(par_input, '\d+', 1, i_cnt + 1);
        v_db  := regexp_substr(par_input, '\d+', 1, i_cnt + 2);
        v_lvl := regexp_substr(par_input, '\d+', 1, i_cnt + 3);
        i_cnt := i_cnt + 3;
    exit when v_aid is null;
        select dim_cust_key
          into v_ret
          from dim_cust_acnt a
          full join dim_cust_dept d using (dim_cust_key)
          where (v_lvl = 1 and level1_account_id = v_aid and a.database_id = v_db)
             or (v_lvl = 2 and level2_account_id = v_aid and d.database_id = v_db)
             or (v_lvl = 3 and level3_account_id = v_aid and d.database_id = v_db);
       v_all := v_all||','||v_ret;
  end loop;
  return ltrim(v_all, ',');
end;

功能2:

create or replace function get_details_2 (par_input in varchar2) 
    return sys.odcinumberlist pipelined is

    v_aid varchar2(10);
    v_db  varchar2(10);
    v_lvl varchar2(10);
    v_ret varchar2(20);
    i_cnt int := 0;
begin
    loop
        v_aid := regexp_substr(par_input, '\d+', 1, i_cnt + 1);
        v_db  := regexp_substr(par_input, '\d+', 1, i_cnt + 2);
        v_lvl := regexp_substr(par_input, '\d+', 1, i_cnt + 3);
        i_cnt := i_cnt + 3;
    exit when v_aid is null;
        select dim_cust_key
          into v_ret
          from dim_cust_acnt a
          full join dim_cust_dept d using (dim_cust_key)
          where (v_lvl = 1 and level1_account_id = v_aid and a.database_id = v_db)
             or (v_lvl = 2 and level2_account_id = v_aid and d.database_id = v_db)
             or (v_lvl = 3 and level3_account_id = v_aid and d.database_id = v_db);
       pipe row (v_ret);
  end loop;
  return;
end;