#plsql #oracle10g
#plsql #oracle10g
Вопрос:
Разработчик Oracle SQL жалуется на next SQL, хотя я, похоже, не могу найти причину:
IF to_number(to_char(sysdate, 'HH24')) > 6 THEN
IF to_number(to_char(sysdate, 'HH24')) < 9 THEN
SELECT 1 FROM dual;
ELSE
SELECT (CASE WHEN result = 'SUCCESS' THEN 1 ELSE 0 END) FROM t_job WHERE to_char(start_time, 'yyyy/mm/dd') = to_char(sysdate, 'yyyy/mm/dd');
END IF;
ELSE
SELECT (CASE WHEN result = 'SUCCESS' THEN 1 ELSE 0 END) FROM t_job WHERE to_char(start_time, 'yyyy/mm/dd') = to_char(sysdate, 'yyyy/mm/dd');
END IF;
В чем ошибка в предоставленном запросе?
Отчет об ошибке:
Error starting at line 7 in command:
ELSE
Error report:
Unknown Command
(CASEWHENRESULT='SUCCESS'THEN1ELSE0END)
---------------------------------------
1
Error starting at line 9 in command:
END IF
Error report:
Unknown Command
Комментарии:
1. на что именно он жалуется? )
2. @быть здесь сейчас, уже добавлено, просто понял, что этого не хватает 🙂
Ответ №1:
Есть пара проблем с вашим кодом (который является PL / SQL, а не просто SQL):
1) Вы пропускаете begin
и end
вокруг блока.
2) Вам select
нужно into
предложение
попробуйте:
DECLARE
l_result number;
BEGIN
IF to_number(to_char(sysdate, 'HH24')) > 6 THEN
IF to_number(to_char(sysdate, 'HH24')) < 9 THEN
SELECT 1 INTO l_result FROM dual;
ELSE
SELECT (CASE WHEN result = 'SUCCESS' THEN 1 ELSE 0 END)
INTO l_result
FROM t_job WHERE to_char(start_time, 'yyyy/mm/dd') = to_char(sysdate, 'yyyy/mm/dd');
END IF;
ELSE
SELECT (CASE WHEN result = 'SUCCESS' THEN 1 ELSE 0 END)
INTO l_result
FROM t_job WHERE to_char(start_time, 'yyyy/mm/dd') = to_char(sysdate, 'yyyy/mm/dd');
END IF;
dbms_output.put_line('result is '||l_result);
END;
Комментарии:
1.
to_char(start_time, 'yyyy/mm/dd') = to_char(sysdate, 'yyyy/mm/dd')
для меня тоже звучит как плохая практика2. Кроме того, вместо
to_char(start_time, 'yyyy/mm/dd') = to_char(sysdate, 'yyyy/mm/dd')
я бы выбралtrunc(start_time) = trunc(sysdate)
3. @Tonu Andrews, это был первоначальный вариант, но как это влияет на производительность?
4. Я не думаю, что немного, но, вероятно, немного быстрее (все, что он делает, это удаляет 3 байта данных, а не довольно сложное форматирование), а также семантически понятнее
5. Хорошо, это, вероятно, работает безупречно, но что, если SQL Developer show напечатает следующую строку: анонимный блок завершен?
Ответ №2:
Поскольку это блок PL / SQL, вашим операторам SELECT потребуется выбрать данные в некоторой локальной переменной, или их нужно будет использовать в курсоре. Какой подход вы хотите, будет зависеть от того, сколько строк в T_JOB
может потенциально соответствовать указанным вами критериям. Предполагая, что все три оператора будут возвращать ровно 1 строку, вы могли бы сделать что-то вроде этого (код упрощен, чтобы избежать повторного выполнения одного и того же запроса дважды)
DECLARE
l_some_local_variable PLS_INTEGER;
BEGIN
IF( to_number( to_char( sysdate, 'HH24' ) ) > 6 and
to_number( to_char( sysdate, 'HH24' ) ) < 9 )
THEN
SELECT 1
INTO l_some_local_variable
FROM dual;
ELSE
SELECT (CASE WHEN result = 'SUCCESS'
THEN 1
ELSE 0
END)
INTO l_some_local_variable
FROM t_job
WHERE trunc( start_time ) = trunc( sysdate );
END IF;
END;
Конечно, после того, как вы заполните данные в своей локальной переменной, вам действительно нужно будет что-то сделать со значением. Возможно, вам захочется создать функцию, которая возвращает локальную переменную, а не использовать анонимный блок PL / SQL, как я сделал здесь.
Комментарии:
1. Ваш ответ отлично работает, но Тони Эндрюс был первым. Тем не менее, большое вам спасибо. 🙂