创建pl / sql过程的困难

时间:2019-07-09 13:40:03

标签: oracle stored-procedures plsql mod-plsql

试图创建一个程序,但我不断收到错误消息。这是代码

create or replace procedure HK.PURGE_LAN_DOTS
AS
batchsize number := 15000;
deleteline timestamp := current_timestamp - 365;
counter number := 0;
BEGIN
  loop
    DELETE FROM LAN.DOTS
    WHERE rownum <= batchsize
    AND TIMESTAMP < deleteline;
    COMMIT;

    counter:=counter + SQL%rowcount;

    exit when batchsize > SQL%rowcount;

  end loop;
  HK.PURGE_LAN_DOTS;
END 

这是我得到的错误

  

错误(36,12):PLS-00103:遇到符号“。”当期望以下之一时:;

2 个答案:

答案 0 :(得分:1)

可能只是错别字。此版本应该有效(只要HK可以访问LAN.DOTS)。

PL / SQL脚本与独立SQL的区别在于,它们既需要尾随分号,又需要在新行上使用正斜杠。

SQL * Plus中的斜线vs.分号语义有点奇怪。这是另一个正好被问到的问题: When do I need to use a semicolon vs a slash in Oracle SQL?

最后,当您可能打算使用HK.PURGE_LAN_DOTS;时,在END语句之前包括了END PURGE_LAN_DOTS;。 请注意,您不能在该结束标记中包含模式名称,并且命名结束标记是完全可选的(您只能使用END;)。

create or replace procedure HK.PURGE_LAN_DOTS
AS
batchsize number := 15000;
deleteline timestamp := current_timestamp - 365;
counter number := 0;
BEGIN
  loop
    DELETE FROM LAN.DOTS
    WHERE rownum <= batchsize
    AND TIMESTAMP < deleteline;
    COMMIT;

    counter:=counter + SQL%rowcount;

    exit when batchsize > SQL%rowcount;

  end loop;

END PURGE_LAN_DOTS;
/

答案 1 :(得分:0)

您发布的代码末尾有以下内容:

  end loop;
  HK.PURGE_LAN_DOTS;
END 

END缺少分号;但是前一行调用 this 过程,这将导致无限递归(Oracle最终将终止该过程)。

我认为您在发布时损坏了此文件,而您实际上拥有:

  end loop;
END HK.PURGE_LAN_DOTS;

现在该错误是有道理的(尽管报告行和列的编号不太正确)。

尽管create语句具有可选的模式前缀:

create or replace procedure HK.PURGE_LAN_DOTS

匹配的END没有。整个语句可以被认为是SQL和PL / SQL的混合-达到的程度与触发器不同,但此处的效果相似。该语句确实做了很多事情-它在该模式下创建了一个名为PURGE_LAN_DOTS的过程类型对象,并使用相同的名称编译和存储了代码的PL / SQL部分。 HK.位不是对象名称的一部分,并且与PL / SQL引擎无关-END是纯PL / SQL。如果您查看all_source视图,将会看到存储的源将是PROCEDURE PURGE_LAN_DOTS AS ...,而没有create or replaceHK.前缀-所有者将被设置为{ {1}}。

因此,HK应该仅引用PL / SQL对象名称,并且不能具有架构前缀:

END

不相关,但是:

create or replace procedure HK.PURGE_LAN_DOTS
...
  end loop;
END PURGE_LAN_DOTS;

会将deleteline timestamp := current_timestamp - 365; 值转换为减去365天的日期,然后将其转换回时间戳;这比必要的转换要多,并且浪费了小数秒。在这种情况下,您可能并不十分在意,但有时很重要。为避免两者,您可以执行以下任一操作:

current_timestamp

一旦切换到间隔,您可能会尝试将其更改为deleteline timestamp := current_timestamp - interval '365' day; deleteline timestamp := current_timestamp - 365 * interval '1' day; ,但是如果您在2月29日运行它,ORA-01839将会出错...

还要确保您确实要current_timestamp - interval '1' year而不是current_timestamp