我有以下表格:
CREATE TABLE DBO.FACT_SERVICES (
SVC_ID INTEGER NOT NULL,
SVC_NAME VARCHAR(50) NOT NULL,
SVC_DESC VARCHAR(2000) NULL,
STATUS VARCHAR(50) NULL
);
CREATE TABLE DBO.FACT_TYPES (
FACT_ID INTEGER NOT NULL,
FACT_NAME VARCHAR(100) NOT NULL,
FACT_DESC VARCHAR(2000) NULL,
PARENT_FACT_ID INTEGER NULL,
);
CREATE TABLE DBO.FACT_TYPE_SVC (
FACT_ID INTEGER NOT NULL,
SVC_ID INTEGER NOT NULL,
STATUS VARCHAR(50) NULL
);
我创建了以下查询来获取 XML 层次结构:
SELECT
XMLElement("services",
XMLAgg(
XMLElement("service",
XMLAttributes(svc.svc_id as "id", svc.svc_name as "name"),
XMLElement("facts",
(SELECT
XMLAgg(
XMLElement("fact",
XMLAttributes(FT.FACT_ID as "id", FT.FACT_NAME AS "name"),
(SELECT
XMLAgg(
XMLElement("fact",
XMLAttributes(FT2.FACT_ID as "id", FT2.FACT_NAME as "name")
)
)
FROM
DBO.FACT_TYPES FT2
WHERE
FT2.PARENT_FACT_ID = FT.FACT_ID
)
)
)
FROM
DBO.FACT_TYPES FT
INNER JOIN DBO.FACT_TYPE_SVC FTS ON FTS.FACT_ID = FT.FACT_ID
WHERE
FTS.SVC_ID = SVC.SVC_ID AND
LOWER(FTS.STATUS) = 'active' AND
PARENT_FACT_ID IS NULL
)
)
)
)
)
FROM
DBO.FACT_SERVICES SVC
这将创建以下 XML:
<services>
<service id="1" name="ABC Plan">
<facts>
<fact id="77" name="Basic Service">
<fact id="71" name="Form XYZ Schedules"></fact>
<fact id="101" name="Per Participant Fee"></fact>
<fact id="103" name="Base Fee"></fact>
</fact>
</facts>
</service>
</services>
但是,我想编写查询,以便我可以拥有 FACT_TYPE 的无限子级。我正在使用 Oracle 中的 dbms_xmlgen.getXmlType(dbms_xmlgen.newContextFromHierarchy()) 函数,但我似乎无法让它与服务部分一起使用。我可以让它直接从 DBO.FACT_TYPES 表中工作,如下所示:
SELECT
XMLElement("facts",
(select dbms_xmlgen.getXmlType(dbms_xmlgen.newContextFromHierarchy('
select level,
XMLElement("fact",
XMLAttributes(ft.fact_id as "id", ft.fact_name as "name")
)
from
dbo.fact_types ft
start with parent_fact_id is null
connect by prior fact_id = parent_fact_id
order siblings by fact_name
')) from SYS.DUAL
)
)AS XML_DATA
FROM
SYS.DUAL
返回:
<facts>
<fact id="77" name="Basic Administrative Service">
<fact id="103" name="Base Fee"/>
<fact id="71" name="Form 5500+ Schedules"/>
<fact id="101" name="Per Participant Fee"/>
</fact>
</facts>
因此,我尝试创建一个传入服务 ID 的函数,它返回应该进入服务层次结构的内部 XML:
功能
create or replace
FUNCTION dbo.FACT_GET_FACTS_XML(SERVICE_ID INT)
RETURN XMLTYPE AS
INNER_SELECT DBMS_XMLGEN.ctxhandle;
MY_RESULT XMLTYPE;
BEGIN
INNER_SELECT := DBMS_XMLGEN.newcontextfromhierarchy(
'select level,
XMLElement("fact",
XMLAttributes(ft.fact_id as "id", ft.fact_name as "name")
)
from
dbo.fact_types ft
inner join dbo.fact_type_svc fts on fts.fact_id = ft.fact_id
where
fts.svc_id = ' || to_char(SERVICE_ID) || '
start with ft.parent_fact_id is null
connect by prior ft.fact_id = ft.parent_fact_id
order siblings by ft.fact_name');
MY_RESULT := DBMS_XMLGEN.getxmltype(INNER_SELECT);
DBMS_XMLGEN.closeContext(INNER_SELECT);
RETURN MY_RESULT;
END;
使用此父查询:
SELECT
XMLElement("services",
XMLAgg(
XMLElement("service",
XMLAttributes(svc.svc_id as "id", svc.svc_name as "name"),
(SELECT
XMLElement("facts",
DBO.FACT_GET_FACTS_XML(SVC.SVC_ID))
FROM
SYS.DUAL)
)
)
)
FROM
DBO.FACT_SERVICES SVC
现在我得到了这个结果:
<services>
<service id="1" name="ABC Plan">
<facts>
<fact id="77" name="Basic Service">
<fact id="103" name="Base Fee"/>
<fact id="71" name="Form XYZ Schedules"/>
<fact id="101" name="Per Participant Fee"/>
<fact id="103" name="Base Fee"/>
<fact id="71" name="Form XYZ Schedules"/>
<fact id="101" name="Per Participant Fee"/>
</fact>
</facts>
</service>
<service id="4" name="Health Retirement Account">
<facts>
<fact id="71" name="Form XYZ Schedules"/>
<fact id="71" name="Form XYZ Schedules"/>
</facts>
</service>
</services>
我想要的 XML 如下:
<services>
<service id="1" name="ABC Plan">
<facts>
<fact id="77" name="Basic Service">
<fact id="71" name="Form XYZ Schedules"></fact>
<fact id="101" name="Per Participant Fee"></fact>
<fact id="103" name="Base Fee"></fact>
</fact>
</facts>
</service>
<service id="4" name="Health Retirement Account">
<facts></facts>
</service>
</services>
但是能够将孩子添加到 fact id="71" 并让它显示在下面。
编辑 这是我目前在表格中的数据
INSERT INTO DBO.FACT_TYPES (FACT_ID, FACT_NAME, FACT_DESC, PARENT_FACT_ID) VALUES (71, 'Form 5500+ Schedules', '', 77);
INSERT INTO DBO.FACT_TYPES (FACT_ID, FACT_NAME, FACT_DESC, PARENT_FACT_ID) VALUES (77, 'Basic Administrative Service', 'Master Group', );
INSERT INTO DBO.FACT_TYPES (FACT_ID, FACT_NAME, FACT_DESC, PARENT_FACT_ID) VALUES (101, 'Per Participant Fee', '', 77);
INSERT INTO DBO.FACT_TYPES (FACT_ID, FACT_NAME, FACT_DESC, PARENT_FACT_ID) VALUES (103, 'Base Fee', '', 77);
INSERT INTO DBO.FACT_TYPE_SVC (FACT_ID, SVC_ID, STATUS) VALUES (77, 1, 'ACTIVE');
INSERT INTO DBO.FACT_TYPE_SVC (FACT_ID, SVC_ID, STATUS) VALUES (77, 3, 'ACTIVE');
INSERT INTO DBO.FACT_TYPE_SVC (FACT_ID, SVC_ID, STATUS) VALUES (71, 1, 'ACTIVE');
INSERT INTO DBO.FACT_TYPE_SVC (FACT_ID, SVC_ID, STATUS) VALUES (71, 3, 'ACTIVE');
INSERT INTO DBO.FACT_TYPE_SVC (FACT_ID, SVC_ID, STATUS) VALUES (71, 4, 'ACTIVE');
INSERT INTO DBO.FACT_TYPE_SVC (FACT_ID, SVC_ID, STATUS) VALUES (101, 1, 'ACTIVE');
INSERT INTO DBO.FACT_TYPE_SVC (FACT_ID, SVC_ID, STATUS) VALUES (101, 3, 'ACTIVE');
INSERT INTO DBO.FACT_TYPE_SVC (FACT_ID, SVC_ID, STATUS) VALUES (101, 21, 'ACTIVE');
INSERT INTO DBO.FACT_TYPE_SVC (FACT_ID, SVC_ID, STATUS) VALUES (103, 1, 'ACTIVE');
INSERT INTO DBO.FACT_TYPE_SVC (FACT_ID, SVC_ID, STATUS) VALUES (103, 3, 'ACTIVE');
INSERT INTO DBO.FACT_SERVICES (SVC_ID, SVC_NAME, SVC_DESC, STATUS) VALUES (1, '401(k) Plan', '', 'Active');
INSERT INTO DBO.FACT_SERVICES (SVC_ID, SVC_NAME, SVC_DESC, STATUS) VALUES (4, 'Health Retirement Account', '', 'Active');
INSERT INTO DBO.FACT_SERVICES (SVC_ID, SVC_NAME, SVC_DESC, STATUS) VALUES (5, 'Profit Sharing Plan', '', 'Active');
INSERT INTO DBO.FACT_SERVICES (SVC_ID, SVC_NAME, SVC_DESC, STATUS) VALUES (2, 'Plan Money Purchase', '', 'Active');
INSERT INTO DBO.FACT_SERVICES (SVC_ID, SVC_NAME, SVC_DESC, STATUS) VALUES (3, '403(b) Plan', '', 'Active');
INSERT INTO DBO.FACT_SERVICES (SVC_ID, SVC_NAME, SVC_DESC, STATUS) VALUES (21, 'ESOP Plan', '', 'Active');
INSERT INTO DBO.FACT_SERVICES (SVC_ID, SVC_NAME, SVC_DESC, STATUS) VALUES (22, 'Health Savings Account', '', 'Active');
INSERT INTO DBO.FACT_SERVICES (SVC_ID, SVC_NAME, SVC_DESC, STATUS) VALUES (23, '457 Plan', '', 'Active');
INSERT INTO DBO.FACT_SERVICES (SVC_ID, SVC_NAME, SVC_DESC, STATUS) VALUES (24, 'Simple Plan ', '', 'Active');
INSERT INTO DBO.FACT_SERVICES (SVC_ID, SVC_NAME, SVC_DESC, STATUS) VALUES (25, '503c Plan', '', 'Active');
INSERT INTO DBO.FACT_SERVICES (SVC_ID, SVC_NAME, SVC_DESC, STATUS) VALUES (26, 'Cafeteria Plan', '', 'Active');