【问题标题】:PL/SQL: Error when creating sequencePL/SQL:创建序列时出错
【发布时间】:2012-07-03 19:26:18
【问题描述】:

相当是 PL/SQL 的新手,并且正在使用 Oracle SQL Developer 编写一个过程,该过程使用序列为一些现有数据生成主键,以写入另一个数据库。

有问题的代码在 NDA 下。基本上我有以下内容:

create or replace
PROCEDURE Generate_Data
(
   output IN VARCHAR2
) 
AS

-- Variables here --

CURSOR myCursor IS
SELECT data1, data2 
FROM table;

CREATE SEQUENCE mySequence      <-- error on this line
START WITH 0
INCREMENT BY 1;

BEGIN
LOOP
    -- snip --

它引发错误 PLS-00103,说它在预期以下内容时遇到了符号 CREATE:开始、函数、包、编译指示、过程...

我一直在关注以下示例: http://www.techonthenet.com/oracle/sequences.php

【问题讨论】:

    标签: oracle plsql pls-00103


    【解决方案1】:

    您收到此错误的原因是您正在尝试执行DDL,在本例中是在 PL/SQL 中创建一个序列。可以这样做,但您必须使用execute immediate

    正如Alex 所说,您也无法在declare 部分执行此操作。它看起来像这样:

    begin
    
       execute immediate 'CREATE SEQUENCE mySequence
                              START WITH 0
                              INCREMENT BY 1';    
    end;
    

    然而,正如Padmarag 所说,您不太可能希望在 PL/SQL 中执行此操作。在外面创建一个序列然后再引用它会更正常。更一般地说,在 PL/SQL 块中执行 DDL 是个坏主意。你应该没有必要这样做。

    您没有提及您使用的是哪个版本的 Oracle。从 11g 开始,您访问序列的方式得到了扩展。如果您使用的是 11g,那么您可以通过创建一个变量并将序列中的下一个值 .nextval 分配给该变量来访问该序列:

    declare    
       l_seq number;    
    begin
    
       loop
          -- For each loop l_seq will be incremented.
          l_seq := mysequence.nextval;
       -- snip    
    end;
    

    如果您在 11g 之前,则必须(在DML 之外)使用 select 语句才能获得下一个值:

    declare
       l_seq number;
    begin
    
       loop
          -- For each loop l_seq will be incremented.
          select mysequence.nextval into l_seq from dual;
       -- snip    
    end;
    

    请记住,序列是数据库中的持久对象。每次您想使用它时,无需删除并重新创建它。如果你要运行你的脚本,然后重新运行它,序列会很高兴地不断增加返回值。

    进一步阅读

    【讨论】:

    • 我已经修改了它以匹配你的第二种方法,因为我很确定我们在 11g 之前。它说序列(我在立即执行中创建)不存在。您对为什么会这样有任何想法吗?
    • 这可能是因为您在代码中引用了序列。当您在块中创建对象时,您必须将对该对象的每个 引用也包含在execute immediate 中。有什么理由不能在块外创建序列吗?
    • 我对编写程序真的很陌生。我不知道如何把这样的东西放在我正在处理的文件之外。
    • 那你不使用图形用户界面吗?您应该能够执行它。您可以创建第二个文件并直接执行吗?
    • 我正在使用 SQL 开发人员。我只在“程序”下拉列表中打开了一个程序,其中包含这件事的所有代码。
    【解决方案2】:

    您不能在 DECLARE 程序块中创建序列。在 BEGIN 之后移动它。不过,如果它有意义,这是有争议的。您可能首先需要在您的过程之外创建它。


    更新

    实际上,如果你真的想在 BEGIN/END 中使用它:

    EXECUTE IMMEDIATE 'CREATE SEQUENCE mySequence  START WITH 0 INCREMENT BY 1'; 
    

    【讨论】:

    • 我尝试在 BEGIN 之后移动它,但它仍然给出了同样的错误。我会考虑把它移到程序之外。
    • 我添加了更新。你不能直接使用CREATE。必须使用EXECUTE IMMEDIATE,尽管它的用处仍然值得商榷。
    • 我会试试的。既然我还在学习,你介意告诉我这是做什么的吗?
    • 是的。这是一种使用动态 SQL 的方法。也就是说,您可以构造一个 SQL 字符串并就地执行它。尽量减少代码中的此类内容。 DDL 不能直接在 PL/SQL 中使用。
    【解决方案3】:

    您需要在使用前创建序列。

    在 PL/SQL 代码中使用
    -- Variables here --1
    v_seq_val number;

    BEGIN
    Select mySequence.nextval from dual into v_seq_val

    一般来说,SQL 用于 DDL(数据定义语言),PL/SQL 用于 DML(数据操作语言)和逻辑。

    如果你愿意,你可以从 PL/SQL 创建,但我认为这不是你想要的。

    【讨论】:

    • 我在循环中使用序列,基本上是输出到INSERT语句中,所以我以为是我在使用之前创建的?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-16
    相关资源
    最近更新 更多