【问题标题】:SQL Server 2008 OPENXML InsertSQL Server 2008 OPENXML 插入
【发布时间】:2012-05-17 23:50:08
【问题描述】:

我有一个 XML 文档,其结构非常类似于基于架构的 Excel 电子表格。此文件中有两个工作表。如何将第二张工作表中的所有数据插入到我的 SQL 表中?我基本上想要直接导入,但 OPENXML 一直告诉我 0 行受影响。这是 XML 文档的示例:

<Worksheet ss:Name="Product Level Data">
<x:WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<Print>
<ValidPrinterInfo/>
<PaperSizeIndex>1</PaperSizeIndex>
<Scale>100</Scale>
<FitWidth>1</FitWidth>
<FitHeight>1</FitHeight>
<HorizontalResolution>300</HorizontalResolution>
<VerticalResolution>300</VerticalResolution>
</Print>
<Zoom>100</Zoom>
<x:PageSetup>
<x:Header  ss:StyleID="systemtitle" Data="The SAS System"
/>
</x:PageSetup>
<Selected/>
<FreezePanes/>
<FrozenNoSplit/>
<SplitHorizontal>1</SplitHorizontal>
<TopRowBottomPane>1</TopRowBottomPane>
<ActivePane>2</ActivePane>
<Panes>
<Pane>
<Number>3</Number>
</Pane>
<Pane>
<Number>2</Number>
</Pane>
</Panes>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
</x:WorksheetOptions>
<AutoFilter x:Range="R1C1:R545C10" xmlns="urn:schemas-microsoft-com:office:excel"></AutoFilter><Table ss:StyleID="_body">
<ss:Column ss:AutoFitWidth="1" ss:Width="90"/>
<ss:Column ss:AutoFitWidth="1" ss:Width="270"/>
<ss:Column ss:AutoFitWidth="1" ss:Width="90"/>
<ss:Column ss:AutoFitWidth="1" ss:Width="90"/>
<ss:Column ss:AutoFitWidth="1" ss:Width="90"/>
<ss:Column ss:AutoFitWidth="1" ss:Width="90"/>
<ss:Column ss:AutoFitWidth="1" ss:Width="90"/>
<ss:Column ss:AutoFitWidth="1" ss:Width="90"/>
<ss:Column ss:AutoFitWidth="1" ss:Width="108"/>
<ss:Column ss:AutoFitWidth="1" ss:Width="108"/>
<Row ss:AutoFitHeight="1">
<Cell ss:StyleID="header__c" ss:Index="1"><Data ss:Type="String">ID</Data></Cell>
<Cell ss:StyleID="header__c" ss:Index="2"><Data ss:Type="String">Company Name</Data></Cell>
<Cell ss:StyleID="header__l" ss:Index="3"><Data ss:Type="String">Item</Data></Cell>
<Cell ss:StyleID="header__c" ss:Index="4"><Data ss:Type="String">Type</Data></Cell>
<Cell ss:StyleID="header__r1" ss:Index="5"><Data ss:Type="String">Total Time</Data></Cell>
<Cell ss:StyleID="header__r1" ss:Index="6"><Data ss:Type="String">Total Amount</Data></Cell>
<Cell ss:StyleID="header__r1" ss:Index="7"><Data ss:Type="String">Count Product</Data></Cell>
<Cell ss:StyleID="header__r" ss:Index="8"><Data ss:Type="String">Percentage Time</Data></Cell>
<Cell ss:StyleID="header__r" ss:Index="9"><Data ss:Type="String">Product Time</Data></Cell>
<Cell ss:StyleID="header__r" ss:Index="10"><Data ss:Type="String">Invalid Product Time</Data></Cell>
</Row>
<Row ss:AutoFitHeight="1">
<Cell ss:StyleID="data__l" ss:Index="1"><Data ss:Type="String">DF</Data></Cell>
<Cell ss:StyleID="data__l" ss:Index="2"><Data ss:Type="String">Dan's Fruit Company</Data></Cell>
<Cell ss:StyleID="data__l" ss:Index="3"><Data ss:Type="String">Apple</Data></Cell>
<Cell ss:StyleID="data__r" ss:Index="4"><Data ss:Type="String">Fruit</Data></Cell>
<Cell ss:StyleID="data__r1" ss:Index="5"><Data ss:Type="Number">2034004</Data></Cell>
<Cell ss:StyleID="data__r1" ss:Index="6"><Data ss:Type="Number">23423</Data></Cell>
<Cell ss:StyleID="data__r1" ss:Index="7"><Data ss:Type="Number">15789</Data></Cell>
<Cell ss:StyleID="data__r" ss:Index="8"><Data ss:Type="Number">100.0</Data></Cell>
<Cell ss:StyleID="data__r" ss:Index="9"><Data ss:Type="Number">0.000</Data></Cell>
<Cell ss:StyleID="data__r" ss:Index="10"><Data ss:Type="Number">0.000</Data></Cell>
</Row>

这是我正在尝试的代码。这是我第一次尝试使用 OPENXML:

DECLARE @XMLDocPointer INT
, @strXML VARCHAR(10000)

SET @strXML = <large code block up there>

EXEC sp_xml_preparedocument @XMLDocPointer OUTPUT, @strXML

