Pertama, Anda tidak dapat memanggil fungsi dengan DML di dalamnya dalam pernyataan pilih. Anda harus menetapkan output ke variabel dalam blok PL/SQL, seperti:
declare
l_output number;
begin
l_output := my_function(variable1, variable2);
end;
Ini praktik yang buruk untuk melakukan DML dalam suatu fungsi; sebagian karena itu menyebabkan kesalahan yang Anda temui. Anda harus menggunakan prosedur seperti yang dijelaskan di bawah ini. Alasan lain untuk ini adalah Anda seperti biasa mengembalikan null, tidak perlu mengembalikan apa pun!
create or replace procedure my_procedure ( <variables> ) is
begin
insert into employees( <columns> )
values ( <values > );
end;
Alasan spesifik untuk kesalahan Anda adalah baris ini:tBirthdate := to_date('pBirthdate','dd/mm/yyyy');
pBirthdate
sudah menjadi string; dengan meletakkan '
di sekitarnya Anda memberikan string 'pBirthdate'
ke fungsi to_date
dan Oracle tidak dapat mengubah string ini menjadi hari, bulan, atau tahun sehingga gagal.
Anda harus menulis ini sebagai:tBirthdate := to_date(pBirthdate,'dd/mm/yyyy');
Anda juga tidak perlu menentukan number(38,0)
, Anda cukup menulis number
sebagai gantinya.
Dimungkinkan untuk mengembalikan nilai dari prosedur menggunakan out
kata kunci. Jika kami berasumsi bahwa Anda ingin mengembalikan empid
Anda bisa menulis seperti ini:
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;
Untuk menjalankan prosedur, panggil saja seperti ini:
begin
A1SF_ADDEMP( EmpName, TaxFileNo, Gender
, Salary, Birthdate);
commit;
end;
Jika Anda ingin mengembalikan empid
maka Anda dapat menyebutnya seperti ini:
declare
l_empid number;
begin
l_empid := A1SF_ADDEMP( EmpName, TaxFileNo, Gender
, Salary, Birthdate);
commit;
end;
Perhatikan bagaimana saya memindahkan commit
ke tingkat tertinggi, ini untuk menghindari melakukan hal-hal di setiap prosedur ketika Anda mungkin memiliki lebih banyak hal yang perlu Anda lakukan.
Kebetulan, jika Anda menggunakan Oracle 11g maka tidak perlu menetapkan nilai A1Seq_Emp.nextval
ke sebuah variabel. Anda bisa langsung memasukkannya ke dalam tabel di values
daftar. Anda, tentu saja tidak akan dapat mengembalikannya, tetapi Anda dapat mengembalikan A1Seq_Emp.curval
, selama tidak ada hal lain yang mendapatkan nilai dari urutan tersebut.