如何使用 PL-SQL 查询包含 XML 的 Clob 节点

Posted

技术标签:

【中文标题】如何使用 PL-SQL 查询包含 XML 的 Clob 节点【英文标题】:How to Query an XML-containing Clob for nodes with PL-SQL 【发布时间】:2016-05-24 13:17:10 【问题描述】:

在 T-SQL 中我这样做:

CREATE PROCEDURE [dbo].[ps_GetAuditUpdatesRequired]
@AuditXML xml
AS
SET NOCOUNT ON

SELECT 
    doc.col.value('@id', 'int') AS id
FROM  
    @AuditXML.nodes('/rths/rth') AS doc(col)
WHERE (
  -- Get anything needs to be deleted and does exist in the database already
  doc.col.value('@method', 'nvarchar(16)') = 'DELETE' AND EXISTS ( SELECT 1 FROM audits_ WHERE doc.col.value('@id', 'int') = audits_.Id_RetinaId ) OR
  -- Get anything that is not set to be deleted and does not already exist with a newer version
  doc.col.value('@method', 'nvarchar(16)') != 'DELETE' AND NOT EXISTS ( SELECT 1 FROM audits_ WHERE doc.col.value('@id', 'int') = audits_.Id_RetinaId AND doc.col.value('@versionSerial', 'int' ) <= audits_.nl_VersionSerial)
  )

SET NOCOUNT OFF

我怎样才能在 oracle 中做到这一点? 注意:AuditXML 参数在 Oracle 版本中将是一个 CLOB。

【问题讨论】:

您能否添加一个示例 XML 文档和其他数据,以及您希望发生什么? 你能给出你想选择的元素/属性的 XPath 吗? 【参考方案1】:

如果我了解您在做什么,您需要an XMLTable 将节点属性提取为关系数据;然后,您可以在 where 子句中使用由此生成的列:

SELECT doc.id
FROM XMLTable('/rths/rth'
  PASSING XMLType(:auditXML)
  COLUMNS id NUMBER PATH '@id',
    method NVARCHAR2(16) PATH '@method',
    versionSerial NUMBER PATH '@versionSerial'
) doc
WHERE (
  -- Get anything needs to be deleted and does exist in the database already
  doc.method = 'DELETE' AND EXISTS (
    SELECT 1
    FROM audits_
    WHERE doc.id = audits_.Id_RetinaId
)
OR (
  -- Get anything that is not set to be deleted and does not already exist with a newer version
  doc.method != 'DELETE' AND NOT EXISTS (
    SELECT 1
    FROM audits_
    WHERE doc.id = audits_.Id_RetinaId
    AND doc.versionSerial <= audits_.nl_VersionSerial)
  )
)

我使用:auditXML 作为绑定变量,但您可以传入表格列或字符串文字 - 尽管后者在纯 SQL 中限制为 4K(最高 12c)。

Oracle 过程无法像在 T-SQL 中那样返回查询结果。在一个过程中,查询必须选择 into 一些东西,但是根据你使用它的方式,你可能实际上需要一个流水线表函数和一个游标循环来将行输出,或者一个函数返回一个引用游标(或具有引用游标 OUT 参数的过程)。

【讨论】:

这是一个美丽的人。我必须使用字符串文字。我应该很好,因为我正在运行 12 c。谢谢!【参考方案2】:

类似:

SELECT id
FROM   (
  SELECT EXTRACTVALUE( column_value, '/rth/@method' ) AS method,
         EXTRACTVALUE( column_value, '/rth/@id' ) AS id,
         EXTRACTVALUE( column_value, '/rth/@versionSerial' ) AS serial
  FROM   TABLE(
           XMLSequence(
             EXTRACT( XMLType( auditXml ), '/rths/rth' )
           )
         )
) x
WHERE  (
      method = 'DELETE'
  AND EXISTS( SELECT 1
              FROM   audits_ a
              WHERE  x.id = a.Id_RetinaId )
)
OR
(
      ( method IS NULL OR method <> 'DELETE' )
  AND NOT EXISTS( SELECT 1
                  FROM   audits_ a
                  WHERE  x.id = a.Id_RetinaId
                  AND    x.serial <= a.nl_VersionSerial )
);

【讨论】:

这可行(当然),但extract 和extractvalue 已弃用。

以上是关于如何使用 PL-SQL 查询包含 XML 的 Clob 节点的主要内容,如果未能解决你的问题,请参考以下文章

PL-SQL 中的 contains() 是如何工作的?

在 PL-SQL 存储过程中为 XML 中的每个段生成唯一 ID

如何在 PL-SQL 上更改之前获取视图/触发器?

PL-Sql 用户连接

在 Asp.net 页面中组织一组 PL-sql 查询

PL-SQL