web-dev-qa-db-ja.com

high_valueから日付データ型への変換

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に変換することが主な問題であることがわかりました。

どうすれば修正できますか?

2
Rajesh

長い列の使用には多くの制限があり、操作が難しくなります。この問題を回避する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
3
Chris Saxon

これには別の解決策があると思います。

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;
/
6
guls