IN y NOT IN para columna XML

8

Tengo una tabla con una columna xml. Xml es similar a

<Root>
  <Row>
    <user>abc</user>
    <Rowid>1</Rowid>
  </Row>
  <Row>
    <user>vf</user>
    <Rowid>2</Rowid>
  </Row>
  <Row>
    <user>ert</user>
    <Rowid>3</Rowid>
  </Row>
  <Maxrowid>3</Maxrowid>
</Root>

Ahora debajo de la consulta, devuelva la columna sl_no y la columna myxml de las filas que contienen la columna xml con los valores 'abc' o 'xyz' en el nodo 'usuario' (). Debajo de la consulta estoy usando una opción similar a IN de sql.

SELECT
    [mytable].[Sl_no],
    [mytable].[myxmlcolumn]
    FROM [mydb].dbo.[mytable]
    WHERE
        [myxmlcolumn].exist('for $x in /Root/Row where (($x/user[fn:upper-case(.)=(''ABC'',''XYZ'')])) return $x') > 0

Quiero un tipo de consulta similar que funcione igual que sql 'NOT IN'. Eso es en mi caso, quiero filas que no tengan valores 'abc' o 'xyz' en el nodo 'usuario' () en la columna xml. Así que por favor ayúdame en esto.

Investigador de TI
fuente

Respuestas:

12

El método exist () (tipo de datos xml) devuelve a bit.
1si se encuentra al menos un nodo y 0si no se encuentran nodos (conjunto de resultados vacío).

Para obtener las filas donde ni existe ABCni XYZexiste, solo tiene que comparar el resultado de existcon 0.

[myxmlcolumn].exist('for $x in /Root/Row 
                     where (($x/user[fn:upper-case(.)=(''ABC'',''XYZ'')])) 
                     return $x') = 0

Su consulta FLWOR puede reescribirse usando un predicado en el nodo de usuario,

select Sl_no,
       myxmlcolumn
from mytable
where myxmlcolumn.exist('/Root/Row/user[fn:upper-case(text()[1]) = ("ABC", "XYZ")]') = 0

Y para la INversión de la consulta, verifica si se existdevuelve 1.

select Sl_no,
       myxmlcolumn
from mytable
where myxmlcolumn.exist('/Root/Row/user[fn:upper-case(text()[1]) = ("ABC", "XYZ")]') = 1
Mikael Eriksson
fuente