XML 方法节点 () 中的 T-SQL 正则表达式范围



我有一个有两列的表 T。列 A 是 varchar 列,B 列是 XML 列。

在 B 列中的某个地方,始终有以下父标记:<Documents> ... </Documents>。里面有一些<Document>...</Document>的孩子。

我想得到一个包含两列的结果集:

第 1 列应包含与列 A 相同的值; 第 2 列应仅包含一个<Document>...</Document>的内容。 此外,在第 2 列中,应该只有属性等于 1、2 或 3 的<Document>

例如,起始表 T:

Column A | Column B
--------------------------------------------------------------------------
abc      | <Documents><Document ID="1">Doc Foo</Document><Document ID="4">Doc Bar</Document></Documents>
def      | <Documents><Document ID="2">Doc Foo2</Document><Document ID="3">Doc Bar2</Document></Documents>

预期成果:

Column 1 | Column 2
-------------------------------------
abc      |<Document ID="1">Doc Foo</Document>
def      |<Document ID="2">Doc Foo2</Document>
def      |<Document ID="3">Doc Bar2</Document>

我可以得到这样的预期结果:

SELECT
[Column A]     AS [Column 1]
,T2.c.query('.') AS [Column 2]
FROM T AS tbl
CROSS APPLY T.nodes('*/Documents/Document[@ID="1" or @ID="2" or @ID="3"]') AS T2(c)

但是当过滤条件更复杂时,如果没有正则表达式,它可能会失控。 这不起作用:

SELECT
[Column A]      AS [Column 1]
,T2.c.query('.') AS [Column 2]
FROM T AS tbl
CROSS APPLY T.nodes('*/Documents/Document[@ID="[1-3]"]') AS T2(c)

如何让它工作?

扩展@JeroenMostert的建议,如果他是对的,那么也许你所追求的是:

WITH YourTable AS(
SELECT *
FROM (VALUES('abc',CONVERT(xml,'<Documents><Document ID="1">Doc Foo</Document><Document ID="4">Doc Bar</Document></Documents>')),
('def',CONVERT(xml,'<Documents><Document ID="2">Doc Foo2</Document><Document ID="3">Doc Bar2</Document></Documents>')))V(Col1,Col2))
SELECT YT.Col1,
Ds.D.query('.')
FROM YourTable YT
CROSS APPLY YT.Col2.nodes('Documents/Document') Ds(D)
WHERE Ds.D.value('@ID','int') IN (1,2,3);

您可以筛选属性以显示在一系列值中:

Document[@ID = (1,2,3)]

你非常接近。XQuery基于序列的概念。因此,您需要检查@ID属性值是否是序列的成员。

.SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (ID CHAR(3), xmldata XML);;
INSERT INTO @tbl (ID, xmldata)
VALUES
('abc', '<Documents><Document ID="1">Doc Foo</Document><Document ID="4">Doc Bar</Document></Documents>')
, ('def', '<Documents><Document ID="2">Doc Foo2</Document><Document ID="3">Doc Bar2</Document></Documents>');
-- DDL and sample data population, end
SELECT ID
, c.query('.') AS [Column 2]
FROM @tbl AS tbl
CROSS APPLY tbl.xmldata.nodes('/Documents/Document[@ID=("1","2","3")]') AS t(c);

输出

+-----+--------------------------------------+
| ID  |               Column 2               |
+-----+--------------------------------------+
| abc | <Document ID="1">Doc Foo</Document>  |
| def | <Document ID="2">Doc Foo2</Document> |
| def | <Document ID="3">Doc Bar2</Document> |
+-----+--------------------------------------+

相关内容

  • 没有找到相关文章

最新更新