- 接口类型
- 语法一览
- 注册表设置
- 单一数据类型列的类型解析
- 混合数据类型列的自然解析
- 混合数据类型列的强制解析——IMEX=1
- 如何解决 NULL 值问题
- SQL Server 2000 中的列顺序问题
- 如何访问隐藏的 Sheet
- 如何访问非常规命名的 Sheet
接口类型
有两种接口可供选择:Microsoft.Jet.OLEDB.4.0(以下简称 Jet 引擎)和Microsoft.ACE.OLEDB.12.0(以下简称 ACE 引擎)。
Jet 引擎大家都很熟悉,可以访问 Office 97-2003,但不能访问 Office 2007。
ACE 引擎是随 Office 2007 一起发布的数据库连接组件,既可以访问 Office 2007,也可以访问 Office 97-2003。
另外:Microsoft.ACE.OLEDB.12.0 可以访问正在打开的 Excel 文件,而 Microsoft.Jet.OLEDB.4.0 是不可以的。
Microsoft.ACE.OLEDB.12.0 安装文件:
语法一览
使用 Jet 引擎或 ACE 引擎访问,在语法上没有什么的区别。
- --> Jet 引擎访问 Excel 97-2003
- select * from OpenRowSet('Microsoft.Jet.OLEDB.4.0', 'Excel 8.0;HDR=Yes;IMEX=1;Database=D:\97-2003.xls', 'select * from [Sheet1$]')
- select * from OpenRowSet('Microsoft.Jet.OLEDB.4.0', 'Excel 8.0;HDR=Yes;IMEX=1;Database=D:\97-2003.xls', [Sheet1$])
- select * from OpenDataSource('Microsoft.Jet.OLEDB.4.0', 'Excel 8.0;HDR=Yes;IMEX=1;Database=D:\97-2003.xls')...[Sheet1$]
- select * from OpenDataSource('Microsoft.Jet.OLEDB.4.0', 'Data Source=D:\97-2003.xls;Extended Properties="Excel 8.0;HDR=Yes;IMEX=1"')...[Sheet1$]
- --> ACE 引擎访问 Excel 97-2003
- select * from OpenRowSet('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=Yes;IMEX=1;Database=D:\97-2003.xls', 'select * from [Sheet1$]')
- select * from OpenRowSet('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=Yes;IMEX=1;Database=D:\97-2003.xls', [Sheet1$])
- select * from OpenDataSource('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=Yes;IMEX=1;Database=D:\97-2003.xls')...[Sheet1$]
- select * from OpenDataSource('Microsoft.ACE.OLEDB.12.0', 'Data Source=D:\97-2003.xls;Extended Properties="Excel 12.0;HDR=Yes;IMEX=1"')...[Sheet1$]
- --> ACE 引擎访问 Excel 2007
- select * from OpenRowSet('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=Yes;IMEX=1;Database=D:\2007.xlsx', 'select * from [Sheet1$]')
- select * from OpenRowSet('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=Yes;IMEX=1;Database=D:\2007.xlsx', [Sheet1$])
- select * from OpenDataSource('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=Yes;IMEX=1;Database=D:\2007.xlsx')...[Sheet1$]
- select * from OpenDataSource('Microsoft.ACE.OLEDB.12.0', 'Data Source=D:\2007.xlsx;Extended Properties="Excel 12.0;HDR=Yes;IMEX=1"')...[Sheet1$]
--> Jet 引擎访问 Excel 97-2003
select * from OpenRowSet('Microsoft.Jet.OLEDB.4.0', 'Excel 8.0;HDR=Yes;IMEX=1;Database=D:\97-2003.xls', 'select * from [Sheet1$]')
select * from OpenRowSet('Microsoft.Jet.OLEDB.4.0', 'Excel 8.0;HDR=Yes;IMEX=1;Database=D:\97-2003.xls', [Sheet1$])
select * from OpenDataSource('Microsoft.Jet.OLEDB.4.0', 'Excel 8.0;HDR=Yes;IMEX=1;Database=D:\97-2003.xls')...[Sheet1$]
select * from OpenDataSource('Microsoft.Jet.OLEDB.4.0', 'Data Source=D:\97-2003.xls;Extended Properties="Excel 8.0;HDR=Yes;IMEX=1"')...[Sheet1$]
--> ACE 引擎访问 Excel 97-2003
select * from OpenRowSet('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=Yes;IMEX=1;Database=D:\97-2003.xls', 'select * from [Sheet1$]')
select * from OpenRowSet('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=Yes;IMEX=1;Database=D:\97-2003.xls', [Sheet1$])
select * from OpenDataSource('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=Yes;IMEX=1;Database=D:\97-2003.xls')...[Sheet1$]
select * from OpenDataSource('Microsoft.ACE.OLEDB.12.0', 'Data Source=D:\97-2003.xls;Extended Properties="Excel 12.0;HDR=Yes;IMEX=1"')...[Sheet1$]
--> ACE 引擎访问 Excel 2007
select * from OpenRowSet('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=Yes;IMEX=1;Database=D:\2007.xlsx', 'select * from [Sheet1$]')
select * from OpenRowSet('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=Yes;IMEX=1;Database=D:\2007.xlsx', [Sheet1$])
select * from OpenDataSource('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=Yes;IMEX=1;Database=D:\2007.xlsx')...[Sheet1$]
select * from OpenDataSource('Microsoft.ACE.OLEDB.12.0', 'Data Source=D:\2007.xlsx;Extended Properties="Excel 12.0;HDR=Yes;IMEX=1"')...[Sheet1$]
Excel 2007 工作簿文件的扩展名是:xlsx
HDR=Yes/No
可选参数,指定 Excel 表的第一行是否列名,缺省为 Yes,可以在注册表中修改缺省的行为。
IMEX=1
可选参数,将 Excel 表中混合 Intermixed 数据类型的列强制解析为文本。
注册表设置
Microsoft.Jet.OLEDB.4.0
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Excel
Microsoft.ACE.OLEDB.12.0
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\12.0\Access Connectivity Engine\Engines\Excel
FirstRowHasNames
设置 HDR 参数的缺省行为,默认为 Yes。
ImportMixedTypes
设置混合列的强制解析类型,默认为文本 Text。
TypeGuessRows
设置用于解析数据类型的取样行数,默认取样前 8 行。如果设置为 0,将分析所有数据行,但不建议这样做,会影响引擎的性能。
注意:Excel 表数据列是单一列数据类型还是混合列数据类型列,是由取样行决定,而不是整列数据决定。
单一数据类型列的类型解析
Sheet1 的内容如下图所示,涵盖了大部分 Excel 的数据类型,其中 longtext 分别有 256 个 A 和 B。
对于单一数据类型列的类型解析,ACE 引擎和 Jet 引擎是一样的,下面测试 Jet 引擎的数据解析:
- use tempdb
- go
- select * into #type from OpenRowSet('Microsoft.Jet.OLEDB.4.0', 'Excel 8.0;Database=D:\97-2003.xls', 'select * from [Sheet1$]')
- select
- a.name,
- date_type = b.name + case a.xusertype when 231 then '('+ltrim(a.length/2)+')' else '' end
- from
- syscolumns a inner join systypes b on a.xusertype = b.xusertype
- where
- a.id = object_id('#type')
- /*
- name date_type
- -------- -------------
- longtext ntext
- text nvarchar(255)
- datetime datetime
- date datetime
- time datetime
- money money
- float float
- numeric float
- integer float
- */
- drop table #type
use tempdb
go
select * into #type from OpenRowSet('Microsoft.Jet.OLEDB.4.0', 'Excel 8.0;Database=D:\97-2003.xls', 'select * from [Sheet1$]')
select
a.name,
date_type = b.name + case a.xusertype when 231 then '('+ltrim(a.length/2)+')' else '' end
from
syscolumns a inner join systypes b on a.xusertype = b.xusertype
where
a.id = object_id('#type')
/*
name date_type
-------- -------------
longtext ntext
text nvarchar(255)
datetime datetime
date datetime
time datetime
money money
float float
numeric float
integer float
*/
drop table #type
数据类型解析总结
-
文本:长度 <= 255,解析为 nvarchar(255),长度 > 255,解析为 ntext。
-
数值:货币解析为 money,其它均解析为 float。
-
时间:datetime。
混合数据类型列的强制解析——IMEX=1
使用 IMEX=1 选参之后,只要取样数据里是混合数据类型的列,一律强制解析为 nvarchar/ntext 文本。当然,IMEX=1 对单一数据类型列的解析是不影响的。
- select * from OpenRowSet('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;IMEX=1;Database=D:\97-2003.xls', 'select * from [Sheet2$]')
- select * from OpenRowSet('Microsoft.Jet.OLEDB.4.0', 'Excel 8.0;IMEX=1;Database=D:\97-2003.xls', 'select * from [Sheet2$]')
- select * from OpenRowSet('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;IMEX=1;Database=D:\2007.xlsx', 'select * from [Sheet2$]')
- /*
- id describe num>str num=str num
- ----- -------- -------- -------- --------
- 1 sampling 1 1 1
- 2 sampling 2 2 2
- 3 sampling 3 3 3
- 4 sampling 4 4 A
- 5 sampling 5 A B
- 6 sampling A B C
- 7 sampling B C D
- 8 sampling C D E
- 9 others 1 2 3
- 10 others > = <
- ----- -------- -------- -------- --------
- float nvarchar nvarchar nvarchar nvarchar <-- 解析的数据类型
- */
select * from OpenRowSet('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;IMEX=1;Database=D:\97-2003.xls', 'select * from [Sheet2$]')
select * from OpenRowSet('Microsoft.Jet.OLEDB.4.0', 'Excel 8.0;IMEX=1;Database=D:\97-2003.xls', 'select * from [Sheet2$]')
select * from OpenRowSet('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;IMEX=1;Database=D:\2007.xlsx', 'select * from [Sheet2$]')
/*
id describe num>str num=str num = <
----- -------- -------- -------- --------
float nvarchar nvarchar nvarchar nvarchar
最后一列(num
在数据解析的细节方面,ACE 引擎的表现优于 Jet 引擎。在前面提到的文本优先问题、非文本数据的 NULL 值问题,ACE 引擎的解析更合理。
如何解决 NULL 值问题
前 8 行(取样行)是混合数据类型的列,使用 IMEX=1 选参解决。
前 8 行是文本,8 行之外有非文本的数据,使用 ACE 引擎解决。
前 8 行是数值,8 行之外又非数值的数据:
-
将前 8 行其中一行的单元格式数字设置为文本(如果还不行,可能要手工重写该单元格,以应用文本格式,不记得是 Office 97 还是 2000 存在这个问题了);
-
修改注册表中的 TypeGuessRows(注册表设置),增加取样行数,或设置为 0 全部解析。
目的只有一个,让取样行变成混合数据类型的列,然后使用 IMEX=1 选参解决。
SQL Server 2000 中的列顺序问题
这是 SQL Server 2000 行集函数 OpenRowSet 和 OpenDataSource 本身的问题,与访问接口引擎无关,也与 Excel 版本无关。SQL Server 2005 的 OpenRowSet 和 OpenDataSource 不存在这个问题。
上图是 Sheet3 的内容,连接到 SQL Server 2000 测试看看是什么问题:
- --> HDR=Yes
- select * from OpenRowSet('Microsoft.Jet.OLEDB.4.0', 'Excel 8.0;HDR=Yes;Database=D:\97-2003.xls', [Sheet3$])
- select * from OpenDataSource('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=Yes;Database=D:\97-2003.xls')...[Sheet3$]
- select * from OpenDataSource('Microsoft.ACE.OLEDB.12.0', 'Data Source=D:\2007.xlsx;Extended Properties="Excel 12.0;HDR=Yes"')...[Sheet3$]
- /*
- A B C D E F G H I J
- --- --- --- --- --- --- --- --- --- ---
- C10 C9 C8 C7 C6 C5 C4 C3 C2 C1
- */
- --> HDR=No
- select * from OpenRowSet('Microsoft.Jet.OLEDB.4.0', 'Excel 8.0;HDR=No;Database=D:\97-2003.xls', [Sheet3$])
- select * from OpenDataSource('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=No;Database=D:\97-2003.xls')...[Sheet3$]
- select * from OpenDataSource('Microsoft.ACE.OLEDB.12.0', 'Data Source=D:\2007.xlsx;Extended Properties="Excel 12.0;HDR=No"')...[Sheet3$]
- /*
- F1 F10 F2 F3 F4 F5 F6 F7 F8 F9
- --- --- --- --- --- --- --- --- --- ---
- J A I H G F E D C B
- C1 C10 C2 C3 C4 C5 C6 C7 C8 C9
- */
--> HDR=Yes
select * from OpenRowSet('Microsoft.Jet.OLEDB.4.0', 'Excel 8.0;HDR=Yes;Database=D:\97-2003.xls', [Sheet3$])
select * from OpenDataSource('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=Yes;Database=D:\97-2003.xls')...[Sheet3$]
select * from OpenDataSource('Microsoft.ACE.OLEDB.12.0', 'Data Source=D:\2007.xlsx;Extended Properties="Excel 12.0;HDR=Yes"')...[Sheet3$]
/*
A B C D E F G H I J
--- --- --- --- --- --- --- --- --- ---
C10 C9 C8 C7 C6 C5 C4 C3 C2 C1
*/
--> HDR=No
select * from OpenRowSet('Microsoft.Jet.OLEDB.4.0', 'Excel 8.0;HDR=No;Database=D:\97-2003.xls', [Sheet3$])
select * from OpenDataSource('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=No;Database=D:\97-2003.xls')...[Sheet3$]
select * from OpenDataSource('Microsoft.ACE.OLEDB.12.0', 'Data Source=D:\2007.xlsx;Extended Properties="Excel 12.0;HDR=No"')...[Sheet3$]
/*
F1 F10 F2 F3 F4 F5 F6 F7 F8 F9
--- --- --- --- --- --- --- --- --- ---
J A I H G F E D C B
C1 C10 C2 C3 C4 C5 C6 C7 C8 C9
*/
返回结果集的列顺序,是按照列名排序,并不是 Excel 表的列顺序。HDR=No 貌似正确,但仔细一看,仍然是按列名排序的。
OpenRowSet(query)
OpenRowSet(query) 可以解决这个列顺序的问题,包括后面的访问隐藏的 Sheet 或非常规命名的 Sheet,都可以用 OpenRowSet(query) 解决。
- --> HDR=Yes
- select * from OpenRowSet('Microsoft.Jet.OLEDB.4.0', 'Excel 8.0;HDR=Yes;Database=D:\97-2003.xls', 'select * from [Sheet3$]')
- select * from OpenRowSet('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=Yes;Database=D:\97-2003.xls', 'select * from [Sheet3$]')
- select * from OpenRowSet('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=Yes;Database=D:\2007.xlsx', 'select * from [Sheet3$]')
- /*
- J I H G F E D C B A
- --- --- --- --- --- --- --- --- --- ---
- C1 C2 C3 C4 C5 C6 C7 C8 C9 C10
- */
- --> HDR=No
- select * from OpenRowSet('Microsoft.Jet.OLEDB.4.0', 'Excel 8.0;HDR=No;Database=D:\97-2003.xls', 'select * from [Sheet3$]')
- select * from OpenRowSet('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=No;Database=D:\97-2003.xls', 'select * from [Sheet3$]')
- select * from OpenRowSet('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=No;Database=D:\2007.xlsx', 'select * from [Sheet3$]')
- /*
- F1 F2 F3 F4 F5 F6 F7 F8 F9 F10
- --- --- --- --- --- --- --- --- --- ---
- J I H G F E D C B A
- C1 C2 C3 C4 C5 C6 C7 C8 C9 C10
- */
--> HDR=Yes
select * from OpenRowSet('Microsoft.Jet.OLEDB.4.0', 'Excel 8.0;HDR=Yes;Database=D:\97-2003.xls', 'select * from [Sheet3$]')
select * from OpenRowSet('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=Yes;Database=D:\97-2003.xls', 'select * from [Sheet3$]')
select * from OpenRowSet('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=Yes;Database=D:\2007.xlsx', 'select * from [Sheet3$]')
/*
J I H G F E D C B A
--- --- --- --- --- --- --- --- --- ---
C1 C2 C3 C4 C5 C6 C7 C8 C9 C10
*/
--> HDR=No
select * from OpenRowSet('Microsoft.Jet.OLEDB.4.0', 'Excel 8.0;HDR=No;Database=D:\97-2003.xls', 'select * from [Sheet3$]')
select * from OpenRowSet('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=No;Database=D:\97-2003.xls', 'select * from [Sheet3$]')
select * from OpenRowSet('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;HDR=No;Database=D:\2007.xlsx', 'select * from [Sheet3$]')
/*
F1 F2 F3 F4 F5 F6 F7 F8 F9 F10
--- --- --- --- --- --- --- --- --- ---
J I H G F E D C B A
C1 C2 C3 C4 C5 C6 C7 C8 C9 C10
*/
如何访问隐藏的 Sheet
隐藏 Sheet 的访问情况比较复杂,就不写测试过程了,归纳一下:
-
使用 OpenRowSet(query) 肯定可以访问。
-
Excel 2007 任何写法都可以访问(Jet 引擎不能访问 Excel 2007)。
-
打开的 Excel 文件任何写法都可以访问(Jet 引擎不能访问打开的 Excel 文件)。
如何访问非常规命名的 Sheet
新建一个空白的 Sheet,重命名为 4 保存关闭:
-
使用 OpenRowSet(query) 可以正常访问。
-
其它写法,用单引号限定名称 ['4$'] 可以访问。
- OpenRowSet(query) 也可以使用单引号限定访问:'select * from [''4$'']'
引出最后一个问题,访问 Excel 97-2003 空白的 Sheet,会返回一行 NULL 值,访问 Excel 2007 空白的 Sheet,返回空结果集,数据类型均解析为 nvarchar(255)。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/518723/viewspace-561399/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/518723/viewspace-561399/