2010-07-14 8 views
0

J'utilise SQL Server 2008 Enterprise + VSTS 2008 + C# + .Net 3.5 + ASP.Net + IIS 7.0 pour développer une application Web simple. Dans ma table de base de données, j'ai une colonne de type XML. Le contenu est comme ci-dessous,Problème de requête SQL SQL Server 2008

Je souhaite obtenir AdditionalInfoList de toutes les lignes de la table si Title contient "Software Engineer" ou Info contient "Software Development". Ma question est comment écrire une telle requête efficacement?

<People> 
    <Item Name="Username" Value="George" /> 
    <Item Name="Info" Value="Software Development Information" /> 
    <Item Name="Title" Value="Software Engineer in Backend" /> 
    <AdditionalInfoList> 
    <AdditionalInfoListItem Guid="xxx" type="type1" /> 
    <AdditionalInfoListItem Guid="yyy" type="type2" /> 
    </AdditionalInfoList> 
</People> 
+0

Ma solution actuelle consiste à lire tout le code XML dans une chaîne XML, puis à analyser la chaîne XML, ce qui, à mon avis, est moins efficace. Je veux trouver une solution plus efficace. – George2

Répondre

2

Vous devez faire quelque chose comme ceci:

SELECT 
    t.ID, -- or whatever you need from the table where the XML is located 
    tbl.People.query('AdditionalInfoList') 
FROM 
    dbo.YourTable t 
CROSS APPLY 
    t.(xmlcolumn).nodes('/People') AS Tbl(People) 
WHERE 
    tbl.People.value('(Item[@Name="Info"]/@Value)[1]', 'varchar(50)') LIKE '%Software Development%' 
    OR 
    tbl.People.value('(Item[@Name="Title"]/@Value)[1]', 'varchar(50)') LIKE '%Software Engineer%' 

Cela devrait vous donner toutes les entrées qui vous intéressent

Explications:.

Le CROSS APPLY crée une table "factices" à laquelle vous devez donner un nom - ici: Tbl(People). Ce nom n'a pas vraiment d'importance, et il n'est pas sensible à la casse, donc Tbl et tbl sont identiques.

Si vous voulez Guid et le type de valeurs distinctes de la <AdditionalInfoList>, vous devez utiliser cette requête ici:

SELECT 
    t.ID, 
    --tbl.People.value('(Item[@Name="Info"]/@Value)[1]', 'varchar(50)') AS 'Info', 
    --tbl.People.value('(Item[@Name="Title"]/@Value)[1]', 'varchar(50)') AS 'Title' 
    Adtl.Info.value('(@Guid)[1]', 'varchar(50)') AS 'GUID', 
    Adtl.Info.value('(@type)[1]', 'varchar(50)') AS 'Type' 
FROM 
    @table t 
CROSS APPLY 
    t.xmlcolumn.nodes('/People') AS Tbl(People) 
CROSS APPLY 
    Tbl.People.nodes('AdditionalInfoList/AdditionalInfoListItem') AS Adtl(Info) 
WHERE 
    Tbl.People.value('(Item[@Name="Info"]/@Value)[1]', 'varchar(50)') LIKE '%Software Development%' 
    OR 
    Tbl.People.value('(Item[@Name="Title"]/@Value)[1]', 'varchar(50)') LIKE '%Software Engineer%' 

Vous avez essentiellement à faire une deuxième CROSS APPLY (qui blessera votre performance !) pour obtenir la liste des "informations supplémentaires" pour chacune des entrées de Tbl.Person et extraire le Guid et la valeur du type à partir de cela.

Découvrez l'introduction SQL Server 2005 XQuery and XML DML - à peu près au milieu de l'article, il y a une section sur la façon d'utiliser la fonction .nodes(). Très utile!

+0

TBL est quoi? Et comment obtenir le GUID et le type à partir des informations récupérées pour chaque ligne correspondante? – George2

+0

Pour TBL, je suis confus parce que vous utilisez à la fois TBL et "tbl". – George2

+0

Merci, pensez-vous que votre méthode est beaucoup plus rapide que ma solution précédente, et pourquoi? – George2