我正在尝试通过将其连接到条件表来找到对XML字符串执行接受/拒绝的方法。我现在有一个“过滤器”工作,但想写它以便它可以过滤2个或更多。
这是与两者中的一个匹配的代码。如果匹配,它将过滤字符串。 我想做的是让它必须与BOTH匹配,同时仍然保留单条件的选项
CREATE TABLE #filter (exclusion_type CHAR(1), excluded_value varchar(10))
INSERT INTO #filter VALUES ('B','boy')
INSERT INTO #filter VALUES ('C','cat')
DECLARE @data XML
SELECT @data = '<A><B>boy</B><C>cat</C></A>'
SELECT * FROM (SELECT CONVERT(VARCHAR(128),node.query('fn:local-name(.)')) AS NodeName, CONVERT(VARCHAR(MAX),node.query('./text()')) AS NodeValue
FROM @data.nodes(N'//*') T(node))xml_shred
IF NOT EXISTS
(SELECT * FROM (SELECT CONVERT(VARCHAR(128),node.query('fn:local-name(.)')) AS NodeName, CONVERT(VARCHAR(MAX),node.query('./text()')) AS NodeValue
FROM @data.nodes(N'//*') T(node)) xml_shred
INNER JOIN #filter
ON (nodename = exclusion_type AND nodevalue LIKE excluded_value)
)
select 'record would be inserted '
ELSE select 'record was filtered'
以下是我目前如何过滤它们的方法。丑陋且不可扩展。
IF NOT EXISTS
(SELECT * FROM (SELECT CONVERT(VARCHAR(128),node.query('fn:local-name(.)')) AS NodeName, CONVERT(VARCHAR(MAX),node.query('./text()')) AS NodeValue
FROM @data.nodes(N'//*') T(node)) xml_shred
INNER JOIN #filter
ON (nodename = exclusion_type AND nodevalue LIKE excluded_value)
)
--combination filters don't easily work within that xml_shred
and not(
@data.value('(/A/B)[1]', 'varchar(128)') = 'boy'
AND
@data.value('(/A/C)[1]', 'varchar(128)')='cat'
)
select 'record would be inserted '
ELSE select 'record was filtered'
我唯一的其他想法:
Mikael建议的代码更改
CREATE TABLE #filter
(
exclusion_set SMALLINT,
exclusion_type CHAR(1) ,
excluded_value VARCHAR(10)
)
INSERT INTO #filter
VALUES (1, 'B', 'boy')
INSERT INTO #filter
VALUES (1, 'C', 'cat')
INSERT INTO #filter
VALUES (2, 'D', 'dog' )
DECLARE @data XML
SELECT @data = '<A><B>boy</B><C>cat</C></A>'
IF NOT EXISTS(
SELECT * FROM
(
select COUNT(*) AS match_count, exclusion_set
from #filter as F
where exists (
select *
from (
select X.N.value('local-name(.)', 'varchar(128)') as NodeName,
X.N.value('./text()[1]', 'varchar(max)') as NodeValue
from @data.nodes('//*') as X(N)
) T
where T.NodeName = F.exclusion_type and
T.NodeValue like F.excluded_value
)
GROUP BY exclusion_set
) matches_per_set
INNER JOIN
(SELECT COUNT(*) AS total_count, exclusion_set FROM #filter GROUP BY exclusion_set) grouped_set
ON match_count = total_count
AND grouped_set.exclusion_set = matches_per_set.exclusion_set
)
答案 0 :(得分:3)
if not exists (
select *
from #filter as F
where exists (
select *
from (
select X.N.value('local-name(.)', 'varchar(128)') as NodeName,
X.N.value('./text()[1]', 'varchar(max)') as NodeValue
from @data.nodes('//*') as X(N)
) T
where T.NodeName = F.exclusion_type and
T.NodeValue like F.excluded_value
)
having count(*) = (select count(*) from #filter)
)
select 'record would be inserted '
else
select 'record was filtered'
答案 1 :(得分:0)
因为如果我没有将某些东西标记为答案,我显然会感到害怕,我会从上面包括我的。非常感谢Mikael Eriksson的帮助。他的XML碎片比我的快,并且通过添加“exclusion_set”字段(char(2)使其明显不是IDENTITY或主键),我可以进行多次检查。如果集合中的所有条件都匹配,则过滤记录。
CREATE TABLE #filter
(
exclusion_set CHAR(2),
exclusion_type CHAR(1) ,
excluded_value VARCHAR(10)
)
INSERT INTO #filter
VALUES ('aa', 'B', 'boy')
INSERT INTO #filter
VALUES ('aa', 'C', 'cat')
INSERT INTO #filter
VALUES ('ab', 'D', 'dog' )
DECLARE @data XML
SELECT @data = '<A><B>boy</B><C>cat</C></A>'
IF NOT EXISTS(
SELECT * FROM
(
select COUNT(*) AS match_count, exclusion_set
from #filter as F
where exists (
select *
from (
select X.N.value('local-name(.)', 'varchar(128)') as NodeName,
X.N.value('./text()[1]', 'varchar(max)') as NodeValue
from @data.nodes('//*') as X(N)
) T
where T.NodeName = F.exclusion_type and
T.NodeValue like F.excluded_value
)
GROUP BY exclusion_set
) matches_per_set
INNER JOIN
(SELECT COUNT(*) AS total_count, exclusion_set FROM #filter GROUP BY exclusion_set) grouped_set
ON match_count = total_count
AND grouped_set.exclusion_set = matches_per_set.exclusion_set
)
select 'record would be inserted '
else
select 'record was filtered'