Ошибка процедуры: ORA-24344: успешно выполнена ошибка компиляции

#oracle #plsql

Вопрос:

Процедура занимает две даты, и найдите отчеты, выпущенные за этот период, обновите общую зарплату и распечатайте их.

 CREATE OR REPLACE PROCEDURE Salary_Update(p_Date1 DATE, p_Date2 DATE) AS 
CURSOR MYCR IS 
SELECT ReportID, TotalSale, Rate, TotalSalary, ReportDate
FROM WEEKLY_REPORT
WHERE ReportDate BETWEEN TO_DATE(p_Date1, 'DD-MM-YYYY') AND TO_DATE(p_Date2, 'DD-MM-YYYY'); 
BEGIN
FOR MYPOINTER IN MYCR LOOP
UPDATE WEEKLY_REPORT SET TotalSalary = ((TotalSale/100)*Rate);
DBMS_OUTPUT.PUT_LINE('The total salary for report ' || MYPOINTER.REPORTID || '  updated to ' || MYPOINTER.TotalSalary || 'dollars, which is ' || MYPOINTER.Rate || '% of the total sale of ' || MYPOINTER.TotalSale || 'dollars.');
WHERE ReportID = MYPOINTER.ReportID;
END LOOP;
END Salary_Update;
/
 

казнь

 BEGIN Salary_Update('02-04-2020','05-04-2020');
END;
BEGIN 
Salary_Update(to_date('02-04-2020','dd-mm-yyyy'), to_date('05-04-2020','dd-mm-yyyy'));
END;
 

и то, и другое не работает.

Комментарии:

1. Сделайте show errors это после компиляции или запроса user_errors , чтобы узнать , что не так. := = Для начала , в вашем обновлении вместо этого есть.

2. @Alexpool Я использую oracle apex. показать ошибку не работает

3. Вы можете запросить user_errors , как предложил @Alexpool. Вы to_date звоните по date телефону, который не имеет смысла в дополнение к ошибке в update . Ваше update утверждение обновляет каждую строку таблицы, потому что в ней нет where предложения. На самом деле нет смысла открывать курсор, который повторяет каждую строку в таблице, а затем if в цикле есть оператор, который отфильтровывает большинство строк. Это должно быть where предложение в определении курсора.

4. Ваши входные параметры определены как ДАТА, но когда вы вызываете процедуру, вы даете строки. ДАТА-это внутренний двоичный тип данных.

5. DBMS_OUTPUT подходит для отладки, но не для формальной отчетности. Он не записывается на экран. Он записывает данные во внутренний буфер. Этот буфер затем передается обратно вызывающей программе после завершения процедуры, когда оперативное управление возвращается вызывающему. Затем вызывающий должен решить, обрабатывать буфер или нет. И некоторые вызывающие программы могут даже не быть запрограммированы на то, чтобы их можно было обработать.

Ответ №1:

Существует ряд синтаксических и логических ошибок. Вы не указали точно, что вы хотите, чтобы код выполнял или предоставил воспроизводимый тестовый пример, но я предполагаю, что вы хотите что-то вроде

 CREATE OR REPLACE PROCEDURE Salary_Update(
  p_Date1 DATE, 
  p_Date2 DATE) 
AS 
  CURSOR MYCR IS 
    SELECT ReportID, TotalSale, Rate, TotalSalary, ReportDate
      FROM WEEKLY_REPORT
     WHERE ReportDate BETWEEN p_date1 AND p_date2;
BEGIN
  FOR MYPOINTER IN MYCR 
  LOOP
    UPDATE WEEKLY_REPORT 
       SET TotalSalary = ((TotalSale/100)*Rate)
     WHERE ReportID = MYPOINTER.ReportID;
    DBMS_OUTPUT.PUT_LINE('The total salary for report ' || MYPOINTER.REPORTID || '  updated to ' || MYPOINTER.TotalSalary || 'dollars, which is ' || MYPOINTER.Rate || '% of the total sale of ' || MYPOINTER.TotalSale || 'dollars.');
  END LOOP;
END Salary_Update;
/
 

Строка, которую вы выводите, кажется, не имеет смысла- MYPOINTER.TotalSalary это значение курсора, которое будет значением до обновления. Если важно, чтобы вы распечатали обновленное TotalSalary значение, вам, вероятно, понадобится что-то вроде

 CREATE OR REPLACE PROCEDURE Salary_Update(
  p_Date1 DATE, 
  p_Date2 DATE) 
AS 
  CURSOR MYCR IS 
    SELECT ReportID, TotalSale, Rate, TotalSalary, ReportDate
      FROM WEEKLY_REPORT
     WHERE ReportDate BETWEEN p_date1 AND p_date2;
  l_newSalary weekly_report.totalSalary%type;
BEGIN
  FOR MYPOINTER IN MYCR 
  LOOP
    l_newSalary := (mypointer.TotalSale/100) * mypointer.rate;
    UPDATE WEEKLY_REPORT 
       SET TotalSalary = l_newSalary
     WHERE ReportID = MYPOINTER.ReportID;
    DBMS_OUTPUT.PUT_LINE('The total salary for report ' || MYPOINTER.REPORTID || '  updated to ' || l_newSalary || 'dollars, which is ' || MYPOINTER.Rate || '% of the total sale of ' || MYPOINTER.TotalSale || 'dollars.');
  END LOOP;
END Salary_Update;
/
 

Если ошибка, которую вы получаете, является ошибкой ORA-00942, которая weekly_report не существует, то в текущей схеме такой таблицы нет. Предполагая, что запрос работает при интерактивном запуске, потенциально таблица существует в другой схеме, в текущей схеме для этой таблицы есть локальный синоним, и владелец процедуры имеет доступ только к таблице, предоставленной через роль. В этом случае вам потребуется, чтобы администратор базы данных предоставил доступ к таблице непосредственно владельцу процедуры.