PLS-00306:“ ADD_MONTHS”调用中参数的数量或类型错误

时间:2019-02-23 03:09:33

标签: oracle plsql

我创建了以下过程,仅保留了最近两个月的数据,并针对oracle中的表删除了其余的数据,下面是该过程,但是我遇到了异常,请建议如何克服这一点

create or replace package TEST_TABLE AS
   PROCEDURE TEST_TABLE;
END TEST_TABLE;


create or replace PACKAGE BODY TEST_TABLE AS 
 PROCEDURE TEST_TABLE IS        
 BEGIN
  FOR cc IN
  (
  SELECT partition_name, high_value
  FROM user_tab_partitions
  WHERE table_name = 'TEST_TABLE'
  )    
  LOOP
   BEGIN               
     IF sysdate >= ADD_MONTHS(cc.high_value,2) THEN                  
      EXECUTE IMMEDIATE                     
      'ALTER TABLE TEST_TABLE DROP PARTITION ' || cc.partition_name;                   
       Dbms_Output.Put_Line('Dropping partition is completed.');        
     END IF;
   END;
  END LOOP;

  EXCEPTION WHEN Others THEN Dbms_Output.Put_Line( SQLERRM );

 END TEST_TABLE;

END TEST_TABLE; 

我得到的错误是:

  

错误(12,6):PL / SQL:语句已忽略
  错误(12,20):PLS-00306:调用“ ADD_MONTHS”时参数的数量或类型错误

5 个答案:

答案 0 :(得分:2)

首先,像您没有其他名称一样,用TEST_TABLE来调用表名,包名和过程名都是很疯狂的。我已经给它们起了适当的名字。

HIGH_VALUE不能直接用于DATE类型的LONG相关功能中。有一种简单的方法可以使用动态SQL(EXECUTE IMMEDIATE)将其转换为日期

CREATE OR replace PACKAGE BODY PKG_test_table AS
     PROCEDURE pr_test_table
          IS
          v_high_value DATE;
     BEGIN
          FOR cc IN (
               SELECT partition_name,
                      high_value
               FROM user_tab_partitions
               WHERE table_name = 'TEST_TABLE'
          ) LOOP
               BEGIN
             EXECUTE IMMEDIATE 'BEGIN :v_high_val := '|| cc.high_value || '; END;' 
                           USING OUT v_high_value;
                    IF
                         SYSDATE >= add_months(v_high_value,2)
                    THEN
                         EXECUTE IMMEDIATE 'ALTER TABLE TEST_TABLE DROP PARTITION ' 
           || cc.partition_name;
                         dbms_output.put_line('Dropping partition is completed.');
                    END IF;
               END;
          END LOOP;
     EXCEPTION
          WHEN OTHERS THEN
               dbms_output.put_line(sqlerrm);
     END pr_TEST_TABLE;
END PKG_test_table;
/

调用过程

BEGIN 
 PKG_test_table.pr_test_table; 
END;
/

答案 1 :(得分:0)

您的过程不接受任何参数。您不能向其传递任何参数。

答案 2 :(得分:0)

USER_TAB_PARTITIONS中的HIGH_VALUE列是一个长数据类型,我不会从另一个网站复制代码,但是如果您使用google“ oracle将高价值转换为日期”,则应该了解如何创建一个函数来您可以用来将“长”转换为日期。

我的声誉太低,无法将其发布为评论,因此我将其添加为答案,尽管它不是一个好的答案,它应该有所帮助:(

答案 3 :(得分:0)

正如错误所述,所有ADD_MONTHS都需要一个DATE,而您是以LONG身份传递的。

尝试类似的方法,应该没问题。

示例:

DECLARE
DT LONG(1000) := 'TO_DATE('||''''||'2018-08-01 00:00:00'||''''||',' ||''''|| 'SYYYY-MM-DD HH24:MI:SS'||''''||','||''''||'NLS_CALENDAR=GREGORIAN'||''''||')';
BEGIN
DBMS_OUTPUT.PUT_LINE(DT);
EXECUTE IMMEDIATE
             'BEGIN
                 DBMS_OUTPUT.PUT_LINE(TO_CHAR(ADD_MONTHS('||DT||',2),'||''''||'YYYY-MM-DD HH24:MI:SS'||''''||
              ')); END;';

END;

输出:

TO_DATE('2018-08-01 00:00:00','SYYYY-MM-DD HH24:MI:SS','NLS_CALENDAR=GREGORIAN')
2018-10-01 00:00:00     

答案 4 :(得分:0)

Oracle不允许长时间使用诸如cast,substr,add_months之类的函数,但是…请阅读下文。

  1. 长型

    描述user_tab_partitions;

    ... SUBPARTITION_COUNT个NUMBER
    HIGH_VALUE LONG
    HIGH_VALUE_LENGTH NUMBER
    ...

  2. 将long转换为varchar2的函数

    FUNCTION long_to_varchar2(p_table_owner输入VARCHAR2,p_table_name输入VARCHAR2,p_partition_name输入VARCHAR2)返回VARCHAR2 是 l_tmp长; 开始

    选择高值 进入l_tmp 来自all_tab_partitions 其中table_owner = p_table_owner 和table_name = p_table_name 和partition_name = p_partition_name;

    返回l_tmp; END long_to_varchar2;

3。使用新功能

select tpar."OWNER",tpar."TABLE_NAME",tpar."PART_MIN",tpar."PART_MIN_HV",tpar."PART_MAX",tpar."PART_MAX_HV",tpar."NR_PART"
      ,pkey.column_name as partitioned_by
      ,ptab.partitioning_type as partition_type
      ,ptab.status  
from        
      (select p1.table_owner     as owner
             ,p1.table_name 
             ,pmin.partition_name as part_min
             ,to_date(substr(long_to_varchar2(p1.table_owner,p1.table_name,pmin.partition_name),11,10),'yyyy-mm-dd') as part_min_hv
             ,pmax.partition_name as part_max
             ,to_date(substr(long_to_varchar2(p1.table_owner,p1.table_name,pmax.partition_name),11,10),'yyyy-mm-dd') as part_max_hv
             ,p1.nr_part+1        as nr_part
       from (select min(part.partition_position) as minp
                   ,max(part.partition_position) as maxp
                   ,count(*)                     as nr_part
                   ,part.table_name
                   ,part.table_owner
             from all_tab_partitions part,
                  dba_tables tbls
             where part.table_name=tbls.table_name
             and part.table_owner=tbls.owner
             and part.PARTITION_NAME <> 'P_CURRENT'
             group by part.table_name, part.table_owner) p1
            ,all_tab_partitions pmin
            ,all_tab_partitions pmax
       where p1.table_name = pmin.table_name
       and p1.table_owner = pmin.table_owner
       and p1.minp=pmin.partition_position
       and p1.table_name = pmax.table_name
       and p1.table_owner = pmax.table_owner
       and p1.maxp = pmax.partition_position) tpar
     ,ALL_PART_KEY_COLUMNS pkey
     ,ALL_PART_TABLES      ptab
where tpar.owner=pkey.owner
and tpar.table_name=pkey.name
and tpar.owner=ptab.owner
and tpar.table_name=ptab.table_name
and pkey.object_type='TABLE';

唯一的问题是您将执行隐式varchar2到日期的转换,否则我看不到任何方法。