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

Posted

技术标签:

【中文标题】PLS-00306:调用“ADD_MONTHS”时参数的数量或类型错误【英文标题】:PLS-00306: wrong number or types of arguments in call to 'ADD_MONTHS' 【发布时间】:2019-02-23 03:09:33 【问题描述】:

我创建了以下程序,仅保留最近两个月的数据,并在 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):

【问题讨论】:

您的程序不接受任何参数。你怎么称呼它? 也许您需要从sysdate 获取月份,然后与ADD_MONTHS(cc.high_value,2) 进行比较? high_valueuser_tab_partitions 中的数据类型是什么? @Bohemian 插入 EXPORT_TABLE (PARTITION_NAME,LAST_ANALYZED,NUM_ROWS,BLOCKS,SAMPLE_SIZE,HIGH_VALUE) 值 ('JUL2018',to_date('22-FEB-19','DD-MON-RR') ,0,0,null,'TO_DATE('' 2018-08-01 00:00:00'', ''SYYYY-MM-DD HH24:MI:SS'', ''NLS_CALENDAR=GREGORIAN'')') ; @fkljfklgfjhkgbng 所以,high_value 是一个包含像'TO_DATE('' 2018-08-01 00:00:00'', ''SYYYY-MM-DD HH24:MI:SS'', ''NLS_CALENDAR=GREGORIAN'')' 这样的值的文本数据类型?更简单地说,您能告诉我们high_value 列的数据类型吗?例如它是varchar?其他人认为它是一种数字类型。你能澄清一下吗? 【参考方案1】:

首先,用TEST_TABLE来调用表名、包名和过程名是很疯狂的,就像你做的那样,好像没有其他可用的名字一样。我已经适当地命名了它们。

HIGH_VALUELONG TYPE,不能直接用在DATE相关函数中。有一个使用动态 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;
/

【讨论】:

谢谢我已经完成了程序,现在已经成功执行,请告知如何执行,请给调用查询 @fkljfklgfjhkgbng :请检查我的答案,如果您发现答案有用,请考虑使用accepting,这样它也可以帮助其他人。另请阅读this【参考方案2】:

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

【讨论】:

感谢您的请求,请您在我的上述程序中进行更改,以便它也应该采用这些参数 因为我不知道你想添加什么参数,也不是他们的目标,我不会。显然,看一下文档不会浪费时间。你可以在这里找到一个例子:docs.oracle.com/cd/B28359_01/appdev.111/b28370/…【参考方案3】:

来自 USER_TAB_PARTITIONS 的 HIGH_VALUE 列是一个长数据类型,我不会从另一个网站复制代码,但是如果你谷歌“oracle 将高值转换为日期”,你应该对如何创建一个函数有一些想法您可以使用将 'long' 转换为日期。

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

【讨论】:

【参考方案4】:

正如错误所说,所有 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     

【讨论】:

【参考方案5】:

Oracle 不允许使用 long 类型的函数,例如 cast、substr、add_months,但是……请阅读下文。

    长型

    描述 user_tab_partitions;

    ... SUBPARTITION_COUNT NUMBER HIGH_VALUE 长 HIGH_VALUE_LENGTH NUMBER ...

    将long转换为varchar2的函数

    FUNCTION long_to_varchar2 ( p_table_owner IN VARCHAR2, p_table_name IN VARCHAR2, p_partition_name IN VARCHAR2) RETURN 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 到日期的转换,我认为没有其他办法。

【讨论】:

以上是关于PLS-00306:调用“ADD_MONTHS”时参数的数量或类型错误的主要内容,如果未能解决你的问题,请参考以下文章

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

PLS-00306:调用 oracle 函数时参数的数量或类型错误

PLS-00306:调用过程 PROC_T 时参数的数量或类型错误

PLS-00306: 调用 'SYNCRN' 时参数个数或类型错误

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

ORA-06550:PLS-00306: 调用中的参数数量或类型错误;ORA-06550: