【问题标题】:difficulties creating a pl/sql procedure创建 pl/sql 过程的困难
【发布时间】:2019-07-09 13:40:03
【问题描述】:

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

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:遇到符号“。”预期以下情况之一时:;

【问题讨论】:

  • 您发布的代码没有36行,因此不清楚错误指的是什么。如果它是更大脚本的一部分,您是否真的在END 之后有一个尾随分号,以及合适的语句分隔符——比如单独一行的/——在这和你在脚本中做的下一件事之间?
  • 除非您打算创建“HK.PURGE_LAN_DOTS;”行以创建永无止境的递归过程需要删除。我相信您要查找的是“END PURGE_LAN_DOTS;(无模式名称)。进一步使用 TIMESTAMP 列名是极差的做法,因为该术语是 Oracle 定义的类型。虽然允许使用列名,但很难发现错误。

标签: oracle stored-procedures plsql mod-plsql


【解决方案1】:

可能只是错别字。这个版本应该可以工作(只要HK 可以访问LAN.DOTS)。

PL/SQL 脚本与独立 SQL 的处理方式不同,因为它们需要尾随分号以及新行上的正斜杠。

SQL*Plus 中的斜线与分号语义有点奇怪;这是另一个关于这个问题的问题: When do I need to use a semicolon vs a slash in Oracle SQL?

最后,当您可能打算使用 END PURGE_LAN_DOTS; 时,您在 END 语句之前包含了 HK.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;
/

【讨论】:

    【解决方案2】:

    您发布的代码末尾是这样的:

      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. 前缀 - 但是所有者将设置为 HK

    所以,END 应该只引用 PL/SQL 对象名称,并且不能有模式前缀:

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

    不相关,但是:

    deleteline timestamp := current_timestamp - 365;
    

    将导致 current_timestamp 值转换为减去 365 天的日期,然后将其转换回时间戳;这比必要的转换更多,并且丢失了小数秒。在这种情况下,您可能并不真正关心这一点,但有时它很重要。为了避免这两种情况,您可以执行以下任一操作:

    deleteline timestamp := current_timestamp - interval '365' day;
    deleteline timestamp := current_timestamp - 365 * interval '1' day;
    

    一旦您切换到一个间隔,您可能会想将其更改为 current_timestamp - interval '1' year,但如果您在 2 月 29 日运行它会出现 ORA-01839 错误...

    还要确保您确实需要current_timestamp 而不是systimestamp

    【讨论】:

      猜你喜欢
      • 2017-12-21
      • 1970-01-01
      • 2018-06-16
      • 2023-01-09
      • 2017-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多