自动将数据从 Access 插入 Sql server
Posted
技术标签:
【中文标题】自动将数据从 Access 插入 Sql server【英文标题】:Automatically insert data from Access into Sql server 【发布时间】:2014-08-11 14:21:19 【问题描述】:情况: 我们每月收到统计源数据。它以带有 Access 数据库的 CD 形式提供,其中包含两个表。所以我们有 1 个 *.mdb 文件,里面有 2 个表。分析师应该能够导入数据、计算和标准化数据并检查结果。如果结果很好,则填充数据。分析师不是程序员,他们没有 SQLServerManagementStudio。
我的任务: 使用按钮为分析师创建一个访问表单作为前端:导入、计算、检查、填充。每个按钮都会触发路径槽查询,它不会在 sql server 端运行存储过程。
我的问题: 我项目的瓶颈是数据导入。它应该自动完成(而不是手动完成,因为分析师没有安装管理工作室)。
我尝试了什么:
1) 我将 SQL Server 的表链接到访问中,并尝试使用常规查询来复制(INSERT INTO ** FROM *),但它需要的时间太长。 (我在两个表中有大约 400 万行)
2) 因为我喜欢 BULK INSERT 无法从访问文件导入。
3) OPENROWSET 方法:
SELECT *
FROM OPENROWSET( 'Microsoft.Jet.OLEDB.4.0','\\euro-dc\DOTS\2014\dots.mdb';'admin';'',TimeSeries)
返回错误:
消息 7308,级别 16,状态 1,行 1 OLE DB 提供程序 'Microsoft.Jet.OLEDB.4.0' 不能用于分布式查询 因为提供程序配置为在单线程单元中运行 模式。
Openrowset 解决方案不可取。我想避免它。因为它可以在某些计算机上运行,但由于 OLDB 驱动程序,它不能在其他计算机上运行。 windows 重新安装后需要检查 OLEDB 驱动程序...不是很舒服,因为有 15 位分析师。只有在没有其他方法可以导入数据的情况下。
\euro-dc\dots 文件夹可用于 sql server - 它已在我的其他项目中进行了测试。
将欣赏任何新的想法。 谢谢
【问题讨论】:
[***.com/questions/22032222/… @mohan111 也许还有另一种方法可以分开 openrowset。因为解决方案可以在某些计算机上运行,而不能在其他计算机上运行。重装windows后需要检查OLEDB驱动……不是很舒服,分析员有15人。 在读入记录之前,您是否尝试将访问文件复制到本地工作站以查看是否加快了复制过程?有时,在尝试处理 CD 或 USB 驱动器上的记录时,性能会大幅下降。 @RemedialBear 是的,我的前端解决方案在我的本地机器上。我尝试将 2 个表从源数据库导入其中,速度非常快。但是当我尝试将数据放入 sql srv 时需要很长时间 我可能会使用@Barry 在他的回答(和相关的 cmets)中建议的方法之一。 【参考方案1】:使用导入向导并保存您要导入的每组数据的导入规范。然后在执行导入规范的按钮下编写一些代码/宏。 您导入的表可以在 Access 中构建,然后升级为 SQL Svr。
400 万条记录会很慢,因此您可能希望将其放在单独的 MDB 中,以免占用分析师的工作 MDB。
【讨论】:
你的意思是我应该保存 SSIS 包吗?当我尝试它返回我“此数据库版本不支持尝试的操作”(我有 sql server 2012) 没有。我不熟悉SSIS。如果我错过了你的观点,请原谅我。我说您应该尝试的是:启动导入向导并创建您的导入(Access 2003 中的“文件”、“获取外部数据”、“导入”)。第一次运行时在 Access 中创建表。将此保存为导入规范。现在,再次执行导入,只是这次指定您第一次创建的表。保存此更改。 (花了我超过 5 分钟的时间来编辑)您可以通过多种方式将目标表升迁到 SQL Server 中,包括使用升迁向导(工具、数据库实用程序、升迁向导)或手动键入结构进入 SQL Server。在 SQL Server 中拥有它后,将其附加到您的 MDB,并为其指定导入规范中使用的名称。 @Almazini - 您运行的是 SQL Server 2012 Express Edition 吗?如果是这样,那么您可能无法使用该版本保存 SSIS 包。 (如果我没记错的话,这是免费 Express Edition 中禁用的功能之一。) @GordThompson 我不认为 Almazini 建议使用 SSIS,而是建议使用 Access 中内置的导入向导【参考方案2】:由于您要处理大量记录,因此您应该考虑索引可能对数据导出/导入过程的性能产生的影响。在您的情况下,有些人用来加快速度的技术是首先将源数据导出为方便的中间文件格式(CSV 或其他格式),删除目标表上的索引,执行 BULK INSERT 以提取中间文件数据到您的目标表中,然后在 BULK INSERT 完成后最终在目标表上重新创建索引。
这可以显着提高性能,因为在最后(一次)重新创建索引通常比每次插入一行时发生的所有索引更新的总和快得多。
我相信您应该能够通过 Access 使用 VBA 和 T-SQL 传递查询以编程方式实现上述每个步骤。
希望对您有所帮助。祝你的项目好运。
【讨论】:
这正是我昨天想要做的。想法是将表格转换为 csv 或 txt,而不是批量插入。问题是访问无法以 csv 格式导出表格,对于 txt 格式,有 65k 行的限制。 一个小的 VBA 函数可以遍历表的行和列,将单个数据项写入 CSV 文件就可以了。编写自己的导出例程时,对 65K 行没有限制。【参考方案3】:如果您在下面的查询行中使用某些内容,它将从 MS Access 运行。您还可以选择传递查询,或者更好的是,提供一些代码来提供参数。
INSERT INTO
[ODBC;DRIVER=SQL Server;Server=servername;Database=dbname;Integrated Security=SSPI].Table1
SELECT * FROM Table1
获取正确连接字符串的最简单方法是链接表,然后检查连接属性。
您还可以在 http://connectionstrings.com 找到连接字符串
一些示例,请注意,虽然名称用作参考,但实际上参数的顺序很重要。大多数情况下,我会检查我是否有连接,以节省时间。
MS Access 中的查询
Set db = CurrentDb
sSQL = "INSERT INTO dbo_LocationLocationType (LocationID,LocationTypeID) VALUES (@LocationId,@LocationName)"
Set qdf = db.CreateQueryDef("", sSQL)
qdf.Parameters![@LocationId] = LocationID
qdf.Parameters![@LocationName] = LocationName
qdf.ReturnsRecords = False
qdf.Execute dbFailOnError
存储过程
Dim cmd As New ADODB.Command
Dim prm As ADODB.Parameter
With cmd
.ActiveConnection = "insert connection string"
.CommandType = adCmdStoredProc
.CommandText = "NameofStoredProcedure"
Set prm = .CreateParameter("@LocationID", adInteger, adParamInput)
prm.Value = frm.txtLocationID
.Parameters.Append prm
Set prm = .CreateParameter("@LocationName", adVarWChar, adParamInput, 255)
prm.Value = frm.txtLocationDetailName
.Parameters.Append prm
.Execute
End With
【讨论】:
感谢您的回答。 access和sql server之间的连接没有问题。我有链接表和路径抛出查询。但是您的解决方案将如何改变性能?据我所知,访问在一个事务中发送一行,这就是为什么在服务器之间复制数百万行需要这么长时间。以上是关于自动将数据从 Access 插入 Sql server的主要内容,如果未能解决你的问题,请参考以下文章
从 Access 插入/更新链接的 SQL Server 表
MS Access - 从文本框中的用户输入将参数传递给 SQL 语句