2014-04-03 53 views
1

嗨我有一个分区表,当我试图更新在动态传递分区名称的循环中取少量选定的分区时,它不起作用。更新分区表oracle

for i in 1..partition_tbl.count Loop 

UPDATE cdr_data PARTITION(partition_tbl(i)) cdt 
SET A='B' 
WHERE 
cdt.ab='c' 

End Loop; 

partition_tbl对象包含我想要执行此更新的所有分区。

请告诉我如何在这里继续。

在此先感谢

回答

2

最好让Oracle照顾有关分区 - 假装你的声明,他们不存在

UPDATE cdr_data cdt SET A='B' WHERE cdt.ab='c' 

它将从那里的条件和您的分区定义选择合适的分区(S )来应用该命令。

当您需要一个有界的DML分区时,可能会发生罕见的事件,但当然它不是显示的示例。在这种情况下,你不能动态地提供分区名称,就像你通常不能动态地提供表名一样你不能

select * from _variable_containing_table_name 

如果你真的分区坚持界命令那么这将是

select * from table_name partition (partition_Name) 

例如

select * from bills partition (p201403) 

要使用动态分区名称,必须通过execute immediate或dbms_sql动态执行整个语句。

但是,再次,不要选择分区,Oracle会。

+0

感谢您的建议,我很困惑甲骨文是否会隐式处理它。现在将使用并行,看看它是如何。将结果更新到 – user3178723

3

你试图解决什么问题?对循环中的每个分区运行单独的UPDATE语句没有任何意义。如果你真的想以更新表,其中ab = 'c'每一行,只是发出一个单一UPDATE声明

UPDATE cdr_data cdt 
    SET a = 'B' 
WHERE ab = 'c' 
PARALLEL暗示,将允许Oracle并行更新多个分区

可能。

如果你真的真的想要独立地更新每个分区,那么基于分区键就可以做到这一点。例如,如果你的表有基于日期

FOR i IN 1 .. <<number of daily partitions>> 
LOOP 
    UPDATE cdr_data cdt 
    SET a = 'B' 
    WHERE ab = 'c' 
    AND partition_key = <<minimum date>> + i; 
END LOOP; 

使用partition(<<partition name>>)语法每日分区是一个绝对的最后手段。如果你真的决定走这条路,你需要使用动态SQL,在循环中构造SQL语句并使用EXECUTE IMMEDIATEdbms_sql来执行它。

+1

我同意,......出于好奇,你能想出一个有意义的情况来使用这种语法吗? –

+2

@MichalPravda - 找出哪些分区行被插入(当人们使用多列分区键而不真正理解它们的操作方式时会定期出现),或者确定散列分区策略是否在分区间大致平均分配数据或者您正在使用系统分区的位置。但是,只有系统分区会涉及应用程序代码使用“分区(<>)”语法的情况。 http://www.oracle-base.com/articles/11g/partitioning-enhancements-11gr1.php#system_partitioning –

+2

我遇到的分区(...)语法的有意义的情况是并发会话加载到同一个表中每个运行会话在自己的分区中)以直接路径模式运行。分区语法有助于避免会话彼此阻塞。 – Yavor