Първо, не можете да извикате функция с 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
, стига нищо друго да не получава стойности от последователността.