Хранимая функция в Oracle не вставляет значения в нужную таблицу - PullRequest
0 голосов
/ 24 марта 2012

Вот мой код, приведенный ниже. Я пытаюсь добавить 5 параметров, которые функция принимает в таблицу Employee. Но мне не удается это сделать, и я много чего пробовал.

Error

ORA-01858: был найден нечисловой символ, где числовой ожидается ORA-06512: в "xxxxxxx.A1SF_ADDEMP", строка 14 01858. 00000 - «не числовой символ был найден там, где ожидалось число» * Причина: входные данные для преобразования с использованием модели формата даты были неверен. Входные данные не содержат числа, где число было требуется модель формата. * Действие: исправьте входные данные или модель формата даты, чтобы убедиться, что элементы совпадают по количеству и типу. Затем повторите операцию.

Кроме того, как мне проверить сохраненную функцию, в которой есть оператор вставки / обновления или удаления?

Отчет о выполнении

Select A1SF_ADDEMP('Adesh', '33', 'M', 8000, '26/03/1990')
From dual;

Код

CREATE OR REPLACE Function A1SF_ADDEMP
        (pEmpName In Varchar2,
        pTaxFileNo In Varchar2,
        pGender In Varchar2,
        pSalary In Number,
        pBirthdate In Varchar2
        ) Return Varchar2
        Is
          tEmpId Number(38,0);
          tBirthDate Date;

        BEGIN
              tEmpId := A1Seq_Emp.nextval;
              tBirthdate := to_date('pBirthdate','dd/mm/yyyy');

               Insert Into Employee(EmpId, EmpName, TaxFileNo, Gender, Salary, Birthdate)
                Values (tEmpId, pEmpName, pTaxFileNo, pGender, pSalary, tBirthdate);                 
                Commit;
                Return null;
        END;

Ответы [ 3 ]

1 голос
/ 24 марта 2012

Во-первых, вы не можете вызвать функцию с DML в операторе выбора. Вы должны назначить вывод переменной в блоке PL / SQL, что-то вроде:

declare
  l_output number;
begin
  l_output := my_function(variable1, variable2);
end;

Это плохая практика - использовать DML в функции; частично потому что это вызывает ошибки, с которыми вы сталкиваетесь. Вы должны использовать процедуру, описанную ниже. Другая причина этого в том, что вы как всегда возвращаете null, и вам вообще не нужно ничего возвращать!

create or replace procedure my_procedure ( <variables> ) is
begin

   insert into employees( <columns> )
   values ( <values > );

end;

Конкретная причина вашей ошибки - эта строка:
tBirthdate := to_date('pBirthdate','dd/mm/yyyy');

pBirthdate уже является строкой; поместив вокруг него ', вы передаете строку 'pBirthdate' функции to_date, и Oracle не может преобразовать эту строку в день, месяц или год, поэтому она не работает.

Вы должны написать это как:
tBirthdate := to_date(pBirthdate,'dd/mm/yyyy');

Вам также не нужно указывать number(38,0), вы можете просто написать number.

Можно вернуть значение из процедуры, используя ключевое слово out. Если мы предполагаем, что вы хотите вернуть empid, вы можете написать что-то вроде этого:

create or replace procedure A1SF_ADDEMP (
          pEmpName in varchar2
        , pTaxFileNo in varchar2
        , pGender in varchar2
        , pSalary in number
        , pBirthdate in varchar2
        , pEmpid out number
          ) return varchar2 is

begin

   pempid := A1Seq_Emp.nextval;

   Insert Into Employee(EmpId, EmpName, TaxFileNo, Gender, Salary, Birthdate)
   Values ( pEmpId, pEmpName, pTaxFileNo, pGender
          , pSalary, to_date(pBirthdate,'dd/mm/yyyy');     

end;

Чтобы просто выполнить процедуру, вызовите ее так:

begin

    A1SF_ADDEMP( EmpName, TaxFileNo, Gender
               , Salary, Birthdate);
    commit;

end;

Если вы хотите вернуть empid, вы можете назвать его так:

declare

   l_empid number;

begin

   l_empid := A1SF_ADDEMP( EmpName, TaxFileNo, Gender
                         , Salary, Birthdate);
   commit;
end;

Обратите внимание на то, как я переместил commit на самый высокий уровень, чтобы избежать фиксации вещей в каждой процедуре, когда у вас может быть больше вещей, которые вам нужно сделать.

Кстати, если вы используете Oracle 11g, тогда нет необходимости присваивать значение A1Seq_Emp.nextval переменной. Вы можете просто вставить его прямо в таблицу в списке values. Вы, конечно, не сможете его вернуть, но вы можете вернуть A1Seq_Emp.curval, если больше ничего не получит значения из последовательности.

1 голос
/ 24 марта 2012

Вы должны использовать процедуру (вместо функции), если вы не возвращаете никаких значений.

Если вы посмотрите на строку, упомянутую в сообщении об ошибке, вы можете обнаружить свою ошибку:

tBirthdate := to_date('pBirthdate','dd/mm/yyyy');

Вы передаете строковый литерал 'pBirthdate' to_date() вызов.Но вы хотите передать параметр, поэтому он должен быть

tBirthdate := to_date(pBirthdate,'dd/mm/yyyy');

(обратите внимание на пропущенные одинарные кавычки во время pBirthdate).

Таким образом, как процедура все это будет выглядеть так:

CREATE OR REPLACE PROCEDURE A1SF_ADDEMP
        (pEmpName In Varchar2,
        pTaxFileNo In Varchar2,
        pGender In Varchar2,
        pSalary In Number,
        pBirthdate In Varchar2
        )
IS 
BEGIN
   Insert Into Employee(EmpId, EmpName, TaxFileNo, Gender, Salary, Birthdate)
   Values (A1Seq_Emp.nextval, pEmpName, pTaxFileNo, pGender, pSalary, to_date(pBirthdate,'dd/mm/yyyy'));
   Commit;

END;

Для запуска:

execute A1SF_ADDEMP('Adesh', '33', 'M', 8000, '26/03/1990');
0 голосов
/ 10 сентября 2015

В вашей ситуации вам нужно использовать процедуру с параметром out, где вашим параметром out является ваш возвращаемый параметр, который содержит желаемое значение. Это, я думаю, лучшая практика в этой ситуации, когда вы хотите использовать DML в операторе выбора.

Второй способ сделать это, но это не очень хорошая практика, это использовать одну функцию, подобную вашей, но перед возвратом значения вам нужно использовать оператор if, чтобы проверить, каково значение, и если значение - это то, что вы хотите вызвать в этом, если процедура PRAGMA AUTONOMOUS_TRANSACTION, которая будет выполнять ваш DML независимо от вызова функции. Более подробную информацию о прагматических транзакциях вы можете прочитать здесь: http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/autonotransaction_pragma.htm

С наилучшими пожеланиями и надеюсь, что я был полезным

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...