XmlRoot, XmlElement, InsertChildXml в PL/SQL функцията дава PLS-00201 идентификаторът трябва да бъде деклариран

Забележка: Моля, не отбелязвайте това като дубликат на подобен въпрос. Питам това само защото другите въпроси не се отнасят до точно същата ситуация и техните отговори не предоставят работещо решение.

Ако използвам свързана с XML функция като INSERTCHILDXML в израз за избор като следния, тя работи напълно добре:

SELECT INSERTCHILDXML( ... ) FROM DUAL;

Но ако се опитам да използвам това в PL/SQL като следното, дава грешка PLS-00201: identifier 'INSERTCHILDXML' must be declared.

CREATE FUNCTION ...
    RETURN XMLType
AS
BEGIN
    RETURN INSERTCHILDXML( ... );
EXCEPTION
    ...
END;

Функции, които имат този проблем: XMLROOT, XMLELEMENT, INSERTCHILDXML

Има десетки резултати при търсене в мрежата за грешката. Много от тях ми казват CREATE PUBLIC SYNONYM и GRANT EXECUTE на проблемния идентификатор. Но не работи.

Публичен синоним може да бъде създаден за същото име, но предоставянето на изпълнение (на която и да е схема) е неуспешно с:

ORA-01775: looping chain of synonyms

Ако се опитам да използвам друго синонимно име, при опит за предоставяне на изпълнение, получавам:

ORA-00980: synonym translation is no longer valid

Как мога да разреша проблема и успешно да използвам изброените функции в моята нова PL/SQL функция?


person ADTC    schedule 06.08.2014    source източник


Отговори (1)


След кратка почивка (и разглеждане на още няколко подобни въпроса), достигнах до прозрение.

Очевидно причината, поради която не работи, е, че се опитвах да RETURN изхода на функцията:

RETURN INSERTCHILDXML( ... );

Това, което наистина трябва да направя, е да накарам изхода в променлива, след което да върна променливата:

CREATE FUNCTION ...
    RETURN XMLType
AS
    temp XMLType;
BEGIN
    SELECT INSERTCHILDXML( ... ) INTO temp FROM DUAL;
    RETURN temp;
EXCEPTION
    ...
END;

Забележка: Няма нужда да създавате синоними или да давате разрешения за изпълнение. Ако сте извършили нещо от това, можете да го отмените.

Допълнителни констатации:

Не можете да присвоите изхода на функцията на променлива. Трябва да се натисне с помощта на SELECT INTO. Можете обаче да използвате типа XMLType и неговите методи.

temp := XMLType( ... ) -- works fine
temp := XMLELEMENT ( ... ) -- does not work

Използването в условни изрази е нестабилно. CASE WHEN го толерира, докато IF не.

CASE WHEN EXISTSNODE( ... ) = 1 THEN -- works fine

IF EXISTSNODE( ... ) = 1 THEN -- does not work

Можете да заобиколите проблема с IF, като използвате променлива:

SELECT EXISTSNODE( ... ) INTO exists_node FROM DUAL;
IF exist_node = 1 THEN -- works
person ADTC    schedule 06.08.2014