SQL 使用 XML 参数查询

SQL query with XML parameter

编辑:我已经在此处的堆栈溢出中找到了相关答案: XQuery [value()]: 'value()' requires a singleton (or empty sequence), found operand of type 'xdt:untypedAtomic *'

我之前没有在T-SQL中处理过XML,我正在修改一个现有的遗留存储过程,并且通过反复试验来挑选大部分。

但是我遇到了一个问题,反复试验证明是徒劳的,而且速度非常慢。认为是时候向堆栈溢出专家求助了!

这是一些XML


    <?xml version=\"1.0\"?>
    <Notification xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">
    <NotificationId>0</NotificationId>
    <UserNotifications>
    <UserNotification>
    <UserNotificationId>0</UserNotificationId>
    <NotificationId>0</NotificationId>
    <UserId>13514</UserId>
    <MessageTypeId>1</MessageTypeId>
    </UserNotification>
    <UserNotification>
    <UserNotificationId>0</UserNotificationId>
    <NotificationId>0</NotificationId>
    <UserId>13514</UserId>
    <MessageTypeId>2</MessageTypeId>
    </UserNotification>
    </UserNotifications>
    </Notification>

有问题的存储过程接受上述 XML 作为参数:


    CREATE PROCEDURE [dbo].[Notification_Insert] 
        @ParametersXml XML
    AS
    BEGIN

XML 包含子 "UserNotification" 元素。我想 select 每个 UserNotification 的 UserId,MessageTypeId,变成 table 这样的


    UserId | MessageTypeId
    13514 | 1
    13514 | 2

显然集合的大小是不固定的。

我目前的尝试(不起作用 - 是沿着这些方向的:


    DECLARE @UserDetails TABLE ( UserId INT, MessageTypeId INT);
                INSERT INTO @UserDetails (UserId, MessageTypeId)
                SELECT Tab.Col.value('@UserId','INT'),
    Tab.Col.value('@MessageTypeId','INT')
                FROM     @ParametersXml.nodes('/Notification/UserNotifications[not(@xsi:nil = "true")][1]/UserNotification') AS Tab(Col)

但这不会插入任何东西..

我已经玩了一段时间了,但没有任何乐趣:(

我建议您浏览以下链接。我发现它们简短而快速:

http://blog.sqlauthority.com/2009/02/12/sql-server-simple-example-of-creating-xml-file-using-t-sql/ http://blog.sqlauthority.com/2009/02/13/sql-server-simple-example-of-reading-xml-file-using-t-sql/

通过进一步搜索堆栈溢出,我找到了解决这个问题的方法。

我需要的查询(感谢XQuery [value()]: 'value()' requires a singleton (or empty sequence), found operand of type 'xdt:untypedAtomic *'


INSERT INTO @UserDetails (UserId, MessageTypeId)
            SELECT UserNotification.value('UserId[1]','INT'), 
            UserNotification.value('MessageTypeId[1]','INT')
            FROM @ParametersXml.nodes('//Notification/UserNotifications') AS x(Coll)
            cross apply @ParametersXml.nodes('//Notification/UserNotifications/UserNotification') as un(UserNotification)