Ошибка простого запроса Oracle 10g

#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. Ваш ответ отлично работает, но Тони Эндрюс был первым. Тем не менее, большое вам спасибо. 🙂