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