Ten eerste kun je geen functie aanroepen met DML daarin in een select statement. Je moet de output toewijzen aan een variabele in een PL/SQL-blok, zoiets als:
declare
l_output number;
begin
l_output := my_function(variable1, variable2);
end;
Het is een slechte gewoonte om DML in een functie te doen; deels omdat het de fouten veroorzaakt die je tegenkomt. U moet een procedure gebruiken zoals hieronder beschreven. De andere reden hiervoor is dat je zoals altijd null retourneert, het is helemaal niet nodig om iets te retourneren!
create or replace procedure my_procedure ( <variables> ) is
begin
insert into employees( <columns> )
values ( <values > );
end;
De specifieke reden voor je fout is deze regel:tBirthdate := to_date('pBirthdate','dd/mm/yyyy');
pBirthdate
is al een string; door een '
. te plaatsen daaromheen geef je de string 'pBirthdate'
. door naar de functie to_date
en Oracle kan deze string niet omzetten in een dag, maand of jaar, dus het mislukt.
Je moet dit schrijven als:tBirthdate := to_date(pBirthdate,'dd/mm/yyyy');
U hoeft ook geen number(38,0)
op te geven , je kunt gewoon number
schrijven in plaats daarvan.
Het is mogelijk om een waarde uit een procedure terug te geven met behulp van de out
trefwoord. Als we aannemen dat je empid
wilt retourneren je zou kunnen schrijven is zoiets als dit:
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;
Om de procedure gewoon uit te voeren, roept u het als volgt aan:
begin
A1SF_ADDEMP( EmpName, TaxFileNo, Gender
, Salary, Birthdate);
commit;
end;
Als u de empid
. wilt retourneren dan kun je het zo noemen:
declare
l_empid number;
begin
l_empid := A1SF_ADDEMP( EmpName, TaxFileNo, Gender
, Salary, Birthdate);
commit;
end;
Merk op hoe ik de commit
. heb verplaatst op het hoogste niveau, dit is om te voorkomen dat u dingen vastlegt in elke procedure wanneer u mogelijk meer dingen moet doen.
Overigens, als u Oracle 11g gebruikt, hoeft u de waarde A1Seq_Emp.nextval
niet toe te wijzen naar een variabele. Je kunt het gewoon rechtstreeks in de tabel invoegen in de values
lijst. U kunt het natuurlijk niet retourneren, maar u kunt A1Seq_Emp.curval
, zolang er niets anders waarden uit de reeks haalt.