使用函数在 Oracle 中获取帐户详细信息
Get Account details in Oracle using function
我们有两个 table 帐户和部门,其中帐户级别 1 将来自帐户 table,级别 2 和级别 3 帐户级别来自部门。 table
现在根据输入,我们需要找到 table 中的帐户密钥,它应该根据源帐户 ID、数据库 ID 和帐户级别显示哪个帐户密钥。
输入:
[112].[22].[1],[113].[23].[1],[245].[21].[2],[289].[20].[2],[301].[21].[3],
[304].[20].[3]
描述:
112 - Account id(level1 accountid or leve2 accountid or level3 accountid),
22 - Database id,
1 or 2 or 3 -account level
例如:
帐号table:
DIM_CUST_KEY level1 account id databaseid
1123 112 22
1234 113 23
部门 table:
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;`
您的问题描述似乎有点乱,请格式化您的问题并使其更易读。无论如何,解决方案很简单。您只需要一个 if
语句,
根据级别,您可以在第一个或第二个 table 和适当的列中搜索:
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;
这里是 tables 和示例函数调用:
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
如果删除 with
和 cross join
部分并添加 into
子句,则可以在函数中使用此查询而不是 if
语句。
编辑:
抱歉耽搁了,我最近没看Stack Overflow。以下是如何编写函数的两个示例:
这个函数returns连接字符串:
select get_details_1('[112].[22].[1],[289].[20].[2],[301].[21].[3]') as list from dual;
LIST
------------------
1123,1576,1587
第二个函数是流水线式的,returns数据是预定义的字符串集合,所以值在不同的行中。
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;
我们有两个 table 帐户和部门,其中帐户级别 1 将来自帐户 table,级别 2 和级别 3 帐户级别来自部门。 table
现在根据输入,我们需要找到 table 中的帐户密钥,它应该根据源帐户 ID、数据库 ID 和帐户级别显示哪个帐户密钥。
输入:
[112].[22].[1],[113].[23].[1],[245].[21].[2],[289].[20].[2],[301].[21].[3],
[304].[20].[3]
描述:
112 - Account id(level1 accountid or leve2 accountid or level3 accountid),
22 - Database id,
1 or 2 or 3 -account level
例如:
帐号table:
DIM_CUST_KEY level1 account id databaseid
1123 112 22
1234 113 23
部门 table:
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;`
您的问题描述似乎有点乱,请格式化您的问题并使其更易读。无论如何,解决方案很简单。您只需要一个 if
语句,
根据级别,您可以在第一个或第二个 table 和适当的列中搜索:
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;
这里是 tables 和示例函数调用:
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
如果删除 with
和 cross join
部分并添加 into
子句,则可以在函数中使用此查询而不是 if
语句。
编辑:
抱歉耽搁了,我最近没看Stack Overflow。以下是如何编写函数的两个示例:
这个函数returns连接字符串:
select get_details_1('[112].[22].[1],[289].[20].[2],[301].[21].[3]') as list from dual;
LIST
------------------
1123,1576,1587
第二个函数是流水线式的,returns数据是预定义的字符串集合,所以值在不同的行中。
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;