LONGデータ型のhigh_valueをDATEデータ型のsysdateと比較する必要があります。 90日経過したすべてのパーティションのパーティション名を取得する必要があります。コードはこのようなものです。
declare
dt date;
time_to_stay number:=1; --CONFIGURE AS PER THE REQUIREMENT
begin
for x in (select partition_name , high_value, partition_position
from user_tab_partitions
where table_name = 'DEMO')
loop
execute immediate 'select '||x.high_value||' from dual' into dt;
if to_date(dt) < sysdate-time_to_stay AND x.partition_position <>'1' then
execute immediate 'ALTER TABLE DEMO DROP PARTITION '|| x.partition_name|| ' UPDATE GLOBAL INDEXES';
このクエリは実行されますが、パーティションは削除されません。ただし、high_valueとsys_dateを比較するために、high_valueのLONGデータ型をDATEに変換することが主な問題であることがわかりました。
どうすれば修正できますか?
長い列の使用には多くの制限があり、操作が難しくなります。この問題を回避する1つの方法は、データをXML構造に変換することです。これを実行したら、XMLでXPATH式を使用してフィールド値を比較できます。
XMLへの変換は、次のようにdbms_xmlgen.getxmltype
をクエリとして文字列として渡すことで実行できます。
select dbms_xmlgen.getxmltype('
select p.table_owner,
p.table_name,
p.high_value
from all_part_key_columns k,
all_tab_cols c,
all_tab_partitions p
where k.owner = c.owner
and k.column_name = c.column_name
and k.name = c.table_name
and k.owner = p.table_owner
and k.name = p.table_name
and (c.data_type = ''DATE'' or
c.data_type like ''TIMESTAMP%'')') as xml
from dual;
これにより、次のようなデータが得られます。
<ROWSET>
<ROW>
<TABLE_OWNER>TABLE_OWNER</TABLE_OWNER>
<TABLE_NAME>TABLE</TABLE_NAME>
<HIGH_VALUE>TIMESTAMP' 2013-02-06 00:00:00'</HIGH_VALUE>
</ROW>
</ROWSET>
次に、high_value
の日付/タイムスタンプを実際の日付に解析できます。これを行ったら、それを実際の日付との比較に使用して、影響を受けるパーティションのリストを返すことができます。
with date_partitions as
(select dbms_xmlgen.getxmltype('
select p.table_owner,
p.table_name,
p.high_value
from all_part_key_columns k,
all_tab_cols c,
all_tab_partitions p
where k.owner = c.owner
and k.column_name = c.column_name
and k.name = c.table_name
and k.owner = p.table_owner
and k.name = p.table_name
and (c.data_type = ''DATE'' or
c.data_type like ''TIMESTAMP%'')')
as xml
from dual)
SELECT x.*
FROM date_partitions p,
xmltable('/ROWSET/ROW'
passing p.xml
columns table_owner varchar2(30)
path '/ROW/TABLE_OWNER',
table_name varchar2(30)
path '/ROW/TABLE_NAME',
high_value varchar2(30)
path '/ROW/HIGH_VALUE'
) x
where to_date(substr(x.high_value,
instr(high_value, '''')+2,
19),
'yyyy-mm-dd hh24:mi:ss') <= sysdate-90
これには別の解決策があると思います。
DECLARE
CURSOR c1 IS
SELECT
HIGH_VALUE
FROM
USER_TAB_PARTITIONS
WHERE
TABLE_NAME = 'MYTAB';
ls_sql_statement VARCHAR2(1000);
ld_date_val DATE;
BEGIN
FOR c1rec IN c1 LOOP
ls_sql_statement := 'SELECT '||c1rec.HIGH_VALUE||' FROM DUAL';
EXECUTE IMMEDIATE ls_sql_statement INTO ld_date_val;
--Do more stuff here with ld_date_val
END LOOP;
END;
/