使用传递给过程的动态表名立即执行

Posted

技术标签:

【中文标题】使用传递给过程的动态表名立即执行【英文标题】:execute immediate with dynamic table name passed to a procedure 【发布时间】:2021-05-01 18:42:22 【问题描述】:

我有一个视图 view_test_dynamic,其中包含作为单列的插入语句,如下所示。

我需要将此单列值填充到表中。示例如下 test_dynamic 表。

我有多个这样的视图,我需要填充到不同的表中。

当我通过为一个视图声明光标以正常方式创建过程时,它可以工作。

我想通过将视图名称传递给过程来使用动态 pl/sql,如下所示。

我在立即执行时遇到错误。错误说“表达式类型错误”

有人可以帮忙吗?

create or replace view view_test_dynamic as

select 'insert into test_dynamic(cust_id,address) values ('||cust_id||','''||address||''')' as trans_out
 
from

    (
    select 10 cust_id,'9 Help Street, Level 4' address from dual union all
    select 11 cust_id,'22 Victoria Street' address from dual union all
    select 12 cust_id,'1495 Franklin Str.' address from dual union all
    select 13 cust_id,'30 Hasivim St.,Petah-Tikva' address from dual union all
    select 14 cust_id,'2 Jakaranda St' address from dual union all
    select 15 cust_id,'61, Science Park Rd' address from dual union all
    select 16 cust_id,'61, Social park road.' address from dual union all
    select 17 cust_id,'Av. Hermanos Escobar 5756' address from dual union all
    select 18 cust_id,'Ave. Hermanos Escobar 5756' address from dual union all
    select 19 cust_id,'8000 W FLORISSANT Ave.' address from dual union all
    select 20 cust_id,'8600 MEMORIAL PKWY SW' address from dual union all
    select 21 cust_id,'8200 FLORISSANTMEMORIALWAYABOVE SW' address from dual union all
    select 22 cust_id,'8600 MEMORIALFLORISSANT PKWY SW.' address from dual
    ) t1;

表:

create table test_dynamic

(

cust_id number,

address varchar2(100)

);

程序:

CREATE OR REPLACE PROCEDURE POP_TABLES_DYNAMIC(p_table_name in varchar2) as

l_cursor sys_refcursor;

l_trans_out dbms_sql.varchar2_table;

l_processed_cnt number := 0;

l_rec varchar2(500);


BEGIN


  dbms_output.put_line( 'Started' );

  open l_cursor for 'select trans_out from ' || p_table_name;

  loop
    fetch l_cursor BULK COLLECT into l_trans_out LIMIT 5000;

    for i in 1 .. l_trans_out.count
    loop

      execute immediate l_trans_out using l_trans_out(i);

      commit;

      l_processed_cnt := l_processed_cnt+1;

    end loop;

    exit when l_cursor%notfound;

  end loop;

  close l_cursor;

  dbms_output.put_line( 'processed ' || l_processed_cnt || ' records' );


  dbms_output.put_line('Ended');

END;

/

sho err;

【问题讨论】:

【参考方案1】:

对于您发布的示例数据:

SQL> select * from view_test_dynamic;

TRANS_OUT
-------------------------------------------------------------------------------------------
insert into test_dynamic(cust_id,address) values (10,'9 Help Street, Level 4')
insert into test_dynamic(cust_id,address) values (11,'22 Victoria Street')
insert into test_dynamic(cust_id,address) values (12,'1495 Franklin Str.')
insert into test_dynamic(cust_id,address) values (13,'30 Hasivim St.,Petah-Tikva')
insert into test_dynamic(cust_id,address) values (14,'2 Jakaranda St')
insert into test_dynamic(cust_id,address) values (15,'61, Science Park Rd')
insert into test_dynamic(cust_id,address) values (16,'61, Social park road.')
insert into test_dynamic(cust_id,address) values (17,'Av. Hermanos Escobar 5756')
insert into test_dynamic(cust_id,address) values (18,'Ave. Hermanos Escobar 5756')
insert into test_dynamic(cust_id,address) values (19,'8000 W FLORISSANT Ave.')
insert into test_dynamic(cust_id,address) values (20,'8600 MEMORIAL PKWY SW')
insert into test_dynamic(cust_id,address) values (21,'8200 FLORISSANTMEMORIALWAYABOVE SW')
insert into test_dynamic(cust_id,address) values (22,'8600 MEMORIALFLORISSANT PKWY SW.')

13 rows selected.

SQL> select * from test_dynamic;

no rows selected

考虑这样一个(更简单的)代码:

SQL> create or replace procedure pop_tables_dynamic (p_table_name in varchar2)
  2  is
  3    rc    sys_refcursor;
  4    l_str view_test_dynamic.trans_out%type;
  5  begin
  6    open rc for 'select trans_out from ' || dbms_assert.sql_object_name(p_table_name);
  7    loop
  8      fetch rc into l_str;
  9      exit when rc%notfound;
 10      execute immediate l_str;
 11    end loop;
 12    close rc;
 13  end;
 14  /

Procedure created.

SQL> exec pop_tables_dynamic('view_test_dynamic');

PL/SQL procedure successfully completed.

结果:

SQL> select * from test_dynamic;

   CUST_ID ADDRESS
---------- ------------------------------------------------------------
        10 9 Help Street, Level 4
        11 22 Victoria Street
        12 1495 Franklin Str.
        13 30 Hasivim St.,Petah-Tikva
        14 2 Jakaranda St
        15 61, Science Park Rd
        16 61, Social park road.
        17 Av. Hermanos Escobar 5756
        18 Ave. Hermanos Escobar 5756
        19 8000 W FLORISSANT Ave.
        20 8600 MEMORIAL PKWY SW
        21 8200 FLORISSANTMEMORIALWAYABOVE SW
        22 8600 MEMORIALFLORISSANT PKWY SW.

13 rows selected.

【讨论】:

以上是关于使用传递给过程的动态表名立即执行的主要内容,如果未能解决你的问题,请参考以下文章

如何在存储过程中动态传递表名 - ORACLE [重复]

每个将表名传递给过程的 ORACLE PL/SQL

如何动态地将表名传递给 PL SQL 游标?

没有参数的redshift过程和参数中的动态表名

存储过程:将表名转换为表变量

sql server存储过程如何动态生成表名