oracle xmltable与另一个表中的列

时间:2015-05-28 04:18:34

标签: sql xml oracle xmltable

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
 }

请告诉我这是否可行以及如何进行?

1 个答案:

答案 0 :(得分:0)

我想到的一个选项是动态sql和ref游标。

这样的事情:

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会更加困难。