PL / SQL ошибка вопрос - PullRequest
0 голосов
/ 23 июля 2011

Я пытаюсь написать хранимую процедуру, которая вставляет строку в таблицу сотрудников.Если отдел не существует, его необходимо вставить в таблицу отделов.У меня есть следующий код:

drop table employees;
drop table departments;

create table departments(
dept            varchar2(30),
dept_number     number,
dept_city       varchar2(30),
CONSTRAINT pk_dept PRIMARY KEY(dept)
);

create table employees( 
dept            varchar2(30),
employee_name   varchar2(40),
employee_id     number,
CONSTRAINT pk_id PRIMARY KEY(employee_id),
CONSTRAINT fk_dept FOREIGN KEY (dept) REFERENCES departments(dept)
);


CREATE  OR REPLACE PROCEDURE employeeadd(
a_dept    IN  VARCHAR2,
a_employee_name    IN VARCHAR2,
a_employee_id    IN NUMBER)
as
    li_count    NUMBER;
BEGIN
sp_check_dept(a_dept, li_count);    
if li_count = 0 then
INSERT INTO departments (dept) values (a_dept);
    return;
end if;
INSERT INTO employee values (a_dept, a_employee_name, a_employee_id);
end;
/

create or replace procedure sp_check_dept(a_dept IN NUMBER,
                        a_count  OUT NUMBER)
as
begin
    select count(*)
into a_count
from departments
where dept_number = a_dept;
end;
/

Когда я запускаю свой оператор execute как execute employeeadd ('marketing', 'john', 10);Я получаю следующие ошибки.Я не могу понять, как обойти ошибки и / или написать это правильно:

ORA-06502: PL / SQL: ошибка числа или значения: ошибка преобразования символа в число ORA-06512: в"employeeadd", строка 8 ORA-06512: в строке 1

Ответы [ 3 ]

3 голосов
/ 23 июля 2011

Почему li_count объявлен вне блока BEGIN ... END?Вам нужно присвоить его перед отправкой в ​​качестве аргумента sp_check_dept ()?

Редактировать: только что увидел ваш комментарий: sp_check_dept ожидает число в качестве первого параметра;Вы объявили a_dept как VARCHAR.

2 голосов
/ 23 июля 2011

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;
/

Несколько других замечаний

  1. Я удалил оператор RETURNиз вашего заявления IF в employeeAdd.Вы почти наверняка не захотите выходить из процедуры после вставки строки в таблицу DEPARTMENTS перед вставкой строки в таблицу EMPLOYEE.
  2. В определении таблицы использовано множественное число EMPLOYEES.Ваша процедура используется единственное число EMPLOYEE.Я не исправил это, потому что я не был уверен, был ли введенный вами DDL неверным, или была ли неправильная опубликованная вами процедура.
  3. В общем, для реализации sp_check_dept было бы гораздо больше смысла.как функция, которая возвращает счет, а не как процедуру с параметром OUT.Если фрагмент кода просто существует для возврата данных вызывающей стороне, он должен быть объявлен как функция.
  4. С точки зрения модели данных имя столбца DEPT не особенно хорошо.Было бы гораздо более уместным использовать что-то вроде DEPARTMENT_NAME, которое передает то, что фактически представляет столбец.
  5. С точки зрения модели данных, имеющей столбец VARCHAR2 DEPT (даже если он переименован в DEPARTMENT_NAME) в качестве первичного ключа DEPARTMENTS и внешнего ключа в EMPLOYEES не имеет особого смысла.Первичный ключ должен быть неизменным.Однако название отдела со временем изменится.Было бы гораздо разумнее, если бы DEPARTMENT_NUMBER был первичным ключом, а DEPARTMENT_NAME был бы просто помечен как уникальный.Это значительно упростит, когда отдел маркетинга переименует в будущем рекламу, потому что вам не придется выслеживать все дочерние таблицы, чтобы обновить их.
  6. Вам следует выбрать соглашение об именах для процедур и придерживатьсятот.Я бы предпочел check_dept и add_employee (глагол, за которым следует тема, подчеркивание разделяющих слов, без префикса).Но если бы вы хотели sp_check_dept и sp_add_employee или checkDept и addEmployee или даже sp_dept_check и sp_employee_add, это было бы хорошо.Но вы и другие разработчики сведете с ума, если в ваших соглашениях об именах процедур нет шаблона.
0 голосов
/ 23 июля 2011

2 возможностей, которые я вижу: 1. таблица сотрудника имеет столбцы в другом порядке, чем ваша инструкция вставки, и она пытается преобразовать dept или name в id 2. значение, установленное в li_count, не является числом, поэтому оно пытаетсяпреобразовать возвращаемое значение в число и выдает ошибку

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...