我可以从分区查询数据,但不能删除分区 (ORA-14006)?
I can query data from partitions, but not drop the partitions (ORA-14006)?
我有一个名为 schema.exampletab 的 table,它有分区,其中分区名称的格式为 Pxxxxxx,其中 x 是分区周期(年和月 YYYYMM),然后有一个本地PK。我想删除一个分区,但我收到错误消息 ORA-14006:尝试删除它时分区名称无效,但是当我尝试简单地从分区查询数据时,它 selects 并显示来自有问题的分区。请注意,我使用的调度程序使用 YYYYMMDD 将日期用作参数,因此我通常使用子字符串。
例如我可以使用以下语句查询数据:
SELECT *
FROM schema.exampletab
PARTITION (P202110);
这returns 20行数据在我的table。
然后我尝试使用以下语句删除分区:
ALTER TABLE schema.exampletab DROP PARTITION (concat(P,substr('20211011',1,6))
UPDATE INDEXES;
但是,这会导致出现 ORA-14006 错误消息。为了控制分区的存在,我试图查找架构 table 和分区存在于 all_tab_partitions 中,其中记录了我使用的数据库中的所有分区。
select partition_name from all_tab_partitions
where table_owner = 'schema' and table_name = 'exampletab' and
substr(partition_name,2,7) = substr('20211022',1,6);
这个returns查询结果中的分区名P202110
我希望我可以像这样将删除分区与子查询一起使用:
ALTER TABLE schema.exampletab DROP PARTITION select partition_name from all_tab_partitions
where table_owner = 'schema' and table_name = 'exampletab' and
substr(partition_name,2,7) = substr('20211022',1,6);
但是,这仍然会导致 ORA-14006 错误。我尝试将分区名称写为 'P202110' 和 P202110 而不是括号,但没有成功。
如何编写删除分区语句以删除分区而不是给出 ORA-14006 错误?
这是我必须经常做的事情,所以很高兴知道如何正确 select 和删除分区,或截断它们等。此外,我使用一个运行 select 的调度程序=38=] 以指定的时间间隔查询,所以我必须将日期指定为参数,这意味着在我的示例代码中 YYYYMM 是一个被解析的参数值,所以我需要将 P 与这个输出的参数值连接起来,因为如果我只输入 P202110 它实际上掉了它。
您不能在分区名称中使用“表达式”
这是错误的:
ALTER TABLE schema.exampletab DROP PARTITION (concat(P,substr('20211011',1,6))
UPDATE INDEXES;
这是正确的:
ALTER TABLE schema.exampletab DROP PARTITION P20211011
UPDATE INDEXES;
您可以使用此代码动态删除分区。只需更新 header 中的 C_OWNER ,C_TABLE_NAME , C_PARTITION_TEMPLATE 。请注意 sql 命令是动态构建的,但是当它准备就绪时,分区名称已完全解析。
declare
C_OWNER varchar2(128) := 'MYOWNER';
C_TABLE_NAME varchar2(128) := 'MYTABLE';
C_PARTITION_TEMPLATE varchar2(128) := '2011';
cursor part_cur is
select *
from all_tab_partitions
where table_owner=C_OWNER and
table_name = C_TABLE_NAME and
partition_name like '%'||C_PARTITION_TEMPLATE||'%'
order by partition_position;
BEGIN
for part_rec in part_cur loop
execute immediate 'ALTER TABLE "'||part_rec.table_owner||'"."'||part_rec.table_name||'"'||
' DROP PARTITION ("'||part_rec.partition_name||'") UPDATE INDEXES';
end loop;
END;
/
您有两个选择,请考虑到您正在使用 sysdate
来了解您应该删除哪个分区。
选项 1 -> 动态 SQL 并且结果必须在查询之外执行
select ' alter table '||table_owner||'.'||table_name||' drop partition '||partition_name||' update indexes ; '
from
dba_Tab_partitions
where table_owner = 'your_schema'
and table_name = 'your_table'
and partition_name = 'P'||substr(to_char(sysdate,'yyyymmdd'),1,6) ; ;
此查询为您提供命令输出,但您需要执行它
alter table yourschema.yourtable drop partition P202110 update indexes;
我自己环境中的示例
SQL> select ' alter table '||table_owner||'.'||table_name||' drop partition '||partition_name||' update indexes ; '
from
dba_Tab_partitions
where table_owner = 'FDM_DATA'
and table_name = 'FDM_DIM_CUSTOMER'
and partition_name = 'P_'||substr(to_char(sysdate,'yyyymmdd'),1,6) ;
'ALTERTABLE'||TABLE_OWNER||'.'||TABLE_NAME||'DROPPARTITION'||PARTITION_NAME||'UP
--------------------------------------------------------------------------------
alter table FDM_DATA.FDM_DIM_CUSTOMER drop partition P_202110 update indexes ;
选项 2 -> PLSQL
更好的选择是使用 PLSQL
。一个小例子,当你只想删除一个基于当前 sysdate
的分区时。您可以扩展/修改此代码以涵盖任何类型的时间范围。
declare
v_owner varchar2(128) := 'YOUR_SCHEMA';
v_table_name varchar2(128) := 'YOUR_TABLE';
v_partition_name varchar2(128);
begin
select partition_name into v_partition_name from all_tab_partitions
where table_owner = v_owner and
table_name = v_table_name and
partition_name = 'P'||substr(to_char(sysdate,'yyyymmdd'),1,6) ;
execute immediate 'alter table '||v_owner||'.'||v_table_name||' drop partition '||v_partition_name||' update indexes' ;
exception
when no_data_found then null; -- if there is no partition, nothing to do and no error is raised
when others then raise;
end;
/
我有一个名为 schema.exampletab 的 table,它有分区,其中分区名称的格式为 Pxxxxxx,其中 x 是分区周期(年和月 YYYYMM),然后有一个本地PK。我想删除一个分区,但我收到错误消息 ORA-14006:尝试删除它时分区名称无效,但是当我尝试简单地从分区查询数据时,它 selects 并显示来自有问题的分区。请注意,我使用的调度程序使用 YYYYMMDD 将日期用作参数,因此我通常使用子字符串。
例如我可以使用以下语句查询数据:
SELECT *
FROM schema.exampletab
PARTITION (P202110);
这returns 20行数据在我的table。 然后我尝试使用以下语句删除分区:
ALTER TABLE schema.exampletab DROP PARTITION (concat(P,substr('20211011',1,6))
UPDATE INDEXES;
但是,这会导致出现 ORA-14006 错误消息。为了控制分区的存在,我试图查找架构 table 和分区存在于 all_tab_partitions 中,其中记录了我使用的数据库中的所有分区。
select partition_name from all_tab_partitions
where table_owner = 'schema' and table_name = 'exampletab' and
substr(partition_name,2,7) = substr('20211022',1,6);
这个returns查询结果中的分区名P202110
我希望我可以像这样将删除分区与子查询一起使用:
ALTER TABLE schema.exampletab DROP PARTITION select partition_name from all_tab_partitions
where table_owner = 'schema' and table_name = 'exampletab' and
substr(partition_name,2,7) = substr('20211022',1,6);
但是,这仍然会导致 ORA-14006 错误。我尝试将分区名称写为 'P202110' 和 P202110 而不是括号,但没有成功。
如何编写删除分区语句以删除分区而不是给出 ORA-14006 错误?
这是我必须经常做的事情,所以很高兴知道如何正确 select 和删除分区,或截断它们等。此外,我使用一个运行 select 的调度程序=38=] 以指定的时间间隔查询,所以我必须将日期指定为参数,这意味着在我的示例代码中 YYYYMM 是一个被解析的参数值,所以我需要将 P 与这个输出的参数值连接起来,因为如果我只输入 P202110 它实际上掉了它。
您不能在分区名称中使用“表达式”
这是错误的:
ALTER TABLE schema.exampletab DROP PARTITION (concat(P,substr('20211011',1,6))
UPDATE INDEXES;
这是正确的:
ALTER TABLE schema.exampletab DROP PARTITION P20211011
UPDATE INDEXES;
您可以使用此代码动态删除分区。只需更新 header 中的 C_OWNER ,C_TABLE_NAME , C_PARTITION_TEMPLATE 。请注意 sql 命令是动态构建的,但是当它准备就绪时,分区名称已完全解析。
declare
C_OWNER varchar2(128) := 'MYOWNER';
C_TABLE_NAME varchar2(128) := 'MYTABLE';
C_PARTITION_TEMPLATE varchar2(128) := '2011';
cursor part_cur is
select *
from all_tab_partitions
where table_owner=C_OWNER and
table_name = C_TABLE_NAME and
partition_name like '%'||C_PARTITION_TEMPLATE||'%'
order by partition_position;
BEGIN
for part_rec in part_cur loop
execute immediate 'ALTER TABLE "'||part_rec.table_owner||'"."'||part_rec.table_name||'"'||
' DROP PARTITION ("'||part_rec.partition_name||'") UPDATE INDEXES';
end loop;
END;
/
您有两个选择,请考虑到您正在使用 sysdate
来了解您应该删除哪个分区。
选项 1 -> 动态 SQL 并且结果必须在查询之外执行
select ' alter table '||table_owner||'.'||table_name||' drop partition '||partition_name||' update indexes ; '
from
dba_Tab_partitions
where table_owner = 'your_schema'
and table_name = 'your_table'
and partition_name = 'P'||substr(to_char(sysdate,'yyyymmdd'),1,6) ; ;
此查询为您提供命令输出,但您需要执行它
alter table yourschema.yourtable drop partition P202110 update indexes;
我自己环境中的示例
SQL> select ' alter table '||table_owner||'.'||table_name||' drop partition '||partition_name||' update indexes ; '
from
dba_Tab_partitions
where table_owner = 'FDM_DATA'
and table_name = 'FDM_DIM_CUSTOMER'
and partition_name = 'P_'||substr(to_char(sysdate,'yyyymmdd'),1,6) ;
'ALTERTABLE'||TABLE_OWNER||'.'||TABLE_NAME||'DROPPARTITION'||PARTITION_NAME||'UP
--------------------------------------------------------------------------------
alter table FDM_DATA.FDM_DIM_CUSTOMER drop partition P_202110 update indexes ;
选项 2 -> PLSQL
更好的选择是使用 PLSQL
。一个小例子,当你只想删除一个基于当前 sysdate
的分区时。您可以扩展/修改此代码以涵盖任何类型的时间范围。
declare
v_owner varchar2(128) := 'YOUR_SCHEMA';
v_table_name varchar2(128) := 'YOUR_TABLE';
v_partition_name varchar2(128);
begin
select partition_name into v_partition_name from all_tab_partitions
where table_owner = v_owner and
table_name = v_table_name and
partition_name = 'P'||substr(to_char(sysdate,'yyyymmdd'),1,6) ;
execute immediate 'alter table '||v_owner||'.'||v_table_name||' drop partition '||v_partition_name||' update indexes' ;
exception
when no_data_found then null; -- if there is no partition, nothing to do and no error is raised
when others then raise;
end;
/