Sql server 迭代Xml列元素并与Xml变量进行比较
我不知道如何正确地使用这个词,但我对Sql Server中的XML非常(非常)陌生 我在表中定义了一个XML列,如果XML列中的数据与预定义列表中的元素匹配,我希望检索记录的id 数据看起来有点像这样: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>
<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')