2010-07-16 1 views
2

Я пытаюсь запустить SQL в PL/SQL-процедуре. Если бы я сказал:Oracle, использующий переменную где-то вроде

SELECT * FROM myTable WHERE FNAME like 'Joe%' AND dept = 'xyz'; 

это работает мгновенно.

, если я попробую поставить «Джо» в переменной, которую требуется навсегда, около 3 минут. Вот некоторый синтаксис, который я нашел для использования как с переменными.

PROCEDURE myProcedure(firstName IN VARCHAR, 
         cEmployees OUT cursor_type) 
IS 
BEGIN 
    OPEN cEmployees FOR 
    SELECT * FROM myTable WHERE FNAME like firstName || '%' AND dept = 'xyz'; 
END myProcedure; 

что я делаю неправильно? Благодарю.

+1

Итак, вы жестко закодированы '' Joe% ''в ** этой ** хранимой процедуре, и она быстро запущена? –

+0

да. Я снова тестирую, но выглядит как SELECT * FROM myTable WHERE FNAME (firstName || '%') AND dept = 'xyz'; починил это. – Travis

ответ

4

Я не работал над Oracle в течение некоторого времени.
Однако, вы можете избежать этого

SELECT * FROM myTable WHERE FNAME like firstName || '%' 

Вместо этого установите переменную firstName перед вышеуказанным заявлением.
, например. firstName = firstName || '%' (простите синтаксис)
, а затем SELECT * FROM myTable WHERE FNAME like firstName

+0

Принцип звука. Однако я бы просто упомянул, что ему придется создать локальную переменную. Поскольку параметр 'firstName' объявляется только как' IN', вы не можете назначить его изнутри процедуры. –

+0

Спасибо Shahkalpesh, я создал локальную переменную типа «Var». likeVar: = firstname || '%'; и использовал его в SQL. Это сработало! Я также подтвердил, что просто добавление() вокруг firstName || «%» также работал. Спасибо вам обоим за ваше время. – Travis

+0

Я рад, что это было полезно. – shahkalpesh

0

(извините, это слишком долго для комментария, так я добавляю его как «ответ»)

Travis, я подозреваю, что вам убежище» У меня все получилось. Вы изменили запрос, и он «исправил его» (т. Е. Запустил менее 3 минут), но вы не знаете, почему. Позже вы обнаружите, что новая процедура снова будет перенесена с той же проблемой.

Причина в том, что при повторном запросе запроса (например, при внесении небольшого изменения в него, например добавлении скобок), Oracle генерирует новый план запроса. Когда он генерирует запрос, он, вероятно, использует функцию переплета переменных, чтобы увидеть, что вы ищете. Когда он анализирует его значением «Джо», он создает лучший план для этого конкретного значения, и он работает быстро. Если, однако, запрос будет повторно рассмотрен позже (что, вероятно, будет время от времени по мере того, как запрос будет выровнен из общего пула), может быть представлено другое значение (например, «Том»), и Oracle будет оптимизировать запрос для этого значения, который вполне может быть совсем другим планом. Затем, неожиданно, запрос на «Джо» работает намного медленнее.

Итог: если вы не знаете, почему это стало быстрее, вы не знаете, является ли улучшение постоянным или временным.

Отказ от ответственности: вышесказанное является общим советом - если вы укажете версию своей базы данных и предоставите отчет плана объяснения для двух запросов, вы можете получить более конкретные рекомендации.

+0

Я больше не мог согласиться. О Oracle я не понимаю. Я борюсь с ним каждый день из-за таких глупых вещей или использования переменной с IN (myList). В настоящее время мы используем 10g. – Travis

+0

Совет о влиянии переменной pingking привязывается к 10g. Взгляните на планы ваших запросов. –

+0

Честно говоря, я мог смотреть на них весь день, и они все равно ничего не значили для меня. Я попробовал запустить процедуру с несколькими именами, и она продолжает работать. Ходят слухи, что мы скоро обновим до 11, чтобы кто-то знал после этого. – Travis

Смежные вопросы