#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
не существует, то в текущей схеме такой таблицы нет. Предполагая, что запрос работает при интерактивном запуске, потенциально таблица существует в другой схеме, в текущей схеме для этой таблицы есть локальный синоним, и владелец процедуры имеет доступ только к таблице, предоставленной через роль. В этом случае вам потребуется, чтобы администратор базы данных предоставил доступ к таблице непосредственно владельцу процедуры.