次のテーブルがあります。
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>
ただし、子をファクト 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');