sp_check_dept
принимает номер отдела в качестве входного параметра (НОМЕР) и возвращает счет в качестве выходного параметра.employeeadd
передает имя отдела (VARCHAR2) в качестве первого параметра в sp_check_dept
.Есть несколько способов исправить это.В общем, вам понадобится более согласованный метод именования параметров, чтобы упростить выявление этих проблем.
Вариант 1: Используйте имя отдела для обеих функций
create or replace procedure sp_check_dept(p_dept_name IN departments.dept%type,
p_count OUT NUMBER)
as
begin
select count(*)
into p_count
from departments
where dept = p_dept_name;
end;
/
CREATE OR REPLACE PROCEDURE employeeadd(
p_dept_name IN departments.dept%type,
p_employee_name IN employees.employee_name%type,
p_employee_id IN employees.employee_id%type)
as
li_count NUMBER;
BEGIN
sp_check_dept(p_dept_name, li_count);
if li_count = 0 then
INSERT INTO departments (dept)
VALUES (p_dept_name);
end if;
INSERT INTO employee(dept, employee_name, employee_id)
VALUES (p_dept, p_employee_name, p_employee_id);
end;
/
Вариант 2: Преобразуйте название отдела в employeeAdd
в номер отдела, прежде чем передать его в sp_check_dept
create or replace procedure sp_check_dept(p_dept_number IN departments.dept_number%type,
p_count OUT NUMBER)
as
begin
select count(*)
into p_count
from departments
where dept_number = p_dept_number;
end;
/
CREATE OR REPLACE FUNCTION get_dept_number( p_dept_name IN departments.dept%tyep )
RETURN departments.dept_number%type
IS
l_dept_number departments.dept_number%type;
BEGIN
SELECT dept_number
INTO l_dept_number
FROM departments
WHERE dept = p_dept_name;
RETURN l_dept_number
END;
/
CREATE OR REPLACE PROCEDURE employeeadd(
p_dept_name IN departments.dept%type,
p_employee_name IN employees.employee_name%type,
p_employee_id IN employees.employee_id%type)
as
li_count NUMBER;
BEGIN
sp_check_dept( get_dept_number(p_dept_name), li_count);
if li_count = 0 then
INSERT INTO departments (dept)
VALUES (p_dept_name);
end if;
INSERT INTO employee(dept, employee_name, employee_id)
VALUES (p_dept, p_employee_name, p_employee_id);
end;
/
Несколько других замечаний
- Я удалил оператор
RETURN
из вашего заявления IF в employeeAdd
.Вы почти наверняка не захотите выходить из процедуры после вставки строки в таблицу DEPARTMENTS
перед вставкой строки в таблицу EMPLOYEE
. - В определении таблицы использовано множественное число
EMPLOYEES
.Ваша процедура используется единственное число EMPLOYEE
.Я не исправил это, потому что я не был уверен, был ли введенный вами DDL неверным, или была ли неправильная опубликованная вами процедура. - В общем, для реализации
sp_check_dept
было бы гораздо больше смысла.как функция, которая возвращает счет, а не как процедуру с параметром OUT.Если фрагмент кода просто существует для возврата данных вызывающей стороне, он должен быть объявлен как функция. - С точки зрения модели данных имя столбца
DEPT
не особенно хорошо.Было бы гораздо более уместным использовать что-то вроде DEPARTMENT_NAME
, которое передает то, что фактически представляет столбец. - С точки зрения модели данных, имеющей столбец VARCHAR2
DEPT
(даже если он переименован в DEPARTMENT_NAME
) в качестве первичного ключа DEPARTMENTS
и внешнего ключа в EMPLOYEES
не имеет особого смысла.Первичный ключ должен быть неизменным.Однако название отдела со временем изменится.Было бы гораздо разумнее, если бы DEPARTMENT_NUMBER
был первичным ключом, а DEPARTMENT_NAME
был бы просто помечен как уникальный.Это значительно упростит, когда отдел маркетинга переименует в будущем рекламу, потому что вам не придется выслеживать все дочерние таблицы, чтобы обновить их. - Вам следует выбрать соглашение об именах для процедур и придерживатьсятот.Я бы предпочел
check_dept
и add_employee
(глагол, за которым следует тема, подчеркивание разделяющих слов, без префикса).Но если бы вы хотели sp_check_dept
и sp_add_employee
или checkDept
и addEmployee
или даже sp_dept_check
и sp_employee_add
, это было бы хорошо.Но вы и другие разработчики сведете с ума, если в ваших соглашениях об именах процедур нет шаблона.