For det første kan du ikke kalde en funktion med DML i det i en udvalgt erklæring. Du skal tildele outputtet til en variabel i en PL/SQL-blok, noget som:
declare
l_output number;
begin
l_output := my_function(variable1, variable2);
end;
Det er dårlig praksis at lave DML i en funktion; dels fordi det forårsager de fejl, du støder på. Du bør bruge en procedure som beskrevet nedenfor. Den anden grund til dette er, at du som altid returnerer null, der er ingen grund til at returnere noget overhovedet!
create or replace procedure my_procedure ( <variables> ) is
begin
insert into employees( <columns> )
values ( <values > );
end;
Den specifikke årsag til din fejl er denne linje:tBirthdate := to_date('pBirthdate','dd/mm/yyyy');
pBirthdate
er allerede en streng; ved at sætte en '
rundt om den sender du strengen 'pBirthdate'
til funktionen to_date
og Oracle kan ikke konvertere denne streng til en dag, måned eller år, så den mislykkes.
Du skal skrive dette som:tBirthdate := to_date(pBirthdate,'dd/mm/yyyy');
Du behøver heller ikke at angive number(38,0)
, du kan bare skrive number
i stedet.
Det er muligt at returnere en værdi fra en procedure ved at bruge out
søgeord. Hvis vi antager, at du ønsker at returnere empid
du kunne skrive sådan noget som dette:
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;
For bare at udføre proceduren kald det sådan her:
begin
A1SF_ADDEMP( EmpName, TaxFileNo, Gender
, Salary, Birthdate);
commit;
end;
Hvis du vil returnere empid
så kan du kalde det sådan her:
declare
l_empid number;
begin
l_empid := A1SF_ADDEMP( EmpName, TaxFileNo, Gender
, Salary, Birthdate);
commit;
end;
Bemærk, hvordan jeg har flyttet commit
til det højeste niveau er dette for at undgå at begå ting i hver procedure, når du måske har flere ting, du skal gøre.
Hvis du i øvrigt bruger Oracle 11g, er der ingen grund til at tildele værdien A1Seq_Emp.nextval
til en variabel. Du kan bare indsætte det direkte i tabellen i values
liste. Du vil selvfølgelig ikke kunne returnere den, men du kan returnere A1Seq_Emp.curval
, så længe der ikke er andet, der henter værdier fra sekvensen.