如何将动态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#)将数据插入一个表,然后将多行插入另一个表