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_value
在user_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_VALUE
是LONG
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:调用 oracle 函数时参数的数量或类型错误
PLS-00306:调用过程 PROC_T 时参数的数量或类型错误