2

(背景:我们正在运行使用Oracle Warehouse Builder构建的数据仓库最近,我们开始在等待锁定时获得大量“ORA-02049:分布式事务超时“错误,原因是我们并行运行多个ETL作业,并且这些作业中的每一个都将INSERT /*+APPEND PARALLEL*/插入到暂存表中。该暂存表由源系统ID进行分区。)Oracle/OWB:在运行时指定用于INSERT的分区

I' d想知道是否可以在运行时指定INSERT的分区键。 假设我有一个表

create table tmp_loading_table (
    etl_source_system_fk number not null enable, 
    object_id number not null enable, 
    object_name varchar2(30) not null enable 
) 
    PARTITION BY LIST ("ETL_SOURCE_SYSTEM_FK") 
(PARTITION "ESS1" VALUES (1), 
PARTITION "ESS2" VALUES (2) 
); 

那么我可以插入使用

insert /*+ APPEND PARALLEL("TMP_LOADING_TABLE") */  
into tmp_loading_table partition(ESS1) (
    etl_source_system_fk, object_id, object_name) 
(select 1 etl_source_system_fk, object_id, object_name from user_objects); 

特定的分区,但是这需要我硬编码的分区名称。

由于我们的OWB映射是通用的(他们得到的源系统ID作为参数),我想在运行时提供的分区名称,像

insert /*+ APPEND PARALLEL("TMP_LOADING_TABLE") */  
into tmp_loading_table partition(:partition_name) (
    etl_source_system_fk, object_id, object_name) 
(select 1 etl_source_system_fk, object_id, object_name from user_objects); 

这可能吗?如果没有,是否有另一种方法可以通过Oracle Warehouse Builder实现这一点?

回答

1

PARTITION FOR语法和动态SQL可以提供帮助。

理想情况下是这样简单:

declare 
    v_partition_value number := 1; 
begin 
    insert /*+ APPEND PARALLEL("TMP_LOADING_TABLE") */  
    into tmp_loading_table partition for (v_partition_value) (
     etl_source_system_fk, object_id, object_name) 
    (select 1 etl_source_system_fk, object_id, object_name from user_objects); 
end; 
/

不幸的是,上面的代码失败ORA-14108: illegal partition-extended table name syntax。这很奇怪,因为对于该语法来说这似乎是一个明显的用法 。

添加动态SQL删除错误。

declare 
    v_partition_value number := 1; 
begin 
    execute immediate ' 
    insert /*+ APPEND PARALLEL("TMP_LOADING_TABLE") */  
    into tmp_loading_table partition for ('||v_partition_value||') (
     etl_source_system_fk, object_id, object_name) 
    (select 1 etl_source_system_fk, object_id, object_name from user_objects)'; 
end; 
/

我对Oracle Warehouse Builder不熟悉,不知道该解决方案是否可以在该环境中工作。我假设在数据仓库中SQL注入不是问题。


另一种方式在运行时指定分区名称是system partitioningDATAOBJ_TO_PARTITION

create table tmp_loading_table (
    etl_source_system_fk number not null enable, 
    object_id number not null enable, 
    object_name varchar2(30) not null enable 
) 
PARTITION BY SYSTEM 
(
    PARTITION ess1, 
    PARTITION ess2 
); 

declare 
    v_object_id number; 
begin 
    select object_id 
    into v_object_id 
    from dba_objects 
    where object_name = 'TMP_LOADING_TABLE' 
     and subobject_name = 'ESS1'; 

    insert into tmp_loading_table 
    partition (dataobj_to_partition (tmp_loading_table, v_object_id)) 
    values (1, 2, 'A'); 
end; 
/

这种方法的巨大缺点是每一个DML必须引用分区:

insert into tmp_loading_table 
values (1, 2, 'A'); 

ORA-14701: partition-extended name or bind variable must be used for DMLs on tables partitioned by the System method 

我从来没有听说过使用此功能的任何人。根据我的经验,Oracle数据盒式磁带有问题。这个动态SQL现在看起来如何? :)

+0

感谢您的答案 - 我只想使用动态SQL作为最后的手段,因为这将使OWB思路更复杂。令人遗憾的是PARTITION FOR语法不起作用:-( –