oracle-databasexmltableoracle-xml-db

got multi-item sequence


My intention is to "select the data where container number is equals to input data" (kind of search functionality). I am facing an issue when I am trying to retrieve the data, with a problem at where condition:

d:goodsShipments/d:consignment/d:transportEquipment/d:id/text()

Here I am getting multiple data. I don't know how to iterate it in the where condition.

My query is:

My source XML is:

How i can select all the declaration where sealId is 5678? how deal with the where condition in this case?


Solution

  • You have multiple containers per consignment, and you're filtering based on LRN after extracting that from the raw XML; so you need to use nested XMLTable objects. The first one gets the data from the declaration and extracts the consignments as a sub-XMLType. That is then passed to the second XMLTable which extracts the container information.

    SELECT x1.lrn, x1.username, x2.containerNumber
    FROM dmsimport_decl d
    CROSS JOIN XMLTable(
      XMLNAMESPACES(DEFAULT 'http://www.xxxx.invalid/xxxx/xxx/schema/xxx',
        'http://www.xxxx.invalid/xxx/schema/common' AS "c",
        'http://www.xxxx.invalid/xxxx/xxx/schema/xxx' AS "d"),
      '/d:declaration'
      PASSING d.object_value
      COLUMNS
        lrn VARCHAR2(35 CHAR)
          PATH 'c:declarationHeader/c:localReferenceNumber/text()',
        username CHAR(25)
          PATH 'c:declarationHeader/c:username/text()',
        consignment XMLType
          PATH 'd:goodsShipments/d:consignment'
    ) x1
    CROSS JOIN XMLTable(
      XMLNAMESPACES(DEFAULT 'http://www.xxxx.invalid/xxxx/xxx/schema/xxx',
        'http://www.xxxx.invalid/xxx/schema/common' AS "c",
        'http://www.xxxx.invalid/xxxx/xxx/schema/xxx' AS "d"),
      '//d:transportEquipment'
      PASSING x1.consignment
      COLUMNS
        containerNumber VARCHAR2(35 CHAR)
          PATH 'd:id/text()'
    ) x2
    WHERE x1.lrn = 'NLDMS111111150010950';
    

    With your (updated) sample XML, that produces:

    LRN                                 USERNAME                  CONTAINERNUMBER                   
    ----------------------------------- ------------------------- -----------------------------------
    NLDMS111111150010950                testSC testSC             abcd                               
    NLDMS111111150010950                testSC testSC             bcde                               
    NLDMS111111150010950                testSC testSC             cdef                               
    NLDMS111111150010950                testSC testSC             defg                               
    NLDMS111111150010950                testSC testSC             efgh                               
    

    Hopefully that is what you want to see.

    Quick SQL Fiddle demo.

    You could also use a more complicated XPath to keep it within a single XMLTable, but I think this is clearer.