Оператор IF не позволяет оператору Select сравнивать данную строку - PullRequest
0 голосов
/ 27 февраля 2020

Напишите процедуру (oracle pl sql) для выполнения любого из следующих действий: (a) обновите курс таблицы и установите плату за ввод имени курса, равную стоимости курса java. (б) вставить новую строку для данного входного курса и установить минимальную плату за обучение из всех курсов, доступных в таблице. Условие: делай (а), если имя входного курса уже присутствует в таблице, в противном случае делай (б), если имя входного курса отсутствует в таблице.

Я предоставляю здесь основные сведения c таблицы:

create table course(cid number primary key, cname varchar2(100), duration number, fee number);
insert into course (CID, CNAME, DURATION, FEE)
values (101, 'java', 30, 13000);

insert into course (CID, CNAME, DURATION, FEE)
values (102, 'c', 20, 5000);

insert into course (CID, CNAME, DURATION, FEE)
values (104, 'oracle', 20, 20000);

insert into course (CID, CNAME, DURATION, FEE)
values (105, 'python', 20, 30000);

insert into course (CID, CNAME, DURATION, FEE)
values (106, 'sql', 20, 1000);

Я попробовал приведенный ниже код, но я не знаю, как сравнить данное имя для каждой строки в таблице внутри оператора IF. Пожалуйста, посмотрите код и помогите мне.

create or replace procedure proc_CourseFeeUpdateTry(coursename in course.cname%type,
                                                    java_fee   out number) is
  n_fee number;
  j_fee number;
begin
    if course.cname = coursename then --i'm getting error here

      select t.fee into j_fee from course t where t.cname = 'java';
      java_fee := j_fee;
      update course t set t.fee = java_fee where t.cname = coursename;
      dbms_output.put_line('new course added');
    else
      dbms_output.put_line(sqlerrm || '-' || sqlcode);
      select min(t.fee) into n_fee from course t;
      java_fee := n_fee;
      insert into course values (103, coursename, 40, java_fee);
    end if;
  commit;
end;

1 Ответ

0 голосов
/ 28 февраля 2020

Кажется, что полученная вами ошибка связана с серьезным неправильным представлением о доступных табличных данных в процедуре. Оператор IF не имеет проблем с возможностью последующего выбора. Проблема здесь в том, что вы ссылались на столбец таблицы (course.cname), предварительно не выбрав что-либо из таблицы курса. То, что таблица существует, не дает доступа к данным внутри нее, поэтому вы должны выбрать ее, прежде чем ссылаться на значения столбцов. Так что до этого, ЕСЛИ вам нужно, по крайней мере, выбор, и так как это процедура выбора .. в частности. Теперь выбор в делает значения столбца доступными , если они существуют , но если нет, то генерируется исключение NO_DATA_FOUND. Мы этого факта избегаем, ЕСЛИ полностью. Далее, есть 2 случая, когда вы используете структуру:

select data_value into local variable;
output_variable = local_variable; 

Это не обязательно, так как вы можете просто выбрать непосредственно в output_variable. Следующее содержит 2 пересмотра вашей процедуры. 1-й оставив ваш код как можно больше. 2-й пересмотр кода, чтобы использовать все вышеперечисленное. Я надеюсь, что это поможет вам понять дальше. Минимальное необходимое изменение требует, чтобы вы выбрали таблицу курсов до вашего утверждения IF и обработали no_data_found_error.

create or replace procedure proc_CourseFeeUpdateTry(coursename in course.cname%type,
                                                    java_fee   out number) is
  n_fee number;
  j_fee number;

  l_course_name   course.cname%type; 
begin
    begin
        select c.cname
          into l_course_name
          from course c
         where c.cname = coursename;
    exception 
    when no_data_found then 
       null; 
    end ; 

    if l_course_name = coursename then  

      select t.fee into j_fee from course t where t.cname = 'java';
      java_fee := j_fee;
      update course t set t.fee = java_fee where t.cname = coursename;
      dbms_output.put_line('course fee updated');       --- course was not added just updted
    else
      dbms_output.put_line(sqlerrm || '-' || sqlcode);
      select min(t.fee) into n_fee from course t;
      java_fee := n_fee;
      insert into course values (103, coursename, 40, java_fee);  --- leave message
      dbms_output.put_line('new course added');
    end if;
  commit;
end;

Во второй версии используются упомянутые выше темы и реструктуризации.

create or replace procedure proc_CourseFeeUpdateTry(coursename in course.cname%type,
                                                    java_fee   out number) is

  l_cid course.cid%type; 
begin
    select c.cid 
      into l_cid  
      from course c
     where c.cname = coursename; 

    begin  -- inner block to trap java not found 
       -- if we get here then we know that the implied test cource.cname = coursename is true
       select t.fee into java_fee
         from course t where t.cname = 'java';

       update course t set t.fee = java_fee where cid = l_cid;
       dbms_output.put_line( coursename || ' fee updated');
       commit;
    exception 
      when no_data_found then 
         raise_application_error( -20109, 'course name ''java'' is not in course table');
      end ; -- inner block

exception
when no_data_found then
   -- if we get here the we know that the course name does not exist 
   select min(t.fee) into java_fee from course t;
   insert into course values (103, coursename, 40, java_fee);
   commit; 
end;

Обратите внимание на вставку в обеих процедурах. Это жесткие коды ID. В результате ваша процедура может добавить строку ровно 1 раз. Это крайне плохой процесс. Либо передайте новый идентификатор в качестве параметра (все еще не хорошо, но лучше), либо переопределите таблицу для автоматической генерации ключа. В зависимости от вашей версии Oracle ищите последовательности и вставляйте триггеры (до 12 c) или столбцы идентификации (12 c и более поздние).

...