簡體   English   中英

如何從 XML clob 列中選擇計數?

[英]How to select count from XML clob column?

我正在嘗試選擇 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

我認為將 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);

有幾種方法可以做到這一點。 一種是使用 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

但我不確定這會比第一種選擇更快。

另一種選擇是對每個節點使用單獨的 XMLQuery 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<> 擺弄一個簡單的 XML CLOB,它會拋出您看到的錯誤,以及這三種方法(包括將 XMLQuery 結果轉換為數字)。

我也有興趣看看其他人想出了什么。


XPath 計數返回 ORA-06502:PL/SQL:超過 10 行時的數值或值錯誤。 當我添加 where 子句時效果很好

當我添加 id = some_number 或顯示 10 行時,它會起作用。

如果處理的行有一個空diagram ,這將出錯; 但是您可以通過添加where diagram is not null來排除那些。

數據庫<>小提琴

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM