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

时间:2016-05-24 13:17:10

标签: xml oracle tsql plsql

在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。

2 个答案:

答案 0 :(得分: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参数的过程)。

答案 1 :(得分:1)

类似的东西:

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 )
);