2
with oracle xmltable 
SELECT u.*
   FROM table1
   ,    XMLTable('/abc/def[contract = $count]'
                 PASSING xmlcol, 1 as "count"
                 COLUMNS contract integer path 'contract',
                         oper     VARCHAR2(20) PATH 'oper' ) u 

これは通常、私たちが行うことです。ここで、上記のクエリで「COLUMNS」を Xpath の別のテーブル列から選択する必要があります。

{
SELECT u.*
   FROM table1
   ,    XMLTable('/abc/def[contract = $count]'
                 PASSING xmlcol, 1 as "count"
                 COLUMNS (select xpath from xpath_metadeta )) u
 }

これが可能かどうか、またその方法を教えてください。

4

1 に答える 1

0

私の頭に浮かぶ1つのオプションは、動的SQLと参照カーソルです。

このようなもの:

DECLARE
columnParameters SYS.ODCIVARCHAR2LIST :=
    SYS.ODCIVARCHAR2LIST(
        'TITLE VARCHAR2(1000) PATH ''title''',
        'SUMMARY CLOB PATH ''summary''',
        'UPDATED VARCHAR2(20) PATH ''updated''',
        'PUBLISHED VARCHAR2(20) PATH ''published''',
        'LINK VARCHAR2(1000) PATH ''link/@href'''
    );

ref_cursor SYS_REFCURSOR;
cursor_id NUMBER;
table_description DBMS_SQL.DESC_TAB;
column_count NUMBER;
string_value VARCHAR2(4000);
clob_value CLOB;

FUNCTION DYNAMIC_XMLTABLE(xml_columns SYS.ODCIVARCHAR2LIST) RETURN SYS_REFCURSOR
IS
    result SYS_REFCURSOR;
    statementText VARCHAR2(32000) := Q'|SELECT * FROM
XMLTABLE(
    XMLNAMESPACES (DEFAULT 'http://www.w3.org/2005/Atom'),
    'for $entry in /feed/entry return $entry'
    PASSING
        HTTPURITYPE('http://stackoverflow.com/feeds/tag?tagnames=oracle&sort=newest').getxml()
    COLUMNS
        {column_definition}
)|';
BEGIN
    SELECT REPLACE(statementText, '{column_definition}', LISTAGG(COLUMN_VALUE, ', ') WITHIN GROUP (ORDER BY ROWNUM)) INTO statementText FROM TABLE(xml_columns);
    DBMS_OUTPUT.PUT_LINE('Statement: ' || CHR(10) || statementText);

    OPEN result FOR statementText;
    RETURN result;
END;
BEGIN
DBMS_OUTPUT.ENABLE(NULL);

ref_cursor := dynamic_xmltable(columnParameters);
cursor_id := DBMS_SQL.TO_CURSOR_NUMBER(ref_cursor);
DBMS_SQL.DESCRIBE_COLUMNS(cursor_id, column_count, table_description);

FOR i IN 1..column_count LOOP
    IF table_description(i).col_type = 1 THEN
        DBMS_SQL.DEFINE_COLUMN(cursor_id, i, string_value, 4000);
    ELSIF table_description(i).col_type = 112 THEN
        DBMS_SQL.DEFINE_COLUMN(cursor_id, i, clob_value);
    END IF;
END LOOP;

WHILE DBMS_SQL.FETCH_ROWS(cursor_id) > 0 LOOP
    FOR i IN 1..column_count LOOP
        DBMS_OUTPUT.PUT_LINE(table_description(i).col_name || ': datatype=' || table_description(i).col_type);
        IF (table_description(i).col_type = 1) THEN
        BEGIN
            DBMS_SQL.COLUMN_VALUE(cursor_id, i, string_value);
            DBMS_OUTPUT.PUT_LINE('Value: ' || string_value);
        END;
        ELSIF (table_description(i).col_type = 112) THEN
        BEGIN
            DBMS_SQL.COLUMN_VALUE(cursor_id, i, clob_value);
            DBMS_OUTPUT.PUT_LINE('Value: ' || clob_value);
        END;
        -- add other data types
        END IF;
    END LOOP;
END LOOP;

DBMS_SQL.CLOSE_CURSOR(cursor_id);
END;

カーソルがどのように消費されるかによって異なります。アプリケーションを使用する場合は非常に簡単ですが、PL/SQL を使用する場合は少し難しくなります。

于 2015-08-24T21:03:49.027 に答える