2013-03-08 6 views
0

У меня есть некоторый SQL код для заполнения базы данных, которая работает просто отлично:Процедура вызова внутри блока в PL/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); 

Для повышения ремонтопригодности, я пытаюсь заменить некоторые магические числа с переменными. Я никогда не использовал переменные раньше, но я прочитал мне нужно использовать/SQL блок PL так:

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: найден 'строка', но ожидалось одно из следующих действий: 'строка'

Если изменить вызов:

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: нет функции с именем «строка» существует в этой области

Мои вопросы:

  1. Я использую переменные правильно или есть лучшее решение для моей первоначальной цели?
  2. Что мне нужно исправить в синтаксисе процедуры вызова и почему?
+1

'execute immediately' нуждается в строке:' EXECUTE IMMEDIATE 'RESET_SEQUENCE (' 'DOCUMENT_ELEMENT_ID_SEQ' ', 4)' '; –

+0

Спасибо всем. Я собрал всю информацию в новый ответ и принял ответ, который дал мне ключ. –

ответ

1
  1. ИМО, было бы лучше, если бы вы имели процедуры с 3 параметрами, где вы бы 1 вставить ... и затем использовать эту процедуру для вставки. Таким образом, вы можете добавить обработку исключений, и если что-то случится, вы бы это знали.

  2. Попробуйте удалить EXECUTE при использовании блочной версии вашего кода. Я не думаю, что вам это нужно :)

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'; 
+0

Такая таблица уже существует. Но это довольно запутанный способ выполнить серию вставок, не так ли? xD –

+0

Если цель состоит в том, чтобы избежать возможности ошибки с помощью магических чисел в коде, тогда определение их как переменных не решает проблему. Понятно, что код может заполнить переменные, запросив базу данных, а затем использовать переменные в другом месте. –

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); 
    

Моя проблема заключалась в том, что я делал команду SQL * Plus внутри блока PL/SQL.

(По состоянию на EXECUTE IMMEDIATE, это PL/SQL command запустить динамически сгенерированный оператор SQL или анонимный/SQL блок PL. Он ожидает строку и не имеет ничего общего с этим вопросом. Oracle только предложил, потому что его имя напоминает SQL * Плюс команда.)