如何 select 从 XML clob 列开始计数?
How to select count from XML clob column?
我正在尝试 select XML(CLOB) 列中的标签数。
我试过
select regexp_count(diagram, 'userTask id=', 1, 'c') as "User Tasks",
regexp_count(diagram, 'task id=', 1, 'c') as "Task"
from process_table
它有效,但是我需要比使用 regexp_count 更快地获得输出。
我试过:
select count(xt.task),
count(xt.userTask)
from process_table process
cross join xmltable(
xmlnamespaces(default 'http://www.omg.org/spec/BPMN/20100524/MODEL'),
'//definitions/process' passing xmltype(process.diagram)
columns
task varchar2(20) path 'task',
userTask varchar2(60) path 'userTask'
) xt
但是,我收到一个错误 ORA-19279: XPTY0004 - XQuery dynamic type mismatch: expected singleton sequence - got multi-item sequence
有几种方法可以做到这一点。一种是使用 XMLTable 查找任一子节点,获取节点名称,并计算每个节点出现的次数:
select
count(case when xt.name = 'userTask' then name end) as userTasks,
count(case when xt.name = 'task' then name end) as tasks
from process_table process
cross join xmltable(
xmlnamespaces(default 'http://www.omg.org/spec/BPMN/20100524/MODEL'),
'//definitions/process/(userTask|task)' passing xmltype(process.diagram)
columns
name varchar2(20) path 'name(.)'
) xt
或者您可以使用 FLWOR 表达式同时获取两种子节点类型的计数:
select userTasks, tasks
from process_table process
cross join xmltable(
xmlnamespaces(default 'http://www.omg.org/spec/BPMN/20100524/MODEL'),
'let $u := count(//definitions/process/userTask)
let $s := count(//definitions/process/task)
return <x><u>{$u}</u><s>{$s}</s></x>'
passing xmltype(process.diagram)
columns
userTasks number path 'u',
tasks number path 's'
) xt
但我不确定最终会比第一个选项更快。
另一种选择是使用单独的XML查询每个节点的 XPath 计数来检查:
select
xmlquery('declare default element namespace "http://www.omg.org/spec/BPMN/20100524/MODEL";
count(//definitions/process/userTask)'
passing xmltype(diagram)
returning content) as userTasks,
xmlquery('declare default element namespace "http://www.omg.org/spec/BPMN/20100524/MODEL";
count(//definitions/process/task)'
passing xmltype(diagram)
returning content) as tasks
from process_table
db<>fiddle 使用一个简单的 XML CLOB 抛出您看到的错误,以及这三种方法(包括将 XML 查询结果转换为数字)。
我也很想看看其他人的想法。
XPath counts returns ORA-06502: PL/SQL: numeric or value error when there are more than 10 rows. When I add where clause works perfectly
When I add id = some_number, or when 10 rows are displayed it works.
如果处理的行有空值,这将出错diagram
;但您可以通过添加 where diagram is not null
.
来排除这些
我认为将 XML 存储为 XMLTYPE
而不是 CLOB
会更好。然后你可以创建一个虚拟列,你甚至可以在它上面创建索引。像这样:
CREATE TABLE PROCESS_TABLE (
DIAGRAM XMLTYPE,
TASK_COUNT INTEGER GENERATED ALWAYS AS (
TO_NUMBER(CAST(XMLQUERY('count(/definitions/process/task)' PASSING BY VALUE "DIAGRAM" RETURNING CONTENT) AS VARCHAR2(100)))
) VIRTUAL,
USER_TASK_COUNT INTEGER GENERATED ALWAYS AS (
TO_NUMBER(CAST(XMLQUERY('count(/definitions/process/userTask)' PASSING BY VALUE "DIAGRAM" RETURNING CONTENT) AS VARCHAR2(100)))
) VIRTUAL
)
XMLTYPE DIAGRAM STORE AS SECUREFILE BINARY XML;
CREATE INDEX IND_TASK_COUNT ON process_table (TASK_COUNT);
我正在尝试 select XML(CLOB) 列中的标签数。
我试过
select regexp_count(diagram, 'userTask id=', 1, 'c') as "User Tasks",
regexp_count(diagram, 'task id=', 1, 'c') as "Task"
from process_table
它有效,但是我需要比使用 regexp_count 更快地获得输出。
我试过:
select count(xt.task),
count(xt.userTask)
from process_table process
cross join xmltable(
xmlnamespaces(default 'http://www.omg.org/spec/BPMN/20100524/MODEL'),
'//definitions/process' passing xmltype(process.diagram)
columns
task varchar2(20) path 'task',
userTask varchar2(60) path 'userTask'
) xt
但是,我收到一个错误 ORA-19279: XPTY0004 - XQuery dynamic type mismatch: expected singleton sequence - got multi-item sequence
有几种方法可以做到这一点。一种是使用 XMLTable 查找任一子节点,获取节点名称,并计算每个节点出现的次数:
select
count(case when xt.name = 'userTask' then name end) as userTasks,
count(case when xt.name = 'task' then name end) as tasks
from process_table process
cross join xmltable(
xmlnamespaces(default 'http://www.omg.org/spec/BPMN/20100524/MODEL'),
'//definitions/process/(userTask|task)' passing xmltype(process.diagram)
columns
name varchar2(20) path 'name(.)'
) xt
或者您可以使用 FLWOR 表达式同时获取两种子节点类型的计数:
select userTasks, tasks
from process_table process
cross join xmltable(
xmlnamespaces(default 'http://www.omg.org/spec/BPMN/20100524/MODEL'),
'let $u := count(//definitions/process/userTask)
let $s := count(//definitions/process/task)
return <x><u>{$u}</u><s>{$s}</s></x>'
passing xmltype(process.diagram)
columns
userTasks number path 'u',
tasks number path 's'
) xt
但我不确定最终会比第一个选项更快。
另一种选择是使用单独的XML查询每个节点的 XPath 计数来检查:
select
xmlquery('declare default element namespace "http://www.omg.org/spec/BPMN/20100524/MODEL";
count(//definitions/process/userTask)'
passing xmltype(diagram)
returning content) as userTasks,
xmlquery('declare default element namespace "http://www.omg.org/spec/BPMN/20100524/MODEL";
count(//definitions/process/task)'
passing xmltype(diagram)
returning content) as tasks
from process_table
db<>fiddle 使用一个简单的 XML CLOB 抛出您看到的错误,以及这三种方法(包括将 XML 查询结果转换为数字)。
我也很想看看其他人的想法。
XPath counts returns ORA-06502: PL/SQL: numeric or value error when there are more than 10 rows. When I add where clause works perfectly
When I add id = some_number, or when 10 rows are displayed it works.
如果处理的行有空值,这将出错diagram
;但您可以通过添加 where diagram is not null
.
我认为将 XML 存储为 XMLTYPE
而不是 CLOB
会更好。然后你可以创建一个虚拟列,你甚至可以在它上面创建索引。像这样:
CREATE TABLE PROCESS_TABLE (
DIAGRAM XMLTYPE,
TASK_COUNT INTEGER GENERATED ALWAYS AS (
TO_NUMBER(CAST(XMLQUERY('count(/definitions/process/task)' PASSING BY VALUE "DIAGRAM" RETURNING CONTENT) AS VARCHAR2(100)))
) VIRTUAL,
USER_TASK_COUNT INTEGER GENERATED ALWAYS AS (
TO_NUMBER(CAST(XMLQUERY('count(/definitions/process/userTask)' PASSING BY VALUE "DIAGRAM" RETURNING CONTENT) AS VARCHAR2(100)))
) VIRTUAL
)
XMLTYPE DIAGRAM STORE AS SECUREFILE BINARY XML;
CREATE INDEX IND_TASK_COUNT ON process_table (TASK_COUNT);