Sql server 迭代Xml列元素并与Xml变量进行比较

Sql server 迭代Xml列元素并与Xml变量进行比较,sql-server,xml,sql-server-2005,tsql,stored-procedures,Sql Server,Xml,Sql Server 2005,Tsql,Stored Procedures,我不知道如何正确地使用这个词,但我对Sql Server中的XML非常(非常)陌生 我在表中定义了一个XML列,如果XML列中的数据与预定义列表中的元素匹配,我希望检索记录的id 数据看起来有点像这样: <Parameters> <Parameter> <Name>Param1</Name> <Value>Value1</Value> </Parameter>

我不知道如何正确地使用这个词,但我对Sql Server中的XML非常(非常)陌生

我在表中定义了一个XML列,如果XML列中的数据与预定义列表中的元素匹配,我希望检索记录的id

数据看起来有点像这样:

<Parameters>
    <Parameter>
        <Name>Param1</Name>
        <Value>Value1</Value>
    </Parameter>
    <Parameter>
        <Name>Param2</Name>
        <Value>Value2</Value>
    </Parameter>
</Parameter>

但是我想要一些能够处理任意数量参数的东西。

您可以使用操作符将XML投影到列中,然后比较投影的列。这通常是通过交叉应用完成的,如下所示(从内存中键入):

例如,您可以在CTE中使用此选择:

WITH shredded_xml AS (
SELECT Table.ID
   , x.value('(Name)[1]', 'varchar(50)') as Name
   , x.value('(Value)[1]', 'varchar(50)') as Value
   from Table
   CROSS APPLY parameters.nodes('/Parameters/Parameter') AS t(x))
SELECT * 
   FROM shredded_xml 
   WHERE Name = 'Param1'
    AND Value = 'Value1';

我本人对SQL XML相当陌生,因此可能有比这更好的方法,但它似乎足够优雅:

-- Set up some sample data

CREATE TABLE Data (
    Id int
    , Attributes xml
)

