pl / sql — to_date не работает с параметром немедленного выполнения

#sql #oracle #plsql #dynamic-sql #ora-00904

#sql #Oracle #plsql #dynamic-sql #ora-00904

Вопрос:

я хочу иметь возможность выполнить мой приведенный ниже процесс следующим образом:

 exec procname('29-JAN-2011');
  

код процедуры является:

 PROCEDURE procname(pardate VARCHAR2) IS

  vardate DATE := to_date(pardate, 'DD-MON-YYYY');
  SQLS VARCHAR2(4000);

BEGIN    

  SQLS := 'SELECT cola, colb
             FROM tablea 
            WHERE TRUNC(coldate) = TRUNC(TO_DATE('''||pardate||''',''DD/MON/YYYY''))';

  EXECUTE IMMEDIATE SQLS;

END;
  

Он продолжает выдавать ошибку:

ORA-00904: «JAN»: недопустимый идентификатор.

Он компилируется, но выдает ошибку при запуске этой команды:

 EXEC procname('29-JAN-2011');
  

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

1. Это не настоящий код, верно? Он не будет компилироваться.

2. Я знаю, что это всего лишь пример, но должна ли эта процедура быть динамическим SQL? Это отлично работало бы как обычная процедура.

3. это должно быть динамическим, потому что я собираюсь сделать так, чтобы имена столбцов были неизвестны во время выполнения

Ответ №1:

Вы объявляете переменную, которая преобразует входной параметр в дату: почему бы не использовать ее?

Кроме того, функция TRUNC(), применяемая к дате, удаляет элемент time. Вам это здесь не нужно, потому что передаваемое вами значение не имеет времени.

Итак, ваш код должен быть:

 PROCEDURE procname(pardate VARCHAR2) IS

  vardate DATE := to_date(pardate, 'DD-MON-YYYY');
  SQLS VARCHAR2(4000)  := 'select cola, colb FROM tablea 
           WHERE TRUNC(coldate) = :1';

   l_a tablea.cola%type;
   l_b tablea.colb%type;
BEGIN    
  EXECUTE IMMEDIATE SQLS 
      into l_a, l_b
      using vardate;
END;  
  

Указание динамического оператора SQL с помощью переменной bind и выполнение его с использованием синтаксиса USING намного эффективнее. Обратите внимание, что нам все еще нужно выбрать в некоторых переменных.

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

1. В качестве дополнительного примечания, этот trunc () может избежать использования индекса вместо coldate . Он может подумать о хитрости «… где coldate между:1 и:2 0.99999» с использованием vardate, vardate .

Ответ №2:

Вы используете две разные нотации в двух вызовах to_date . Я думаю, что один из них (второй) неверен.

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

1. Я имею в виду, что один из них — DD-MON-ГГГГ, а другой — DD / MON / ГГГГ. При вводе используются тире, а не косые черты, поэтому я думаю, что второе неверно.

2. Также может быть проблема с настройкой языка. Вы живете в стране, где январь не сокращается до января?