Oracle xmlexists с переменным путем

У меня есть таблица tsk с двумя столбцами: идентификатор задачи в числе и область действия в XMLTYPE, которая может быть такой:

<scope>
    <siteCode>2</siteCode>
    <supplierCode>1111</supplierCode>
    <contractCode>464</contractCode>
    <orderNumber>85235478</orderNumber>
</scope>

Но элементы под тегом могут варьироваться от одной записи к другой.

Мне нужно выбрать идентификаторы задач, которые соответствуют некоторым условиям в области. Например :

select tskid
from tsk t 
where xmlexists('$a/scope[siteCode = 2 and supplierCode = 111]' passing t.tskscope as "a");

Поскольку область действия может варьироваться, у меня есть функция PL/SQL, которая использует путь xml p_xmlpath для поиска в типе varchar2. Так, например, p_xmlpath будет:

p_xmlpath := 'scope[siteCode = 2 and supplierCode = 1111]';

Затем я хочу запустить запрос с помощью XMLEXISTS, чтобы найти совпадающие записи. Я думал сделать это с переменными связывания следующим образом:

select tskid
from tsk t 
where xmlexists('$a/$b' passing t.tskscope as "a", p_xmlpath as "b" );

Делая это, запрос возвращает все записи без использования условия с xmlexists.

Кто-нибудь знает, как с этим справиться, т.е. иметь переменный путь для XMLEXISTS?

Дополнительная информация: до сих пор я использовал функцию existsNode, и следующий запрос выполнял задание правильно:

select tskid
from tsk t 
where existsnode(t.tskscope, p_xmlpath) = 1;

Но с одной стороны existsNode устарел, а с другой я заметил, что в моей ситуации функция xmlexists работала заметно быстрее, чем existsNode, поэтому я бы перешел на xmlexists.

Заранее спасибо.


person cbe    schedule 16.06.2017    source источник


Ответы (1)


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

В качестве обходного пути вы можете создать XPath во время выполнения с помощью replace():

select tskid
from tsk t 
where xmlexists(replace('$a/$b', '$b', p_xmlpath) passing t.tskscope as "a");

или создайте строку XPath как переменную, если вы не хотите заменять ее, и включите часть $a/:

p_xmlpath := '$a/' || p_xmlpath;

select tskid
from tsk t 
where xmlexists(p_xmlpath passing t.tskscope as "a");
person Alex Poole    schedule 16.06.2017
comment
Спасибо ! Я попробовал решение с определением всего пути как переменной, и оно дало мне правильные результаты. К сожалению, запрос в 200 раз длиннее, чем если бы я запускал его с тем же путем в литеральной строке, я не знаю, почему... - person cbe; 16.06.2017