BEGIN TRANSACTION
INSERT INTO xml_staging_table
(
id
, company_name
, item
, type
, total_time
, total_amount
, count_product
, percent_time
, product_time
, invalid_product_time
)
SELECT id
, company_name
, item
, type
, total_time
, total_amount
, count_product
, percentage_time
, product_time
, invalid_product_time
FROM OPENXML(@XMLDocPointer,'/WORKSHEET/TABLE/ROW/CELL', 4) --What is the correct syntax here?
WITH 
(
id VARCHAR(10) 'id/.'
, company_name VARCHAR(500) 'company_name/.'
, item VARCHAR(10) 'item/.'
, type VARCHAR(50) 'type/.'
, total_time BIGINT 'total_time/.'
, total_amount BIGINT 'total_amount/.'
, count_product BIGINT 'count_product/.'
, percentage_time DECIMAL(5,2) 'percentage_time/.'
, product_time BIGINT 'product_time/.'
, invalid_product_time BIGINT 'invalid_product_time/.'
)
COMMIT

EXEC sp_xml_removedocument @XMLDocPointer

【问题讨论】:

    标签: sql-server-2008 openxml


    【解决方案1】:

    不知道如何使用OPENQUERY - 这已被弃用,您应该直接使用XQuery support in SQL Server 2005 和更新版本。

    另外:您的 XML 不完整,因为它没有在任何地方显示 ss: xml 命名空间的定义 - 但忽略这一点 - 您应该能够使用类似这样的 SQL 语句获取数据:

    -- reduced huge XML to the actual relevant parts...
    -- defined "dummy" XML namespace for ss: prefix
    DECLARE @input XML = '<Worksheet ss:Name="Product Level Data" xmlns:ss="urn:test">
    <Table ss:StyleID="_body">
      <Row ss:AutoFitHeight="1">
        <Cell ss:StyleID="data__l" ss:Index="1"><Data ss:Type="String">DF</Data></Cell>
        <Cell ss:StyleID="data__l" ss:Index="2"><Data ss:Type="String">Dan''s Fruit Company</Data></Cell>
        <Cell ss:StyleID="data__l" ss:Index="3"><Data ss:Type="String">Apple</Data></Cell>
        <Cell ss:StyleID="data__r" ss:Index="4"><Data ss:Type="String">Fruit</Data></Cell>
        <Cell ss:StyleID="data__r1" ss:Index="5"><Data ss:Type="Number">2034004</Data></Cell>
        <Cell ss:StyleID="data__r1" ss:Index="6"><Data ss:Type="Number">23423</Data></Cell>
        <Cell ss:StyleID="data__r1" ss:Index="7"><Data ss:Type="Number">15789</Data></Cell>
        <Cell ss:StyleID="data__r" ss:Index="8"><Data ss:Type="Number">100.0</Data></Cell>
        <Cell ss:StyleID="data__r" ss:Index="9"><Data ss:Type="Number">0.000</Data></Cell>
        <Cell ss:StyleID="data__r" ss:Index="10"><Data ss:Type="Number">0.000</Data></Cell>
      </Row>
     </Table>
    </Worksheet>'
    
    SELECT
        XmlCell.value('(.)[1]', 'varchar(50)')
    FROM
        @Input.nodes('/Worksheet/Table/Row/Cell/Data') AS Nodes(XmlCell)
    

    这给了我一个输出:

    DF
    Dan's Fruit Company
    Apple
    Fruit
    2034004
    23423
    15789
    100.0
    0.000
    0.000
    

    更新:要处理“完整”输入 XML,并仅提取具有 StyleID 类似于 data.... 的单元格,您可以再次使用此 T-SQL 语句,它必须知道 ss: XML 命名空间的定义 - 我只是在这里“调整”它为我选择的东西 - 将其替换为 ss: 前缀的实际 XML 命名空间:

    ;WITH XMLNAMESPACES('urn:test' AS ss), 
    XmlParsedData AS
    (
    SELECT
        CellStyle = XmlCell.value('@ss:StyleID', 'varchar(50)'),
        CellIndex = XmlCell.value('@ss:Index', 'int'),
        CellValue = XmlCell.value('(Data)[1]', 'varchar(50)')
    FROM
        @Input.nodes('/Worksheet/Table/Row/Cell') AS Nodes(XmlCell)
    )
    SELECT *
    FROM XmlParsedData
    WHERE
        CelLStyle LIKE 'data%'
    

    这将为您提供如下输出:

    CellStyle  CellIndex  CellValue
    data__l        1      DF
    data__l        2      Dan's Fruit Company
    data__l        3      Apple
    data__r        4      Fruit
    data__r1       5      2034004
    data__r1       6      23423
    data__r1       7      15789
    data__r        8      100.0
    data__r        9      0.000
    data__r       10      0.000
    

    【讨论】:

    • 将那些不相关的部分添加回去仍然可以使这项工作吗?我问的原因是因为我想直接引用文件。
    • @eek142:是的,它也适用于您的完整 XML - 只要您为 ss: XML 命名空间前缀提供正确的定义
    • 此行中的 XML 命名空间不是:
    • @eek142: 那是 default XML 命名空间(没有任何前缀)——但这仅在&lt;WorksheetOptions&gt; 节点及其子节点的范围内使用
    • @eek142: 不管你的文件里有什么,是的——你展示的部分从&lt;Worksheet&gt;开始——但如果真正的文件在那之前有更多的节点,当然也必须包含这些节点在 XPath 表达式中,是的。
    猜你喜欢
    • 1970-01-01
    • 2011-05-06
    • 1970-01-01
    • 2011-05-22
    • 1970-01-01
    • 1970-01-01
    • 2013-02-17
    • 2010-11-25
    • 2013-10-17
    相关资源
    最近更新 更多