XmlElement 子查询中的 Oracle 序列问题
Oracle squence problem in XmlElement subquery
有这个功能:
CREATE OR REPLACE FUNCTION get_seq_xi_pl9_wws2lvs
RETURN NUMBER
IS
BEGIN
RETURN seq_xi_pl9_wws2lvs.NEXTVAL;
END get_seq_xi_pl9_wws2lvs;
并使用此示例查询:
SELECT id,
''
|| XMLELEMENT ("Request",
XMLELEMENT ("TransaktionsNr",
id),
XMLELEMENT ("Zeitstempel",
0),
(SELECT xmldaten
FROM DUAL)) AS xml_final
FROM (SELECT id,
xmldaten
FROM (SELECT get_seq_xi_pl9_wws2lvs AS id,
(XMLELEMENT ("Bestellung",
XMLELEMENT ("BestellNr",
tmp_bsp.BestellNr))) AS xmlDaten
FROM (SELECT 4711 AS BestellNr
FROM DUAL
UNION ALL
SELECT 4712 AS BestellNr
FROM DUAL) tmp_bsp));
这是输出:
ID
XML_FINAL
347816
<Request><TransaktionsNr>347817</TransaktionsNr><Zeitstempel>0</Zeitstempel><Bestellung><BestellNr>4711</BestellNr></Bestellung></Request>
347818
<Request><TransaktionsNr>347819</TransaktionsNr><Zeitstempel>0</Zeitstempel><Bestellung><BestellNr>4712</BestellNr></Bestellung></Request>
在一行中,字段“ID”和 XmlElement“TransaktionsNr”(也有“ID”作为值)具有不同的值 - 我希望它们相同。
我做错了什么?
SQL 引擎选择不具体化子查询,并将函数调用推送到外部查询,在那里它会为每一行调用多次。您需要强制在调用它的子查询中评估函数,而不是允许 SQL 引擎重写查询。
一种方法是使用 sub-query 分解子句和具体化提示:
WITH data (bestellnr) AS (
SELECT 4711 AS BestellNr FROM DUAL
UNION ALL
SELECT 4712 AS BestellNr FROM DUAL
),
ids (id, bestellnr) AS (
SELECT /*+ materialize */
get_seq_xi_pl9_wws2lvs,
bestellnr
FROM data
)
SELECT id,
XMLELEMENT (
"Request",
XMLELEMENT ("TransaktionsNr", id),
XMLELEMENT ("Zeitstempel", 0),
XMLELEMENT(
"Bestellung",
XMLELEMENT ("BestellNr", BestellNr)
)
).getStringVal() AS xml_final
FROM ids;
输出:
ID
XML_FINAL
1
<Request><TransaktionsNr>1</TransaktionsNr><Zeitstempel>0</Zeitstempel><Bestellung><BestellNr>4711</BestellNr></Bestellung></Request>
2
<Request><TransaktionsNr>2</TransaktionsNr><Zeitstempel>0</Zeitstempel><Bestellung><BestellNr>4712</BestellNr></Bestellung></Request>
如果您不想使用提示,那么您可以添加(看似无用的)过滤器 WHERE ROWNUM >= 1
,这也将强制 SQL 引擎在此时具体化查询。
SELECT id,
XMLELEMENT (
"Request",
XMLELEMENT ("TransaktionsNr", id),
XMLELEMENT ("Zeitstempel", 0),
XMLELEMENT(
"Bestellung",
XMLELEMENT ("BestellNr", BestellNr)
)
).getStringVal() AS xml_final
FROM (
SELECT get_seq_xi_pl9_wws2lvs AS id,
bestellnr
FROM (
SELECT 4711 AS BestellNr FROM DUAL UNION ALL
SELECT 4712 AS BestellNr FROM DUAL
)
WHERE ROWNUM >= 1
);
db<>fiddle here
有这个功能:
CREATE OR REPLACE FUNCTION get_seq_xi_pl9_wws2lvs
RETURN NUMBER
IS
BEGIN
RETURN seq_xi_pl9_wws2lvs.NEXTVAL;
END get_seq_xi_pl9_wws2lvs;
并使用此示例查询:
SELECT id,
''
|| XMLELEMENT ("Request",
XMLELEMENT ("TransaktionsNr",
id),
XMLELEMENT ("Zeitstempel",
0),
(SELECT xmldaten
FROM DUAL)) AS xml_final
FROM (SELECT id,
xmldaten
FROM (SELECT get_seq_xi_pl9_wws2lvs AS id,
(XMLELEMENT ("Bestellung",
XMLELEMENT ("BestellNr",
tmp_bsp.BestellNr))) AS xmlDaten
FROM (SELECT 4711 AS BestellNr
FROM DUAL
UNION ALL
SELECT 4712 AS BestellNr
FROM DUAL) tmp_bsp));
这是输出:
ID | XML_FINAL |
---|---|
347816 | <Request><TransaktionsNr>347817</TransaktionsNr><Zeitstempel>0</Zeitstempel><Bestellung><BestellNr>4711</BestellNr></Bestellung></Request> |
347818 | <Request><TransaktionsNr>347819</TransaktionsNr><Zeitstempel>0</Zeitstempel><Bestellung><BestellNr>4712</BestellNr></Bestellung></Request> |
在一行中,字段“ID”和 XmlElement“TransaktionsNr”(也有“ID”作为值)具有不同的值 - 我希望它们相同。
我做错了什么?
SQL 引擎选择不具体化子查询,并将函数调用推送到外部查询,在那里它会为每一行调用多次。您需要强制在调用它的子查询中评估函数,而不是允许 SQL 引擎重写查询。
一种方法是使用 sub-query 分解子句和具体化提示:
WITH data (bestellnr) AS (
SELECT 4711 AS BestellNr FROM DUAL
UNION ALL
SELECT 4712 AS BestellNr FROM DUAL
),
ids (id, bestellnr) AS (
SELECT /*+ materialize */
get_seq_xi_pl9_wws2lvs,
bestellnr
FROM data
)
SELECT id,
XMLELEMENT (
"Request",
XMLELEMENT ("TransaktionsNr", id),
XMLELEMENT ("Zeitstempel", 0),
XMLELEMENT(
"Bestellung",
XMLELEMENT ("BestellNr", BestellNr)
)
).getStringVal() AS xml_final
FROM ids;
输出:
ID XML_FINAL 1 <Request><TransaktionsNr>1</TransaktionsNr><Zeitstempel>0</Zeitstempel><Bestellung><BestellNr>4711</BestellNr></Bestellung></Request> 2 <Request><TransaktionsNr>2</TransaktionsNr><Zeitstempel>0</Zeitstempel><Bestellung><BestellNr>4712</BestellNr></Bestellung></Request>
如果您不想使用提示,那么您可以添加(看似无用的)过滤器 WHERE ROWNUM >= 1
,这也将强制 SQL 引擎在此时具体化查询。
SELECT id,
XMLELEMENT (
"Request",
XMLELEMENT ("TransaktionsNr", id),
XMLELEMENT ("Zeitstempel", 0),
XMLELEMENT(
"Bestellung",
XMLELEMENT ("BestellNr", BestellNr)
)
).getStringVal() AS xml_final
FROM (
SELECT get_seq_xi_pl9_wws2lvs AS id,
bestellnr
FROM (
SELECT 4711 AS BestellNr FROM DUAL UNION ALL
SELECT 4712 AS BestellNr FROM DUAL
)
WHERE ROWNUM >= 1
);
db<>fiddle here