在SQL Server 2008及更高版本中查询同一查询中的表和XML列的正确方法是什么?

时间:2013-05-24 15:07:05

标签: xml tsql

我正在尝试从同一查询中查询表格及其中一个表格的XML列的内容。

我的表架构基本上如下:

CREATE TABLE AuditLogs
(
    [AuditLogId] INT, 
    [ObjectType] VARCHAR(50), 
    [Action] VARCHAR(50), 
    [ObjectId] INT, 
    [Changes] XML
);

使用Changes列中的XML类似于:

<ArrayOfChange>
    <Change FieldName="ItemStatus">
        <OldValue>Unreconciled</OldValue>
        <NewValue>Reconciled</NewValue>
    </Change>
    <Change FieldName="Amount">
        <OldValue>50.00</OldValue>
        <NewValue>45.00</NewValue>
    </Change>
</ArrayOfChange>

最后,我渴望得到的结果是:

AuditLogId
Action
ObjectType
ObjectId
FieldName
OldValue
NewValue

在真正的StackOverflow传统中,我自己做了一些尝试,取得了一些进展,我认为我差点儿,只是缺少一些东西。我遇到的问题是OldValue和NewValue列始终为null。

我的最新版本是:

SELECT
    [AuditLogId],
    [Action],
    [ObjectType],
    [ObjectId],
    c.n.value('@FieldName', 'varchar(50)') AS FieldName,
    c.n.value('(OldValue)[0]', 'varchar(50)') AS OldValue,
    c.n.value('(NewValue)[0]', 'varchar(50)') AS NewValue
FROM TMP
    CROSS APPLY [Changes].nodes('/ArrayOfChange/Change') c(n)

现在,我创建了一个SQLFiddle,让生活更轻松。

1 个答案:

答案 0 :(得分:2)

你的xpath让你失望。

更改

c.n.value('(OldValue)[0]', 'varchar(50)') AS OldValue,
c.n.value('(NewValue)[0]', 'varchar(50)') AS NewValue

c.n.value('OldValue[1]', 'varchar(50)') AS OldValue,
c.n.value('NewValue[1]', 'varchar(50)') AS NewValue

Xpath是基于1的(关于主题的许多想法in this blogpost);并且你不需要那些带有这种简单路径表达式的括号(它们是允许的,但在这里是不必要的)。