ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

ACE.OLEDB.16.0 未注册:SQL Server 读 Excel 排查笔记

ACE.OLEDB.16.0 未注册:SQL Server 读 Excel 排查笔记 今天上午收到同事的告警说生产库上一个定时任务又挂了。我登上服务器一看错误日志里躺着一行熟到不能再熟的报错“未在本地计算机上注册 Microsoft.ACE.OLEDB.16.0 提供程序”。说它熟是因为在 MSSQL2022、MSSQL2019、MSSQL2017 上都经常出现凡是拿 SQL Server 直接读 Excel 的人基本都撞到过这堵墙。这句话平平无奇却很让人恼火它既没说“驱动没装”也没说“位数不对”只是一句“未注册”。可实际上每次报错背后对应的环境可能完全不一样。有人是服务器上压根没装 ACE 驱动有人是装了但装了 32 位有人是注册表有问题还有人是因为服务账户权限没给够。今天我就把这个问题彻底拆开从原理、安装、排查到可复用的脚本一次性讲清楚重点是给经常用 OPENROWSET 读 Excel、靠 SQL Agent 作业自动跑批的 DBA 和数据开发一份可以直接“抄作业”的笔记。1. 报错到底是什么在“抱怨”1.1 “提供程序”和 ACE 驱动的关系先说点基础。Microsoft.ACE.OLEDB.16.0 这个名字里的“ACE”全称是 Access Connectivity Engine是微软提供的、专门用来访问 Excel、Access、文本文件等数据源的 OLE DB 提供程序。注意它和 Access 数据库软件不是一回事它只是一个驱动平时不会显示在任何程序菜单里你把它理解成一个“司机”就好。为什么 SQL Server 需要这个“司机”因为 SQL Server 本身不会直接解析 xlsx 文件。当你执行SELECT * FROM OPENROWSET(...)读 Excel 时SQL Server 是把请求转交给 OLE DB Provider由 Provider 去读取文件并返回一张“表”。这个过程有点像是餐厅里客人点菜厨房不买菜而是通过一个固定的供货渠道进货。如果供货渠道没开通厨房就只能告诉你“找不到这个菜源”。MSSQL2022 的数据库引擎sqlservr.exe是一个 64 位进程所以它必须找到 64 位的 Microsoft.ACE.OLEDB.16.0 提供程序。如果机器上只有 32 位版本的 ACE64 位的 SQL Server 一样会报“未在本地计算机上注册”。这就是这条报错最常见的来源之一。1.2 报错背后最常见的三种情况根据我自己处理过的现场这条报错往下拆基本跑不出这么几类现象可能原因怎么判断裸服务器刚装完 SQL Server 就报错没装 ACE 驱动注册表里没有对应项sys.providers也查不到装了 ACE 驱动SQL Server 还是报错位数不对装成了 32 位检查 ACE 安装文件是 x64 还是 x86驱动位数正确但某些程序能用某些不能用执行进程的位数不一致查 SQL 服务进程位数、SSMS 向导位数驱动也装了位数也对依然报错注册表权限、Ad Hoc Distributed Queries 未开启、Provider 被禁用逐一排查注册表和sp_configure要特别说明一点你用的是不是“最新版 Windows Server”“最新版 SQL Server”与这个报错没有必然关系。MSSQL2022 本身不带 ACE 驱动它也不会在安装时自动帮你装。这个驱动需要单独下载安装而且安装完成后不会新增任何桌面快捷方式导致很多人装了也觉得自己没装过。2. 第一次解决从安装 ACE 到查询可用2.1 下载对应位数的 ACE 驱动首选方案是去微软下载中心搜索“Microsoft Access Database Engine 2016 Redistributable”。注意是 2016 版本因为它的 OLEDB 提供程序版本号是 16.0和报错文本里的 Microsoft.ACE.OLEDB.16.0 正好对应。不要去找 Access 2019 或 Office 365 的安装包那些虽然也有 ACE 组件但版本号和注册方式未必一致容易引出新的幺蛾子。下载的时候一定要分清两个文件AccessDatabaseEngine_x64.exe64 位驱动给 64 位 SQL Server 用。AccessDatabaseEngine.exe32 位驱动给 32 位应用用。如果你是在 Windows Server 2022 上装 MSSQL202299% 的情况应该选x64。判断原则很简单MSSQL2022 的标准版、企业版、开发版都是 64 位数据库引擎所以服务器端必须装 64 位 ACE。安装时用一个管理员 PowerShell 或 CMD直接双击也行。安装完成后在“控制面板 - 程序和功能”里能看到一个名为“Microsoft Access Database Engine 2016”的条目。这里看不到任何新的 Excel 图标很多人就是因为这一步太安静而误以为没装成功。2.2 验证驱动是否注册成功装完之后先做一次“体检”。打开注册表编辑器确认这个位置存在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\16.0\Access Connectivity Engine\Providers在这个键下面你应该能看到Microsoft.ACE.OLEDB.16.0。如果是 32 位 ACE它会被 Windows 重定向到 WOW6432Node 下也就是HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Office\16.0\Access Connectivity Engine\Providers注册表只能证明“驱动装了”但 SQL Server 能不能看到它还得用 SQL 来验证。在 SSMS 中执行SELECT name, friendly_name, description FROM sys.providers WHERE name Microsoft.ACE.OLEDB.16.0;如果能返回一行说明 SQL Server 已经能看到这个提供程序。如果这里查不到基本可以断定 ACE 没装成功或者被装成了 32 位版本需要回到上一步重新检查。2.3 重启服务并开启外部查询开关驱动装好、注册表也正常别急着庆祝。MSSQL 在运行期间可能已经把“有哪些 Provider 可用”的信息缓存下来最好重启一下 SQL Server 服务和 SQL Server Agent确保新装的驱动被重新加载。另外MSSQL 出于安全考虑默认关闭了 OPENROWSET、OPENDATASOURCE 这类临时访问外部数据的开关。如果之前没开过就算 ACE 驱动正常你还会遇到下一句报错SQL Server blocked access to STATEMENT OpenRowset...。在开始测试前先执行下面的脚本EXEC sp_configure show advanced options, 1; RECONFIGURE; EXEC sp_configure Ad Hoc Distributed Queries, 1; RECONFIGURE;执行完后再去跑 OPENROWSET报错应该就消失了。如果你在非常严格的许可环境里用完以后可以考虑把Ad Hoc Distributed Queries重新设回 0保持默认安全状态。3. 版本位数那些坑能坑掉半天时间3.1 为什么本机能跑、服务器就跑不了这个问题我见过太多次开发在自己的笔记本上跑得好好的一部署到生产服务器就报“未在本地计算机上注册”。多数人第一反应是“服务器驱动没装”其实还有一个隐藏得很深的原因——开发笔记本上可能装的是 32 位 ACE而生产服务器是 64 位 SQL Server。为什么本机能跑我仔细排查过几次发现大部分开发笔记本都装着 Office 32 位Office 32 位安装时自带 32 位 ACE。笔记本上的测试如果是从 SSMS 的“导入导出向导”走而向导可能以 32 位进程运行它用的正好是 32 位 ACE但生产服务器上跑的是 SQL Agent 作业作业里的 T-SQL 是发给 64 位 sqlservr.exe 执行的64 位引擎找不到 32 位驱动自然就报“未注册”。还有一个更迷惑的现象SSMS 连的是远程 64 位实例但你在本机用“导入数据”向导导 Excel 成功了换成 Openrowset 写在存储过程里又失败。原因就是向导的执行进程和 SQL 引擎的执行进程根本不是同一个位数环境。总之记住一句话在 MSSQL2022 里T-SQL 查询永远都由 64 位数据库引擎执行和 SSMS 是多少位没有关系和你的开发笔记本是多少位也没有关系。3.2 判断执行环境位数的方法处理这类问题时我习惯按下面几步来定位第一步确认 SQL Server 服务本身是不是 64 位。在 SSMS 里查询SELECT SERVERPROPERTY(MachineName) AS MachineName, SERVERPROPERTY(Edition) AS Edition, SERVERPROPERTY(ProductVersion) AS ProductVersion, SERVERPROPERTY(IsIntegratedSecurityOnly) AS IsIntegratedSecurityOnly;再配合sys.dm_os_loaded_modules看核心模块所在路径通常...\MSSQL16.MSSQLSERVER\MSSQL\Binn\sqlservr.exe只要没有(x86)标记就是 64 位。第二步检查 ACE 安装位数。最简单的方法是看注册表HKLM\SOFTWARE\Microsoft\Office\16.0\Access Connectivity Engine\Providers这个位置存在的是 64 位如果只有下面这个位置存在HKLM\SOFTWARE\WOW6432Node\Microsoft\Office\16.0\Access Connectivity Engine\Providers那就是 32 位SQL Server 用不了。第三步用sys.providers验证 SQL Server 是否认识该提供程序。如果认识但性能出现异常再检查提供程序属性中是否勾选了“允许进程内”选项。3.3 32 位还是 64 位一张决策表环境推荐 ACE 版本备注Windows Server MSSQL202264 位引擎64 位无需装 Office独立安装 RedistributableWindows 10/11 64 位 Office64 位但若 Office 是即点即用版必要时改用 Runtime 方式Windows 10/11 32 位 Office32 位这只能用于 32 位程序测试不能替代服务器 64 位驱动需要同时兼容 32 位工具和 64 位 SQL 引擎不建议共存ACE 32/64 不能同时安装只能二选一“32 位和 64 位不能同时安装”这条要单独画重点。很多人想“干脆两个都装岂不是两头都覆盖”结果安装程序会提示“已有更高版本”然后退出。如果你先装了 32 位想换 64 位基本上需要先卸载 32 位 ACE再装 64 位。如果这台机器上还装着 32 位 Office这个冲突会更麻烦实践中我见过装了 Office 32 位后 ACE 64 位一直装不上的情况。3.4 导入导出向导与 SSIS 的额外注意点如果报错出现在“SQL Server 导入和导出向导”里而不是 T-SQL 查询里你还要多留一个心眼向导进程DTSWizard.exe本身有一个运行时位数的选择默认可能和你 SQL Server 服务位数不一致。SQL Server 2022 自带的安装向导在某些版本里仍然保留“32 位运行时”选项甚至在安装 SQL Server 时还会问你“是否启用 32 位 SQL Server Integration Services”。很多人没注意这个选项默认勾上之后向导里就会默认找 32 位 ACE。如果一定要用向导可以在选择“导入导出向导”之后的配置页面里明确把“32 位运行时”的勾选去掉让它使用 64 位运行时。前提是 64 位 ACE 已正确安装。SSIS 包同理在 Visual Studio 里调试 SSIS 包时项目属性中有“Run64BitRuntime”选项调试版本默认经常是 False也就是以 32 位运行部署到 SQL Agent 后变成 64 位执行于是你在开发环境不报错部署后立刻报“未注册”。这就是“本机能跑、服务器不能跑”的另一种变形。4. 把读 Excel 写成可复用的查询OPENROWSET 与链接服务器4.1 临时查询的标准写法驱动就绪后最直接的用法就是 OPENROWSET。下面这个写法是经过多次验证的标准格式SELECT * FROM OPENROWSET( Microsoft.ACE.OLEDB.16.0, Excel 12.0;DatabaseC:\data\import\20240601.xlsx;HDRYES;IMEX1, SELECT * FROM [Sheet1$] );拆解一下连接字符串参数Excel 12.0表示使用 Excel 2007 及以上的文件格式也就是 .xlsx。即使 Provider 用的是 ACE 16.0这里写的还是Excel 12.0这是一个固定的数据源类型名称不要改成“Excel 16.0”改了反而报错。HDRYES表示第一行是列名第一行不会作为数据记录。IMEX1是很关键的一个参数它告诉驱动把混合类型列都按文本读取避免 Excel 单元格里既有数字又有文字时驱动猜测类型导致部分数据返回 NULL。执行前一定要确认Ad Hoc Distributed Queries已经开启否则会报“SQL Server blocked access”。上面的查询跑通以后你可以用SELECT * INTO temptable FROM OPENROWSET(...)把数据落进临时表或正式表再做后续处理。4.2 配置链接服务器持续复用如果隔三差五就要读同一个 Excel不想每次都写一大串连接字符串可以注册一个链接服务器让查询简洁很多。EXEC master.dbo.sp_addlinkedserver server NExcelSrv, srvproduct NACE, provider NMicrosoft.ACE.OLEDB.16.0, datasrc NC:\data\import\20240601.xlsx, provstr NExcel 12.0;HDRYES;IMEX1; EXEC master.dbo.sp_serveroption server NExcelSrv, optname NRPC OUT, optvalue Ntrue;然后就可以用下面这种方式查询SELECT * FROM OPENQUERY(ExcelSrv, SELECT * FROM [Sheet1$]);有一点务必注意datasrc指向的文件路径是相对于 SQL Server 服务器本机的。如果你的 Excel 在自己电脑上SQL Server 在另一台服务器上要把文件复制到服务器或者放到两台机器都能访问的共享目录中。SQL Server 服务账户必须对该路径有读取权限否则会报“找不到文件”或“访问被拒绝”。还有一个容易被忽略的点Excel 文件如果正被某个用户打开SQL Server 再去读会报“文件正在使用”或者返回奇怪的错误提示。建议专门准备一个导入目录文件放进去后就不要在 Excel 里打开操作。4.3 ACE 驱动不是万能边界条件要先想清楚用 ACE 读 Excel 的成本很低但坑也不少。我遇到的典型情况包括工作表名称带空格比如“Sheet 1”引用时记得写成[Sheet 1$]中括号不能少。Excel 首行有合并单元格、空列名驱动会生成F1、F2这种列名后面查询时要留意。Excel 超过 Excel 2007 的行数限制约一百万行时无法打开真正的大文件不如直接换 CSV。某些加密或包含公式的 Excel驱动可能读不出公式列的内存值返回 NULL。跨服务器查询时性能很一般只适合几万行以内的数据。数据量再往上效率会明显变差。我自己在实际项目中定了一条规矩临时看数据可以用 OPENROWSET 读 Excel但生产环境的定时任务绝不直接读 Excel。更稳妥的做法是让上游把 Excel 另存为 CSV再用BULK INSERT或bcp导入。这不只是为了避开 ACE 驱动也是为了性能和稳定性。5. 现场排查我踩过的问题和速查表5.1 三次真实踩坑的复盘第一次踩坑给一台全新的 Windows Server 2019 装完了 MSSQL2022建了个作业读 Excel第一步 OPENROWSET 就报“未注册”。我以为是驱动没装一看确实没装下载了AccessDatabaseEngine_x64.exe双击安装会弹出一个写着“安装已成功”之类的窗口。我还特意去注册表确认过键存在再执行查询依然报错。后来才发现服务没重启。装了驱动后 SQL Server 引擎还停留在旧缓存里重启后瞬间正常。第二次踩坑在一个老项目里开发机上的 SSMS 一切正常可换到服务器上就跑不了。排查了很久发现开发机装的是 32 位 ACE因为那台机器装了 32 位 Office。开发机上跑的查询所以能成功用的是 32 位 SSMS 的“导入向导”吗其实也不是准确说是它在本地通过 32 位 Office 自带的 ACE 能力时碰巧能通。问题是这个经验完全不能迁移到服务器。从那以后我要求所有涉及外部文件读取的需求直接在服务器环境上验证谁在开发机上验证都不算数。第三次踩坑更隐蔽64 位 ACE 装了SQL Server 服务也重启了sys.providers也能查到但一执行还是提示“未在本地计算机上注册”。后来我把链接服务器上的Microsoft.ACE.OLEDB.16.0打开属性发现“允许进程内”被取消了。查了一下才发现是某人为了“安全加固”把一系列外部 Provider 的进程内选项都关了。Provider 的属性里这一项默认是开启的一旦被关掉报错的就是“未注册”而不是其他说明性更强的错误。把这个选项勾回去问题就解决了。5.2 常见问题与排查速查表症状直接原因解决动作新服务器未装 ACE驱动不存在下载 AccessDatabaseEngine_x64.exe 并安装只装了 32 位 ACEMSSQL2022 仍报错64 位引擎找不到 32 位驱动卸载 32 位安装 64 位装完了仍报错SQL Server 服务持有旧缓存重启 SQL Server 和 SQL Agent 服务OPENROWSET 报“blocked access”Ad Hoc Distributed Queries 未开启sp_configure Ad Hoc Distributed Queries, 1sys.providers有记录但查询失败链接服务器 Provider 属性被改检查“允许进程内”是否开启服务器上文件路径正确但读不了服务账户无权限或文件被占用授权读取目录关闭 Excel 中打开的文件同一套脚本在向导和作业里表现不同运行时位数不同确保 64 位 ACE并检查 SSIS/向导的 32 位运行时选项排查顺序我建议是注册表查驱动是否存在 →sys.providers查 SQL Server 是否可见 →sp_configure查开关 → 服务重启 → 再看链接服务器 Provider 属性。按这个顺序走95% 的“未注册”都能在十分钟内确认到根因。6. 最后分享一个长期更省心的做法关于 ACE 驱动这件事我自己从最初的“三天两头处理报错”到后来干脆换了一条路。如果你只是临时拉一个 xlsx 里的几十行数据用 OPENROWSET 很爽快驱动装好基本一劳永逸。但如果这是一条每天跑批的生产链路我会强烈建议你把它改成上游导出 CSV → 放在固定目录 → 用BULK INSERT或bcp导入表。这样做至少有三个好处一是不再依赖第三方 OLE DB Provider换机器、升版本都不容易踩驱动坑二是导入性能比 OPENROWSET 读 Excel 快得多几万行以上差距非常明显三是可以用FORMATFILE严格控制列映射和类型转换数据质量更可控。我至今还在电脑里存着Microsoft.ACE.OLEDB.16.0的安装包因为它终究是应急处理的第一选择。但每当有人跑来问我“为什么 SQL Server 读不了 Excel”我都会反问一句这个需求是临时的还是长期要跑的如果是后者与其跟驱动斗智斗勇不如把架构改得更简单一点。驱动坑踩一次是教训踩三次就说明方案本身值得换新了。
返回列表