-- Number 1 is red and small
INSERT Data
VALUES ( 1, '
<Parameters>
    <Parameter>
        <Name>Color</Name>
        <Value>Red</Value>
    </Parameter>
    <Parameter>
        <Name>Size</Name>
        <Value>Small</Value>
    </Parameter>
</Parameters>' )

-- Number 2 is blue and large
INSERT Data
VALUES ( 2, '
<Parameters>
    <Parameter>
        <Name>Color</Name>
        <Value>Blue</Value>
    </Parameter>
    <Parameter>
        <Name>Size</Name>
        <Value>Large</Value>
    </Parameter>
</Parameters>' )

-- Number 3 is Large
INSERT Data
VALUES ( 3, '
<Parameters>
    <Parameter>
        <Name>Size</Name>
        <Value>Large</Value>
    </Parameter>
</Parameters>' )



-- Search for large ones
DECLARE @searchCriteriaXml xml
SET @searchCriteriaXml = '<Parameters>
    <Parameter>
        <Name>Size</Name>
        <Value>Large</Value>
    </Parameter>
</Parameters>'

/*
-- Or for large blue ones:
SET @searchCriteriaXml = '<Parameters>
    <Parameter>
        <Name>Size</Name>
        <Value>Large</Value>
    </Parameter>
    <Parameter>
        <Name>Color</Name>
        <Value>Blue</Value>
    </Parameter>
</Parameters>'
*/

-- *************************************
-- Here begins the search process

-- Shred the search criteria into a rowset
DECLARE @searchCriteria TABLE (
    Name nvarchar(100)
    , Value nvarchar(100)
)

INSERT INTO
    @searchCriteria
SELECT DISTINCT
    P.value('Name[1]', 'nvarchar(100)')
    , P.value('Value[1]', 'nvarchar(100)')
FROM
    @searchCriteriaXml.nodes('/Parameters/Parameter') SC(P)

-- Debug:
-- SELECT * FROM @searchCriteria

-- To find matching items, we want to shred each
-- item's xml, INNER JOIN against the search criteria,
-- and return those Ids that matched exactly as many rows 
-- as there are in the criteria

SELECT
    Id
FROM
    (
    SELECT
        Data.Id
        , P.value('Name[1]', 'nvarchar(100)') ParameterName
        , P.value('Value[1]', 'nvarchar(100)') ParameterValue
    FROM
        Data
        CROSS APPLY Attributes.nodes('/Parameters/Parameter') D(P)
    ) D -- the shredded data
    INNER JOIN @searchCriteria SC 
        ON D.ParameterName = SC.Name
        AND D.ParameterValue = SC.Value
GROUP BY Id
HAVING COUNT(*) = (SELECT COUNT(*) FROM @searchCriteria)



DROP TABLE Data

虽然我一时兴起,但我想不出一个好方法来计算最后的不同参数。您可以充分信任您的搜索条件,认为这是不必要的。

是否所有参数名称和值都包含在单个参数元素中?那会让事情。。。很抱歉你是对的,我错了,谢谢。现在,您能说出传入的“必须匹配所有这些”数据的格式是什么吗?它是类似的xml格式-或逗号分隔的字符串-还是表格?它是xml格式,样式完全相同,只是值和元素数可能不同。干杯,我来看看。对于具有任意数量参数的通用解决方案,您还应该将@xml变量拆分为一个表格,并连接两个表格,就像Aakash那样干杯我来看看。
WITH shredded_xml AS (
SELECT Table.ID
   , x.value('(Name)[1]', 'varchar(50)') as Name
   , x.value('(Value)[1]', 'varchar(50)') as Value
   from Table
   CROSS APPLY parameters.nodes('/Parameters/Parameter') AS t(x))
SELECT * 
   FROM shredded_xml 
   WHERE Name = 'Param1'
    AND Value = 'Value1';
-- Set up some sample data

CREATE TABLE Data (
    Id int
    , Attributes xml
)

-- Number 1 is red and small
INSERT Data
VALUES ( 1, '
<Parameters>
    <Parameter>
        <Name>Color</Name>
        <Value>Red</Value>
    </Parameter>
    <Parameter>
        <Name>Size</Name>
        <Value>Small</Value>
    </Parameter>
</Parameters>' )

-- Number 2 is blue and large
INSERT Data
VALUES ( 2, '
<Parameters>
    <Parameter>
        <Name>Color</Name>
        <Value>Blue</Value>
    </Parameter>
    <Parameter>
        <Name>Size</Name>
        <Value>Large</Value>
    </Parameter>
</Parameters>' )

-- Number 3 is Large
INSERT Data
VALUES ( 3, '
<Parameters>
    <Parameter>
        <Name>Size</Name>
        <Value>Large</Value>
    </Parameter>
</Parameters>' )



-- Search for large ones
DECLARE @searchCriteriaXml xml
SET @searchCriteriaXml = '<Parameters>
    <Parameter>
        <Name>Size</Name>
        <Value>Large</Value>
    </Parameter>
</Parameters>'

/*
-- Or for large blue ones:
SET @searchCriteriaXml = '<Parameters>
    <Parameter>
        <Name>Size</Name>
        <Value>Large</Value>
    </Parameter>
    <Parameter>
        <Name>Color</Name>
        <Value>Blue</Value>
    </Parameter>
</Parameters>'
*/

-- *************************************
-- Here begins the search process

-- Shred the search criteria into a rowset
DECLARE @searchCriteria TABLE (
    Name nvarchar(100)
    , Value nvarchar(100)
)

INSERT INTO
    @searchCriteria
SELECT DISTINCT
    P.value('Name[1]', 'nvarchar(100)')
    , P.value('Value[1]', 'nvarchar(100)')
FROM
    @searchCriteriaXml.nodes('/Parameters/Parameter') SC(P)

-- Debug:
-- SELECT * FROM @searchCriteria

-- To find matching items, we want to shred each
-- item's xml, INNER JOIN against the search criteria,
-- and return those Ids that matched exactly as many rows 
-- as there are in the criteria

SELECT
    Id
FROM
    (
    SELECT
        Data.Id
        , P.value('Name[1]', 'nvarchar(100)') ParameterName
        , P.value('Value[1]', 'nvarchar(100)') ParameterValue
    FROM
        Data
        CROSS APPLY Attributes.nodes('/Parameters/Parameter') D(P)
    ) D -- the shredded data
    INNER JOIN @searchCriteria SC 
        ON D.ParameterName = SC.Name
        AND D.ParameterValue = SC.Value
GROUP BY Id
HAVING COUNT(*) = (SELECT COUNT(*) FROM @searchCriteria)



DROP TABLE Data
SELECT
    Id
FROM
    (
    SELECT
        Data.Id
        , P.value('Name[1]', 'nvarchar(100)') ParameterName
        , P.value('Value[1]', 'nvarchar(100)') ParameterValue
    FROM
        Data
        CROSS APPLY Attributes.nodes('/Parameters/Parameter') D(P)
    ) D -- the shredded data
    INNER JOIN 
    (
    SELECT DISTINCT
        P.value('Name[1]', 'nvarchar(100)') Name
        , P.value('Value[1]', 'nvarchar(100)') Value
    FROM
        @searchCriteriaXml.nodes('/Parameters/Parameter') SC(P)
    ) SC    -- the shredded search criteria
        ON D.ParameterName = SC.Name
        AND D.ParameterValue = SC.Value
GROUP BY Id
HAVING COUNT(*) = @searchCriteriaXml.value('count(/Parameters/Parameter)', 'int')