got multi-item sequence

2019-04-16 04:01发布

问题:

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?

回答1:

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.



回答2:

You can use the below query to iterate and get the id's from container component..

SELECT x1.lrn, x1.username, x2.containerNumber
FROM dmsimport_decl d
CROSS JOIN XMLTable(
  XMLNAMESPACES(DEFAULT 'http://www.SSSSSSS/dmsimport',
    'http://www.SSSSSSScommon' AS "c",
    'http://www.SSSSSSSS/dmsimport' 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()',
    containerComponent XMLType
      PATH 'd:goodsShipments/d:goodsItems'
) x1.
CROSS JOIN XMLTable(
  XMLNAMESPACES(DEFAULT 'http://www.SSSSSSSSS/dmsimport',
    'http://www.SSSSSS/common' AS "c",
    'http://www.SSSSSSSS/dmsimport' AS "d"),
  '//d:containerComponent'
  PASSING x1.containerComponent
  COLUMNS
    containerNumber VARCHAR2(35 CHAR)
      PATH 'd:id/text()'
) x2
WHERE x1.lrn = 'NL123456789160000464';