将列对选择到变量pl / sql中

时间:2016-06-15 17:05:58

标签: sql oracle plsql tuples

我有一个我多次重复使用的元组:

with ICC_DATA_REQS AS
(
 select ml_tran_id, tran_type, msg_type, icc_data as icc_data_req from TRANEMV2G where msg_type = 'CQ' and (BUSINESS_DT, ML_TRAN_ID) IN (
                SELECT BUSINESS_DT, ML_TRAN_ID
                FROM TRANRSP2G
                WHERE SETTLE_FILE_ID = -1)
),

ICC_DATA_RESP AS 
(
select ml_tran_id, tran_type, msg_type, icc_data as icc_data_rsp from TRANEMV2G where msg_type = 'CS' and (BUSINESS_DT, ML_TRAN_ID) IN (
                SELECT BUSINESS_DT, ML_TRAN_ID
                FROM TRANRSP2G
                WHERE SETTLE_FILE_ID = -1)
),
ICC_DATA_ADVC AS 
(
select ml_tran_id, tran_type, msg_type, orig_ml_tran_id, icc_data as icc_data_adv from TRANEMV2G where msg_type = 'CA' and (BUSINESS_DT, ORIG_ML_TRAN_ID) IN (
                SELECT BUSINESS_DT, ML_TRAN_ID
                FROM TRANRSP2G
                WHERE SETTLE_FILE_ID = -1)
)

我想做的是:

SELECT BUSINESS_DT, ML_TRAN_ID INTO vpairs
                FROM TRANRSP2G
                WHERE SETTLE_FILE_ID = -1

然后在其他查询中使用vpairs。这可能吗?我一直遇到未知的变量错误。

另外,我这样做的原因是表TRANEMV2G有3条记录,我需要3条记录中的数据作为3列。我找不到更好的办法。

3 个答案:

答案 0 :(得分:3)

您可以在另一个CTE中检索它们:

with p2g as
(
  select business_dt, ml_tran_id
  from tranrsp2g
  where settle_file_id = -1
),
icc_data_reqs as
(
  select v2g.ml_tran_id, tran_type, msg_type, icc_data as icc_data_req
  from p2g
  join tranemv2g v2g
  on v2g.business_dt = p2g.business_dt
  and v2g.ml_tran_id = p2g.ml_tran_id
  where v2g.msg_type = 'CQ'
),
icc_data_resp as 
(
  select v2g.ml_tran_id, tran_type, msg_type, icc_data as icc_data_rsp
  from p2g
  join tranemv2g v2g
  on v2g.business_dt = p2g.business_dt
  and v2g.ml_tran_id = p2g.ml_tran_id
  where v2g.msg_type = 'CS'
),
icc_data_advc as 
(
  select v2g.ml_tran_id, tran_type, msg_type, orig_ml_tran_id, icc_data as icc_data_adv
  from p2g
  join tranemv2g v2g
  on v2g.business_dt = p2g.business_dt
  and v2g.orig_ml_tran_id = p2g.ml_tran_id
  where v2g.msg_type = 'CA'
)

with p2g as
(
  select business_dt, ml_tran_id
  from tranrsp2g
  where settle_file_id = -1
),
icc_data_reqs as
(
  select ml_tran_id, tran_type, msg_type, icc_data as icc_data_req
  from tranemv2g
  where msg_type = 'CQ'
  and (business_dt, ml_tran_id) in (select business_dt, ml_tran_id from p2g)
),
icc_data_resp as 
(
  select ml_tran_id, tran_type, msg_type, icc_data as icc_data_rsp
  from tranemv2g
  where msg_type = 'CS'
  and (business_dt, ml_tran_id) in (select business_dt, ml_tran_id from p2g)
),
icc_data_advc as 
(
  select ml_tran_id, tran_type, msg_type, orig_ml_tran_id, icc_data as icc_data_adv
  from tranemv2g
  where msg_type = 'CA'
  and (business_dt, orig_ml_tran_id) in (select business_dt, ml_tran_id from p2g)
)

不确定是否比你拥有的要好得多。

如果你想要一个PL / SQL变量,那么因为你想在SQL上下文中使用它,它需要是一个SQL级别的类型:

