oracle 动态函数将嵌套的XML有效负载展平为行和列

u0sqgete  于 2023-06-22  发布在  Oracle
关注(0)|答案(1)|浏览(134)

不管xml结构如何,它可以是例如父和子,或者可以是父、子、孙等等,但是我希望能够解析有效负载,并有一个函数将任何XML文件转换和展平为表中的行和列。
这个想法是创建一个函数,然后使用SQL查询调用它。理想情况下,我将创建一个对象和表,然后将结果通过管道传输到临时表。
我已经搜索了高和低,还没有找到任何通用的甲骨文。我发现的例子是,一个函数已经被构建来容纳一个特定的xml,但是这个函数必须足够聪明,通过我假设的嵌套元素使用某种循环来动态创建列和行。

gc0ot86w

gc0ot86w1#

要执行您想要的操作,您需要使用函数“RETURN ANYDATASET PIPELINED USING package_name”,传递XML和所需的参数:根节点的名称、行节点的名称、“子”节点的名称、if“id”的名称以及其他列的名称。
在包中,您需要实现ODCI接口:ODCITableDescribe、ODCITablePrepare、ODCITableStart、ODCITableFetch、ODCITableClose。
在ODCITableDescribe中,您必须根据参数动态生成查询,然后调用DBMS_SQL.PARSE、DBMS_SQL.DESCRIBE_COLUMNS2。您必须发明自己的方法来元描述结果的列类型(NUMBER,DATE,...),否则它们都将是文本的。您将需要为行类型(DBMS_TYPES.TYPECODE_OBJECT)和ANYDATASET(DBMS_TYPES.typecode_table)构建ANYDATA meta描述,并使用ANYTYPE.BEGINCREATE/ENDCREATE。
您可以使用以下示例作为源代码,以激发生成查询的“模板”(当然没有CTE,只是在这里测试和理解它的作用):

with data(xml) as (
    select xmltype(q'{<rows>
    <row>
        <id>1</id>
        <name>A</name>
        <children>
            <row>
                <id>11</id>
                <name>A1</name>
                <children>
                    <row>
                        <id>111</id>
                        <name>A11</name>
                    </row>
                    <row>
                        <id>112</id>
                        <children>
                            <row>
                                <id>1121</id>
                                <name>A121</name>
                            </row>
                        </children>
                    </row>
                    <row>
                        <id>113</id>
                    </row>
                </children>
            </row>
        </children>
    </row>
    <row>
        <id>2</id>
        <children>
            <row>
                <id>21</id>
                <name>B1</name>
            </row>
        </children>
    </row>
</rows>}') as xml from dual
)
-- root nodes only
select t.id, t.name, null as parent_id
from data d,
xmltable(
        -- here you should build the path of first level rows bases on you parameters
        '/rows/row' passing d.xml
        columns
            -- the column identifying the rows
            id path 'id',
            -- one path per "other" columns...
            name path 'name'
    ) t
union all 
-- all children nodes
select t.id, t.name, t.parent_id 
from data d,
xmltable(
        -- you will need to have one attribute per "other" column
        -- and build dynamically the path of the children rows
        'for $c in //row/children/row 
            return <child id="{$c/id}" name="{$c/name}" parent_id="{$c/../../id}">{$c}</child>' passing d.xml
        columns
            -- the id column
            id path '@id',
            -- one path per "other" columns...
            name path '@name',
            -- plus the "parent" id
            parent_id path '@parent_id'
    ) t
;

相关问题