Хранимая процедура Oracle SQL с зарезервированными словами Oracle, переданными в переменную - PullRequest
0 голосов
/ 27 апреля 2018

У меня есть хранимая процедура, передающая строку значений, разделенных пробелами, которая затем выполняет поиск в таблице и возвращает данные, где столбец имеет любое из этих значений. Все шло хорошо до тех пор, пока пользователю не понадобилось передать «INDEX END UNKNOWN PROCESS», который ничего не возвращал, даже если есть данные с этими значениями:

    CREATE OR REPLACE PROCEDURE  Searches
(
   QUEUE             IN TYPES.CHAR50,  
   P_CURSOR          IN OUT SYS_REFCURSOR  
)   
AS

BEGIN

OPEN P_CURSOR FOR
 SELECT *
 FROM tablez t
 WHERE /* If the subquery returns UNKNOWN, END, PROCESS, INDEX which are Oracle reserved words the main query won't return any results */
       /* In order to pass this inconsistency, I concatenated XYZ to both sides when using IN Clause                                   */
       CONCAT(LTRIM(RTRIM(t.QUEUECD)),'XYZ') IN ( SELECT CONCAT(LTRIM(RTRIM(tr.prom)),'XYZ')     
                                                        FROM ( SELECT regexp_substr(QUEUE,'[^ ]+', 1, LEVEL) prom 
                                                               FROM dual 
                                                               CONNECT BY regexp_substr(QUEUE, '[^ ]+', 1, LEVEL) IS NOT NULL 
                                                              ) tr   
                                                       )
    ;

END Searches;

Итак, я изменил код, чтобы использовать regexp_substr, и только конкатенируя 'XYZ' возвращал значения при выполнении сравнения. Но это временное исправление, потому что QUEUECD является индексированным столбцом в базе данных и использование CONCAT в предложении WHERE привело к проблемам с производительностью больших данных. Есть ли у вас какие-либо предложения, как улучшить производительность или передать список значений другим способом?

Спасибо!

1 Ответ

0 голосов
/ 28 апреля 2018

Хранимая процедура Oracle SQL с зарезервированными словами Oracle, переданными переменная

Похоже, другая проблема. Посмотрите: нет способа передать «зарезервированные слова» в качестве значения переменной - когда у вас есть переменная varchar, тогда значение является текстом - больше ничего.

Я сделал пример таблицы и протестировал запрос без конкатенации 'XYZ' - и у меня нет таких проблем. Может быть, есть какие-то белые непечатные символы в конце или в начале записи?

Относительно:

Есть ли у вас какие-либо предложения, как улучшить производительность или передать список значений другим способом?

Да. Передать коллекцию (вложенную таблицу) в качестве параметра. Например:

create or replace type T_TAB_STRING as table of varchar2(4000);

Затем измените тип QUEUE с TYPES.CHAR50 на T_TAB_STRING.

Затем вы можете использовать выражение table () для удаления вложенной коллекции внутри запроса:

SELECT *
FROM tablez t
WHERE t.QUEUECD IN ( SELECT /*+ DYNAMIC_SAMPLING(tr, 2) */
                         *
                       FROM TABLE(QUEUE) tr
                   )
;

Подсказка динамической выборки заставляет БД проверять, сколько элементов находится внутри коллекции. Без этой БД предполагается, что это размер 1 блока (обычно 8 КБ), поэтому CBO может выбрать полное сканирование вместо индексного сканирования.

Если вы не можете использовать эту подсказку или она по какой-то причине не работает, есть другой способ помочь CBO с коллекциями в запросах. Он реализует интерфейс Extensible Optimizer для этой коллекции. Адриан Биллингтон написал в этой статье , как это сделать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...