create type t_tuple as object (business_dt date, ml_tran_id number)
/
create type t_tuple_tab as table of t_tuple
/

declare
    v_tuples t_tuple_tab;
begin
    select t_tuple(business_dt, ml_tran_id)
    bulk collect into v_tuples
    from tranrsp2g
    where settle_file_id = -1;

    with icc_data_reqs as
    (
      select ml_tran_id, tran_type, msg_type, icc_data as icc_data_req
      from tranemv2g
      where msg_type = 'CQ'
      and (business_dt, ml_tran_id) in
        (select business_dt, ml_tran_id from table(v_tuples))
    ),
    ...

或加入表集合表达式。除非您将在代码中稍后重新使用元组列表,否则这似乎并没有超过您的原始代码或使用额外的CTE。

但是,如果我理解你在做什么,你可以查询一次表并转动结果,至少如果你是11g或以上:

select * from
(
  select v2g.ml_tran_id, tran_type, msg_type, orig_ml_tran_id, icc_data
  from tranrsp2g p2g
  join tranemv2g v2g
  on v2g.business_dt = p2g.business_dt
  and ((v2g.msg_type in ('CQ', 'CS') and v2g.ml_tran_id = p2g.ml_tran_id)
    or (v2g.msg_type = 'CA' and v2g.orig_ml_tran_id = p2g.ml_tran_id))
  where p2g.settle_file_id = -1
)
pivot (max(icc_data) for (msg_type) in ('CQ' as req, 'CS' as rsp, 'CA' as adv))

答案 1 :(得分:1)

如果这些是常量值,那么您可以将它们存储在包中:

CREATE TABLE TRANRSP2G (
  BUSINESS_DT    DATE,
  ML_TRAN_ID     INT,
  SETTLE_FILE_ID INT
);

CREATE TYPE TRANRSP2G_PAIR IS OBJECT(
  BUSINESS_DT DATE,
  ML_TRAN_ID  INT
);
/
CREATE TYPE TRANRSP2G_PAIR_TABLE IS TABLE OF TRANRSP2G_PAIR;
/

CREATE PACKAGE TRANRSP2G_DATA AS
  FUNCTION getData RETURN TRANRSP2G_PAIR_TABLE;
END;
/

CREATE PACKAGE BODY TRANRSP2G_DATA AS
  pairs TRANRSP2G_PAIR_TABLE;

  FUNCTION getData RETURN TRANRSP2G_PAIR_TABLE
  IS
  BEGIN
    RETURN pairs;
  END;

BEGIN
  SELECT TRANRSP2G_PAIR( BUSINESS_DT, ML_TRAN_ID )
  BULK COLLECT INTO pairs
  FROM TRANRSP2G
  WHERE SETTLE_FILE_ID = -1;
END;
/

(注意:加载包时将填充pairs集合,并且存储的数据将保持静态[即使基础表发生更改],因此您不应将此方法用于非静态数据。)

然后你可以这样做:

WITH ICC_DATA_REQS AS
(
  select ml_tran_id, tran_type, msg_type, icc_data as icc_data_req
  from TRANEMV2G
  where msg_type = 'CQ'
  and   TRANRSP2G_PAIR(BUSINESS_DT, ML_TRAN_ID)
          MEMBER OF TRANRSP2G_DATA.getData()
),
...

答案 2 :(得分:0)

如果在连接时TRANRSP2G(对于SETTLE_FILE_ID = -1)的值不是太大,则可以在其他地方使用该列表。

LISTAGG是一个选项。 (或此处描述的其他方法:https://oracle-base.com/articles/misc/string-aggregation-techniques

SELECT LISTAGG(BUSINESS_DT || '_p_' || ML_TRAN_ID, ';')
       WITHIN GROUP (ORDER BY BUSINESS_DT || '_x_' || ML_TRAN_ID)
INTO vpairs
FROM TRANRSP2G
WHERE SETTLE_FILE_ID = -1;

然后vpairs可以与INSTR一起使用

select ml_tran_id, tran_type, msg_type, icc_data as icc_data_req 
from TRANEMV2G where msg_type = 'CQ' 
and INSTR(vpairs, BUSINESS_DT || '_x_' || ML_TRAN_ID) <> 0