Reputation: 305
I have the following body from my package, used to do some CRUD operations in HR schema:
CREATE SEQUENCE emp_sequence;
CREATE OR REPLACE PACKAGE BODY employee_crud AS
PROCEDURE create_emp(p_last_name IN employees.last_name%type, p_first_name IN employees.first_name%type,
p_email IN employees.email%type, p_hire_date IN employees.hire_date%type,
p_job_id IN employees.job_id%type) AS
BEGIN
SELECT emp_sequence.NEXTVAL INTO id FROM dual;
INSERT INTO employees(last_name, first_name, email, hire_date, job_id)
VALUES (emp_seq.nextval, p_last_name, p_first_name, p_email, p_hire_date, p_job_id);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
dbms_output.put_line('error');
END create_emp;
PROCEDURE erase_emp(p_employee_id IN employees.employee_id%type) AS
BEGIN
DELETE FROM employees
WHERE employee_id = p_employee_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('Error');
END erase_emp;
PROCEDURE upd_emp(p_employee_id IN employees.employee_id%type, p_salary IN employees.salary%type,
p_email IN employees.email%type, p_department_id IN employees.department_id%type) AS
BEGIN
UPDATE employees
SET employee_id = p_employee_id,
salary = p_salary,
email = p_email,
department_id = p_department_id
WHERE employee_id = p_employee_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('error');
END upd_emp;
PROCEDURE read_emp(p_employee_id IN employees.employee_id%type, p_last_name OUT employees.last_name%type,
p_first_name OUT employees.first_name%type, p_email OUT employees.email%type,
p_hire_date OUT employees.hire_date%type, p_job_id OUT employees.job_id%type,
p_salary OUT employees.salary%type) AS
BEGIN
SELECT employee_id, last_name, first_name, email, hire_date, job_id, salary
INTO p_last_name, p_first_name, p_email, p_hire_date, p_job_id, p_salary
FROM EMPLOYEES
WHERE employee_id = p_employee_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('Error');
END read_emp;
END employee_crud;
/
After creating the specification (which is correct), I create a sequence to help adding employees. But compiling the body of the package, it shows the following errors:
LINE/COL ERROR
-------- ----------------------------------------------------
10/5 PL/SQL: SQL Statement ignored
10/38 PLS-00201: 'ID' must be declared
10/41 PL/SQL: ORA-00904: : identifier is not valid
11/5 PL/SQL: SQL Statement ignored
11/17 PL/SQL: ORA-00913: too many values
49/5 PL/SQL: SQL Statement ignored
51/5 PL/SQL: ORA-00947: insufficient values
What should I do to correct these errors? I changed some names from my code because it's an assignment and I having troubles trying to do it without errors.
Upvotes: 0
Views: 927
Reputation: 231851
10/38 PLS-00201: 'ID' must be declared
You're selecting data into a local variable ID
that hasn't been declared. If you want to declare a local variable, you'd do so in the declaration section between the AS
and the BEGIN
PROCEDURE create_emp(p_last_name IN employees.last_name%type,
p_first_name IN employees.first_name%type,
p_email IN employees.email%type,
p_hire_date IN employees.hire_date%type,
p_job_id IN employees.job_id%type)
AS
id integer;
BEGIN
SELECT emp_sequence.NEXTVAL INTO id FROM dual;
If you're going to do that, you'd want to use the local variable id
in your INSERT
statement rather than calling emp_sequence.nextval
directly. Personally, though, I'd get rid of the local variable, get rid of the initial SELECT
, and just make the emp_sequence.nextval
call in your INSERT
statement.
11/17 PL/SQL: ORA-00913: too many values
Regardless of how you do it, though, you'd need the number of columns in your INSERT
to match the number of VALUES
you specify.
PROCEDURE create_emp(p_last_name IN employees.last_name%type,
p_first_name IN employees.first_name%type,
p_email IN employees.email%type,
p_hire_date IN employees.hire_date%type,
p_job_id IN employees.job_id%type)
AS
id integer;
BEGIN
SELECT emp_sequence.NEXTVAL INTO id FROM dual;
INSERT INTO employees(employee_id, last_name, first_name, email, hire_date, job_id)
VALUES (id, p_last_name, p_first_name, p_email, p_hire_date, p_job_id);
END create_emp;
Or if you want to call the sequence directly
PROCEDURE create_emp(p_last_name IN employees.last_name%type,
p_first_name IN employees.first_name%type,
p_email IN employees.email%type,
p_hire_date IN employees.hire_date%type,
p_job_id IN employees.job_id%type)
AS
BEGIN
INSERT INTO employees(employee_id, last_name, first_name, email, hire_date, job_id)
VALUES ( emp_sequence.NEXTVAL, p_last_name, p_first_name, p_email, p_hire_date, p_job_id);
END create_emp;
Similarly, for your next error, the number of variables that you fetch into should match the number of columns that you're selecting
51/5 PL/SQL: ORA-00947: insufficient values
In your read_emp, you're selecting 7 things and trying to put them into 6 variables. Assuming that you don't want to return the employee_id
, don't bother selecting it.
PROCEDURE read_emp(p_employee_id IN employees.employee_id%type,
p_last_name OUT employees.last_name%type,
p_first_name OUT employees.first_name%type,
p_email OUT employees.email%type,
p_hire_date OUT employees.hire_date%type,
p_job_id OUT employees.job_id%type,
p_salary OUT employees.salary%type)
AS
BEGIN
SELECT last_name, first_name, email, hire_date, job_id, salary
INTO p_last_name, p_first_name, p_email, p_hire_date, p_job_id, p_salary
FROM EMPLOYEES
WHERE employee_id = p_employee_id;
END read_emp;
While you can write a read_emp
procedure like this, it would generally make more sense to create a function that returns an employees%rowtype
record instead.
Your exception clauses should be removed. At best, they are discarding the error stack that would tell a person what failed and where. At worst, they're hiding the errors (you should never assume that anyone will ever see anything that you write to dbms_output
) and causing the calling code to believe that some operation succeeded when it didn't.
Upvotes: 3