Usando o SQL Server 2005 do XQuery selecionar todos os nós com um valor de atributo específico ou com esse atributo em falta

StackOverflow https://stackoverflow.com/questions/90023

  •  01-07-2019
  •  | 
  •  

Pergunta

Update: dando um exemplo muito mais completa .

As duas primeiras soluções oferecidas estavam certos ao longo das linhas do que eu estava tentando dizer não para fazer. Eu não posso saber local, ele precisa ser capaz de olhar para toda a árvore documento. Então uma solução ao longo destas linhas, com / Livros / especificado como o contexto não vai funcionar:

SELECT x.query('.') FROM @xml.nodes('/Books/*[not(@ID) or @ID = 5]') x1(x)

pergunta original com melhor exemplo:

Usando XQuery implementação I necessidade 2005 é para selecionar todos os nós em um documento XML SQL Server, apenas uma vez cada um e mantendo a sua estrutura original, mas apenas se eles estão faltando um atributo particular, ou que atributo tem um valor específico (passado pelo parâmetro). A consulta também tem que trabalhar em todo o documento XML (descendente-ou-auto eixo) em vez de selecionar a uma profundidade pré-definida.

Ou seja, cada nó individual aparecerá no documento resultante somente se ele e cada um de seus antepassados ??estão faltando o atributo, ou ter o atributo com um único valor específico.

Por exemplo:

Se este fosse o XML:

    DECLARE @Xml XML
    SET @Xml =
    N'
<Library>
  <Novels>
    <Novel category="1">Novel1</Novel>
    <Novel category="2">Novel2</Novel>
    <Novel>Novel3</Novel>
    <Novel category="4">Novel4</Novel>
  </Novels>
  <Encyclopedias>
    <Encyclopedia>
      <Volume>A-F</Volume>
      <Volume category="2">G-L</Volume>
      <Volume category="3">M-S</Volume>
      <Volume category="4">T-Z</Volume>
    </Encyclopedia>
  </Encyclopedias>
  <Dictionaries category="1">
    <Dictionary>Webster</Dictionary>
    <Dictionary>Oxford</Dictionary>
  </Dictionaries>
</Library>
    '

Um parâmetro de 1 para a categoria resultaria no seguinte:

<Library>
  <Novels>
    <Novel category="1">Novel1</Novel>
    <Novel>Novel3</Novel>
  </Novels>
  <Encyclopedias>
    <Encyclopedia>
      <Volume>A-F</Volume>
    </Encyclopedia>
  </Encyclopedias>
  <Dictionaries category="1">
    <Dictionary>Webster</Dictionary>
    <Dictionary>Oxford</Dictionary>
  </Dictionaries>
</Library>

Um parâmetro de 2 para a categoria resultaria no seguinte:

<Library>
  <Novels>
    <Novel category="2">Novel2</Novel>
    <Novel>Novel3</Novel>
  </Novels>
  <Encyclopedias>
    <Encyclopedia>
      <Volume>A-F</Volume>
      <Volume category="2">G-L</Volume>
    </Encyclopedia>
  </Encyclopedias>
</Library>

Eu sei XSLT é perfeitamente adequado para este trabalho, mas não é uma opção. Nós temos que fazer isso inteiramente em SQL Server 2005. Todas as implementações que não utilizam XQuery são bem também, contanto que isso pode ser feito inteiramente em T-SQL.

Foi útil?

Solução

Não está claro para mim com seu exemplo que você está realmente tentando alcançar. Você quer retornar um novo XML com todos os nós retirados, exceto aqueles que cumprem a condição? Se sim, então isso se parece com o trabalho para uma transformação XSLT que eu não acho que é embutido no MSSQL 2005 (pode ser adicionado como um UDF: http://www.topxml.com/rbnews/SQLXML/ re-23872_Performing-XSLT-transforma-on-XML-Data-armazenados-in-SQL-Server-2005.aspx ).

Se você só precisa voltar a lista de nós, então você pode usar esta expressão:

//Book[not(@ID) or @ID = 5]

mas tenho a impressão de que não é o que você precisa. Seria bom se você pode fornecer um exemplo mais claro.

Editar : Este exemplo é realmente mais clara. O melhor que eu poderia encontrar é esta:

SET @Xml.modify('delete(//*[@category!=1])')
SELECT @Xml

A idéia é excluir do XML todos os nós que você não precisa, para que permaneçam com a estrutura original e os nós necessários. Eu testei com seus dois exemplos e produziu o resultado desejado.

No entanto Modificar tem algumas restrições - parece que você não pode usá-lo em uma instrução SELECT, tem que modificar dados no lugar. Se você precisa de retornar esses dados com uma escolha que você poderia usar uma tabela temporária no qual copiar os dados originais e atualizar essa tabela. Algo parecido com isto:

INSERT INTO #temp VALUES(@Xml)
UPDATE #temp SET data.modify('delete(//*[@category!=2])')

Espero que ajude.

Outras dicas

A questão não é muito claro, mas isso é o que você está procurando?

DECLARE @Xml AS XML
        SET @Xml =
        N'
        <Books>
                <Book ID="1">Book1</Book>
                <Book ID="2">Book2</Book>
                <Book ID="3">Book3</Book>
                <Book>Book4</Book>
                <Book ID="5">Book5</Book>
                <Book ID="6">Book6</Book>
                <Book>Book7</Book>
                <Book ID="8">Book8</Book>
        </Books>
        '
DECLARE @BookID AS INT
SET @BookID = 5
DECLARE @Result AS XML

SET @result = (SELECT @xml.query('//Book[not(@ID) or @ID = sql:variable("@BookID")]'))
SELECT @result
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top