我正在编写下面的存储过程,但是在oracle中编译过程时也遇到了异常,下面是过程
CREATE OR REPLACE PACKAGE BODY TEST_TABLE AS
PROCEDURE TEST_TABLE
--This procedure will delete partitions for the following tables:
--TEST_TABLE
BEGIN
FOR cc IN
(
SELECT partition_name, high_value
FROM user_tab_partitions
WHERE table_name = 'TEST_TABLE'
)
LOOP
EXECUTE IMMEDIATE 'BEGIN
IF sysdate >= ADD_MONTHS(' || cc.high_value || ', 3) THEN
EXECUTE IMMEDIATE
''ALTER TABLE TEST_TABLE DROP PARTITION ' || cc.partition_name || '
'';
END IF;
dbms_output.put_line('drop partition completed');
END;';
END LOOP;
exception
when others then
dbms_output.put_line(SQLERRM);
END;
END;
/
我在编译时遇到的一个例外是,请提出如何克服这一点的建议。
Error(7,1): PLS-00103: Encountered the symbol "BEGIN" when expecting one of the following: ( ; is with authid as cluster order using external deterministic parallel_enable pipelined result_cache The symbol ";" was substituted for "BEGIN" to continue.
Error(22,25): PLS-00103: Encountered the symbol "DROP" when expecting one of the following: * & = - + ; < / > at in is mod remainder not rem return returning <an exponent (**)> <> or != or ~= >= <= <> and or like like2 like4 likec between into using || bulk member submultiset
答案 0 :(得分:2)
第一条错误消息告诉您BEGIN
之前缺少某些内容,甚至还提到了“何时”列表中的两个可能选项。您需要将其更改为:
PROCEDURE TEST_TABLE IS
-- ^^
或者,如果您愿意...,也可以使用AS
代替IS
。
第二个错误是因为您在动态SQL中嵌入了字符串文字,尽管在其他地方也没有转义单引号:
...
dbms_output.put_line(''drop partition completed'');
-- ^ ^
END;';
您可以改用alternative quoting mechanism。
我不确定为什么要执行两个级别的动态SQL。您可以执行dbms_output()
并静态评估cc.high_value
,并决定是否仅使该部分为动态(如@BarbarosÖzhan所示,因此不重复!),以使alter call
。或在游标查询中进行高价值检查。
我仍然收到异常错误(1,14):PLS-00304:如果没有说明,就无法编译“ TEST_TABLE”的正文
如果要使用包,则必须先创建其规格,然后再尝试创建其主体:
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
...
LOOP
...
END LOOP;
END TEST_TABLE; -- end of procedure
END TEST_TABLE; -- end of package
/
包名称与其中的过程相同,有点奇怪和混乱。
但是也许您实际上根本不需要包,而是试图创建一个独立的过程,在这种情况下,只需删除package-body部分:
CREATE OR REPLACE PROCEDURE TEST_TABLE AS
BEGIN
FOR cc IN
...
LOOP
...
END LOOP;
END TEST_TABLE; -- end of procedure
/
我强烈建议您摆脱异常处理程序,而将其排除在大纲之外-您应该让任何异常流回到调用方。您不知道谁叫它甚至都启用了输出,因此很可能甚至看不到您要打印的消息。届时只有您可以处理和需要处理的异常。
答案 1 :(得分:2)
您需要在下面加上正确的引号(并在is
之后加上一个PROCEDURE TEST_TABLE
关键字“ 感谢Alex使我醒来”):
CREATE OR REPLACE PACKAGE BODY PKG_TEST_TABLE IS
PROCEDURE TEST_TABLE IS
--This procedure will delete partitions for the following tables:
--TEST_TABLE
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, 3) 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 PKG_TEST_TABLE;
/
有一点建议,对于软件包,请使用与PKG_TEST_TABLE
之类的过程不同的名称,以防混淆。
编辑:当然,您需要在包装的主体部分之前为包装创建一个规格部分:
CREATE OR REPLACE PACKAGE PKG_TEST_TABLE IS
PROCEDURE TEST_TABLE;
END PKG_TEST_TABLE;
/