如何将动态sql的多行结果插入另一个表?

Posted

技术标签:

【中文标题】如何将动态sql的多行结果插入另一个表?【英文标题】:How to insert multiple row result of dynamic sql to another Table? 【发布时间】:2019-05-03 04:59:15 【问题描述】:

我写了一个动态 SQL,它的结果是一个有 2 列和多行的表,我想将它插入到另一个有 4 列的表中,其中 2 列将被动态 SQL 的结果填充,我尝试使用集合但不知道如何将结果插入另一个表

CREATE OR REPLACE PROCEDURE P_C_SM_Failure_error_Code_P2P AS

v_month          VARCHAR2(16); -- to get Month for each table
v_day            VARCHAR2(16); -- to get day for each table
v_ERRCODE        t_c_rpt_resultmsg.code%TYPE;
v_ERRMSG         t_c_rpt_resultmsg.MESSAGE%TYPE;
v_param          VARCHAR2(16);
v_sql            VARCHAR2(3000);
v_result         number;
type t_c_result is record (Err_code varchar2(2000), Err_count number);
type v_t_result is table of t_c_result index by PLS_INTEGER;
v_t1_result      v_t_result; 
BEGIN
v_sql :='0';
v_param := 'Gateway_G';
v_result := '0';
select to_char(sysdate - 1,'MM') into v_month from dual;
select to_char(sysdate - 1,'DD') into v_day from dual;

-- Get count of P2P
v_sql := '(select count(*), error_code from (
select error_code from sm_histable'||v_month||''||v_day||'@ORASMSC01 where 
orgaccount = '''||v_param||''' and destaccount = '''||v_param||''' and 
sm_status <> 1 union all
select error_code from sm_histable'||v_month||''||v_day||'@ORASMSC02 where 
orgaccount = '''||v_param||''' and destaccount = '''||v_param||''' and 
sm_status <> 1 )
group by error_code)';
EXECUTE IMMEDIATE v_sql bulk collect into v_t1_result; 

--insert into t_c_rpt_result2 values (trunc(sysdate, 'DD'), v_errcount, 
v_err_code,'Failure_error_Code_P2P');


--for indx in 1 .. v_t1_result.COUNT
--loop
--dbms_output.put_line (v_t1_result (indx).Err_code);
--end loop;

【问题讨论】:

【参考方案1】:

您可以将日期的常量值和错误消息附加到子查询并运行动态插入。如果您删除动态 sql 的外括号,它也应该可以工作,因为常量可以包含在group by 中。永远记住将值作为绑定变量传递,而不是将它们连接起来 (v_param)。此外,在 INSERT 语句中明确指定列名。

v_sql := '(select count(*) as cnt, error_code 
           from (
               select error_code from sm_histable'||v_month||''||v_day||'@ORASMSC01 
            where orgaccount = :x and destaccount = :x  and sm_status <> 1 
            union all
               select error_code from sm_histable'||v_month||''||v_day||'@ORASMSC02 
            where  orgaccount = :x and destaccount = :x and sm_status <> 1 )
         group by error_code)';
EXECUTE IMMEDIATE v_sql bulk collect into v_t1_result using v_param; 

EXECUTE IMMEDIATE 'insert into t_c_rpt_result2(err_dt,err_msg,errcount,error_code) 
                    select :dt,:msg,cnt,error_code from '|| v_sql
        USING trunc(sysdate, 'DD'),'Failure_error_Code_P2P',v_param;

【讨论】:

【参考方案2】:

我认为您正在寻找 FORALL 的出色用例。您正在填充的集合需要立即执行,因为您正在动态构建表名。但是插入到 t_c_rpt_result2 对我来说看起来是静态的。

BEGIN
   v_sql :=
         '(select count(*) as cnt, error_code 
           from (
               select error_code from sm_histable'
      || v_month
      || ''
      || v_day
      || '@ORASMSC01 
            where orgaccount = :x and destaccount = :x  and sm_status <> 1 
            union all
               select error_code from sm_histable'
      || v_month
      || ''
      || v_day
      || '@ORASMSC02 
            where  orgaccount = :x and destaccount = :x and sm_status <> 1 )
         group by error_code)';

   EXECUTE IMMEDIATE v_sql BULK COLLECT INTO v_t1_result USING v_param;

   FORALL indx IN 1 .. v_t1_result.COUNT
      INSERT INTO t_c_rpt_result2 (err_dt,
                                   err_msg,
                                   errcount,
                                   ERROR_CODE)
           VALUES (TRUNC (SYSDATE, 'DD'),
                   'Failure_error_Code_P2P',
                   v_t1_result (indx).cnt,
                   v_t1_result (indx).ERROR_CODE);
END;

在 LiveSQL here 上查找更多 FORALL 示例。当然,即使您的插入是动态的,您也可以使用 FORALL - 将执行立即数直接放在 FORALL 语句的“内部”。但我认为这里的复杂性是不合理的。

希望有帮助!

【讨论】:

我改了,但现在卡在PLS-00103上-遇到符号异常似乎有一些书写问题但我找不到。 Majid,也许您可​​以将问题中的代码替换为您尝试编译和执行的完整块或过程。否则很难给你建议。也欢迎您通过 steven.feuerstein@oracle.com 将代码直接发送给我。

以上是关于如何将动态sql的多行结果插入另一个表?的主要内容,如果未能解决你的问题,请参考以下文章

使用存储过程(SQL + C#)将数据插入一个表,然后将多行插入另一个表

将 SQL 代码(作为字符串)转换为表 - 动态数据透视

sql中一对多关系的查询结果的多行转换成一行多列

将一个表的查询结果插入到另一个表中(oracle、mysql、sql 、GP)

如何将一个表的查询结果插入到另一个表中?

在 SQL Server 中将多行动态组合成多列