SQL sql:XML插入中的变量用法

时间:2014-01-01 22:40:11

标签: sql sqlxml

我正在尝试使用sql:variable从XML文件中读取数据。我的问题是,我可以读取XML的第一行或第n行(或节点),但是我不能在行(或节点)中进行迭代。这是我使用sql:variable

的地方
    CAST((SELECT @xmlExpenseItems.value(N'(/ExpenseItem//ExpenseID/node())[sql:variable("@iteratorVarChar")]','int')) AS int),
    CAST((SELECT @xmlExpenseItems.value(N'(/ExpenseItem//ExpenseTypeID/node())[sql:variable("@iteratorVarChar")]','int')) AS int),
    CAST((SELECT @xmlExpenseItems.value(N'(/ExpenseItem//ExpenseAmount/node())[sql:variable("@iteratorVarChar")]','float')) AS float)

其中@iteratorVarChar是从int转换的varchar。

我收到错误“XQuery [value()]:仅”http://www.w3.org/2001/XMLSchema#decimal?“,”http://www.w3.org/2001/XMLSchema#boolean?“或'node()*'表达式作为谓词,在上面的代码的第一行找到'xs:string?'“。

当我用@ @iterator切换@iteratorVarChar时已经是一个int,我得到“XQuery [value()]:'value()'需要一个单例(或空序列),找到类型为'xdt的操作数:untypedAtomic *'“

正如我所说,当我用sql:variable("@iteratorVarChar")之类的int替换1时,代码将与xml的第一个节点一起使用。

我的问题是,我错过了什么,还是我犯了根本错误?如何使这项工作?

我的整个代码如下(我注释了CREATE以避免重新创建错误):

DECLARE @xmlExpenseItems XML

    SET @xmlExpenseItems = ' 
    <ExpenseItem>
            <ExpenseID>5</ExpenseID>
            <ExpenseTypeID>5</ExpenseTypeID>
            <ExpenseAmount>5</ExpenseAmount>
        </ExpenseItem>
        <ExpenseItem>
            <ExpenseID>3</ExpenseID>
            <ExpenseTypeID>5</ExpenseTypeID>
            <ExpenseAmount>7</ExpenseAmount>
        </ExpenseItem>
    '

--CREATE TABLE #ExpenseItems
--(ExpenseItemID int not null identity(1,1), 
--ExpenseID int not null,
--ExpenseTypeID int not null, 
--ExpenseAmount float not null
--)

DECLARE @iterator int = 1
DECLARE @IDCount int
SELECT @IDCount = (SELECT @xmlExpenseItems.value('count(/ExpenseItem)', 'int') )
DECLARE @iteratorVarChar varchar(3)

WHILE @iterator <= @IDCount
    BEGIN
    SET @iteratorVarChar = CAST(@iterator AS varchar(3))
    INSERT INTO #ExpenseItems
    (ExpenseID, ExpenseTypeID, ExpenseAmount)
    VALUES
    (
        CAST((SELECT @xmlExpenseItems.value(N'(/ExpenseItem//ExpenseID/node())[sql:variable("@iteratorVarChar")]','int')) AS int),
        CAST((SELECT @xmlExpenseItems.value(N'(/ExpenseItem//ExpenseTypeID/node())[sql:variable("@iteratorVarChar")]','int')) AS int),
        CAST((SELECT @xmlExpenseItems.value(N'(/ExpenseItem//ExpenseAmount/node())[sql:variable("@iteratorVarChar")]','float')) AS float)
    )
    SET @iterator = @iterator + 1
    END

select * from #ExpenseItems

1 个答案:

答案 0 :(得分:1)

尝试基于集合的方法而不是迭代。 nodes()函数从XML文档返回行集:

insert  #ExpenseItems
        (ExpenseID, ExpenseTypeID, ExpenseAmount)
select  col.value('ExpenseID[1]', 'int')
,       col.value('ExpenseTypeID[1]', 'int')
,       col.value('ExpenseAmount[1]', 'int')
from    @xmlExpenseItems.nodes('/ExpenseItem') doc(col)