在PL / SQL块内部调用过程

时间:2013-03-08 09:40:54

标签: oracle plsql oracle-xe

我有一些SQL代码来填充数据库,这很好用:

INSERT INTO PDF_DOCUMENT_ELEMENT (DOCUMENT_ELEMENT_ID, DOCUMENT_ID, ELEMENT_ID) VALUES (1, 1, 1);
INSERT INTO PDF_DOCUMENT_ELEMENT (DOCUMENT_ELEMENT_ID, DOCUMENT_ID, ELEMENT_ID) VALUES (2, 1, 1);
INSERT INTO PDF_DOCUMENT_ELEMENT (DOCUMENT_ELEMENT_ID, DOCUMENT_ID, ELEMENT_ID) VALUES (3, 1, 2);

EXECUTE RESET_SEQUENCE('DOCUMENT_ELEMENT_ID_SEQ', 4);

为了增强可维护性,我试图用变量替换一些幻数。我之前从未使用过变量,但我读过我需要使用PL / SQL块,所以:

DECLARE
    ELEMENT_TEXT SMALLINT := 1;
    ELEMENT_IMAGE SMALLINT := 2;
BEGIN

INSERT INTO PDF_DOCUMENT_ELEMENT (DOCUMENT_ELEMENT_ID, DOCUMENT_ID, ELEMENT_ID) VALUES (1, 1, ELEMENT_TEXT);
INSERT INTO PDF_DOCUMENT_ELEMENT (DOCUMENT_ELEMENT_ID, DOCUMENT_ID, ELEMENT_ID) VALUES (2, 1, ELEMENT_TEXT);
INSERT INTO PDF_DOCUMENT_ELEMENT (DOCUMENT_ELEMENT_ID, DOCUMENT_ID, ELEMENT_ID) VALUES (3, 1, ELEMENT_IMAGE);

EXECUTE RESET_SEQUENCE('DOCUMENT_ELEMENT_ID_SEQ', 4);

END;
/

除了过程调用之外,这个工作正常:

EXECUTE RESET_SEQUENCE('DOCUMENT_ELEMENT_ID_SEQ', 4);
           *
ERROR en lÝnea 45:
ORA-06550: lÝnea 45, columna 9:
PLS-00103: Se ha encontrado el sÝmbolo "RESET_SEQUENCE" cuando se esperaba uno
de los siguientes:
:= . ( @ % ; immediate
El sÝmbolo ":=" ha sido sustituido por "RESET_SEQUENCE" para continuar.

PLS-00103错误转换为:

  

PLS-00103:找到'string',但期望以下之一:'string'

如果我将通话更改为:

EXECUTE IMMEDIATE RESET_SEQUENCE('DOCUMENTO_ELEMENTO_ID_SEQ', 4);

......我明白了:

PLS-00222: en este ßmbito no existe ninguna funci¾n cuyo nombre sea
'RESET_SEQUENCE'
ORA-06550: lÝnea 45, columna 1:
PL/SQL: Statement ignored

......翻译为:

  

PLS-00222:此范围内不存在名称为'string'的函数

我的问题是:

  1. 我是否正确使用变量,或者我的初始目标有更好的解决方案?
  2. 我需要在程序调用语法中修复什么以及为什么?

3 个答案:

答案 0 :(得分:1)

  1. IMO,如果您有一个包含3个参数的过程会更好,您将有1个插入...然后使用该过程进行插入。这样你就可以添加异常处理,如果发生了什么事,你就会知道。

  2. 尝试使用代码的块版本时删除EXECUTE。我认为你不需要它:)

答案 1 :(得分:1)

过程调用不是纯SQL,而是PL / SQL。因此,您需要从PL / SQL上下文运行它。选项包括:

  • 创建一个PL / SQL块并直接调用该过程:

    BEGIN
        RESET_SEQUENCE('DOCUMENT_ELEMENT_ID_SEQ', 4);
    END;
    /
    
  • 如果您使用的是SQL * Plus,则可以使用EXECUTE internal command

    EXECUTE RESET_SEQUENCE('DOCUMENT_ELEMENT_ID_SEQ', 4);
    

我的问题是我在PL / SQL块中发出了一个SQL * Plus命令。

(从EXECUTE IMMEDIATE开始,运行动态生成的SQL语句或匿名PL / SQL块是PL/SQL command。它需要一个字符串,与此问题无关.Oracle仅建议它,因为它的名称类似于SQL * Plus命令。)

答案 2 :(得分:0)

如果最初的目标是避免使用幻数,那么解决方案是使用具有这些数字含义的表格并引用它。

所以......

 create table element (
   element_id   integer primary key,
   element_name varchar2(30) not null unique);

 insert into element values (1,'Text');
 insert into element values (2,'Image');

 INSERT INTO PDF_DOCUMENT_ELEMENT (DOCUMENT_ELEMENT_ID, DOCUMENT_ID, ELEMENT_ID)
 Select 1, 1, element_id
 from   elements
 where  element_name = 'Text';

 INSERT INTO PDF_DOCUMENT_ELEMENT (DOCUMENT_ELEMENT_ID, DOCUMENT_ID, ELEMENT_ID)
 Select 1, 1, element_id
 from   elements
 where  element_name = 'Text';

 INSERT INTO PDF_DOCUMENT_ELEMENT (DOCUMENT_ELEMENT_ID, DOCUMENT_ID, ELEMENT_ID)
 Select 1, 1, element_id
 from   elements
 where  element_name = 'Image';