1

我有一个 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
4

1 回答 1

2

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

另外:您的 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类似" 将其替换为我选择的内容 - 将其替换为您的实际 XML 命名空间作为前缀:data....ss:ss:

;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
于 2012-05-17T15:40:51.777 回答