如何使用T-SQL迭代XML文档中的所有节点(SQL2008)。 我需要为文档中的每个不同节点路径(元素)创建表模式。
declare @x xml='
<logins>
<roles>
<role name="Administrator" />
<role name="elUser" />
<role name="ElAdministrator"/>
<role name="regionalManager" />
<role name="Rep"/>
<role name="DiscountAdministrator" />
<role name="LoginAdmin"/>
<groups>
<group name="Administrators">
<role name="Administrator"/>
<role name="elUser" />
<role name="ElAdministrator" />
<role name="Rep" />
<role name="regionalManager" />
<role name="DiscountAdministrator" />
<role name="LoginAdmin" />
</group>
</groups>
</roles>
<members>
<member login="apeiris" ofgroup="Administrator"></member>
</members>
</logins>'
编辑包括上述内容, 我正在考虑创建/维护模式的通用脚本,这意味着我手头上不知道节点。
答案 0 :(得分:1)
以下代码可用于映射存储在文档中的整个xml结构和值,我们只知道其根目录的名称。
当我测试它时,它只运行了几次,之后它吸收了太多的sql资源,并且无关的事务开始受到影响。
我试图找到使用nodes()函数的方法,但只有旧OPENXML
做了我需要做的事情。
然后我将其插入表变量并对其进行操作。
对于这个特定问题,可以生成动态sql以验证是否存在必要的表,并在需要时创建它们后继续进行值插入。
DECLARE @idoc INT
DECLARE @param_XML XML =
'<root>
<element1>hello
<element2>1</element2>
<element3 id="3">goodbye</element3>
</element1>
</root>'
EXEC sys.sp_xml_preparedocument @idoc OUTPUT, @param_XML
--SELECT id, parentid, nodetype,localname, prev, [text]
SELECT *
FROM OPENXML (@idoc, '/root', 2)
-- remeber to close document to avoid memory leak
EXEC sys.sp_xml_removedocument @idoc
答案 1 :(得分:0)
如果结构仍然像您发布的那样,那么您无需担心是否添加了更多角色
试试这个:
declare @x xml='
<logins>
<roles>
<role name="Administrator" />
<role name="elUser" />
<role name="ElAdministrator"/>
<role name="regionalManager" />
<role name="Rep"/>
<role name="DiscountAdministrator" />
<role name="LoginAdmin"/>
<groups>
<group name="Administrators">
<role name="Administrator"/>
<role name="elUser" />
<role name="ElAdministrator" />
<role name="Rep" />
<role name="regionalManager" />
<role name="DiscountAdministrator" />
<role name="LoginAdmin" />
</group>
</groups>
<groups>
<group name="SimpleUser">
<role name="Administrator"/>
<role name="elUser" />
<role name="ElAdministrator" />
<role name="Rep" />
<role name="regionalManager" />
<role name="DiscountAdministrator" />
<role name="LoginAdmin" />
</group>
</groups>
</roles>
<members>
<member login="apeiris" ofgroup="Administrator"></member>
</members>
</logins>'
select
row_number() over (partition by
t.x.value('(group/@name)[1]' , 'varchar(100)')
order by t.x.value('(group/@name)[1]' , 'varchar(100)')) Id,
t.x.value('(group/@name)[1]' , 'varchar(100)') GroupName,
p.y.value('@name' , 'varchar(100)') RoleName
from @x.nodes('//logins/roles/role') p(y)
cross apply @x.nodes('//groups') t(x)
它提供xml中的所有角色和组
答案 2 :(得分:-1)
我很确定如果您知道哪些节点将成为表,您可以使用XPath语句...您是否有该文件的样本?
这为我提供了所有7个角色名称:
SELECT Logins.L.query('data(@name)').value('.', 'varchar(60)') as RoleName
FROM @x.nodes('/logins/roles/role') Logins (L)
从这里开始,您可以使用相同的想法获取所需的数据,并根据您选择的SELECT结果执行任何SQL。