我需要将数据从 SQL Server 2005 DB 导出到 Access 97 .mdb 文件。需要它的客户端需要它是 Access 97,因为他们将其导入的系统需要 Access 97 文件格式(不要让我开始)。有什么建议如何从 SQL 或 .Net(或 VB6 或 Ruby 或 Python ..)编写老式的 Access 文件?
提前谢谢,李
我需要将数据从 SQL Server 2005 DB 导出到 Access 97 .mdb 文件。需要它的客户端需要它是 Access 97,因为他们将其导入的系统需要 Access 97 文件格式(不要让我开始)。有什么建议如何从 SQL 或 .Net(或 VB6 或 Ruby 或 Python ..)编写老式的 Access 文件?
提前谢谢,李
我会让 Sql 2005 为你做这件事。
在 Sql Management Stuidio 中,右键单击源数据库,然后单击 Tasks,然后单击 Export Data。您可以使用它直接导出到您的 Access 数据库中,只需按照提示操作即可。或者,您可以将其输出为可用于放入 Access 的文件格式。
您需要做的是将您安装的任何 Access 版本导出到 Access 文件中(只要它是 2000...2003;Access 2007 无法写入 Access 97 文件)。我假设你已经知道如何做到这一点。
然后您可以通过 COM 创建一个 Access 对象,并要求它将您的新 .mdb 文件转换为新的 Access 97 数据库。在 VBScript 中,代码如下所示(如果您使用 VBA、VB.Net 或其他语言,请根据需要进行调整):
const acFileFormatAccess97 = 8
dim app
set app = CreateObject("Access.Application")
app.ConvertAccessProject "y:\mydatabase.mdb", "y:\mydatabase97.mdb", acFileFormatAccess97
如果您安装了 Access 97,上述命令将不起作用,因为 Access 在该版本中没有 ConvertAccessProject 功能。当然,在这种情况下,您无论如何都不需要转换文件。
这是一个很好的问题!我实际上希望能够以编程方式做这种事情,但在过去,我除了想出它之外什么都没有。然而,这些年来我的 .NET 技能已经成熟了一点,我想我会尝试编写一个可以作为控制台应用程序执行的解决方案。这可以作为 windows server 或 sql server(使用 Sql Server 代理)上的计划任务来实现。我不明白为什么如果没有以下代码就不能从 Sql Server 自动执行此操作,但我真的很喜欢这个,所以我只需要把它放在那里。Sql 和 Access 中的表都是狗的列表,带有 ID、名称、品种和颜色。通用的东西。这实际上适用于我的本地 Sql Server 实例和 Access 之间的桌面(2007,但我没有 不知道为什么它不适用于 97)。请随时批评。
顺便说一句,具有以下内容:
using System.Data;
using System.Data.OleDb;
using System.Data.SqlClient;
这里:
static void Main(string[] args)
{
SqlConnectionStringBuilder cstrbuilder = new SqlConnectionStringBuilder();
cstrbuilder.DataSource = "localhost";
cstrbuilder.UserID = "frogmorton";
cstrbuilder.Password = "lillypad99";
cstrbuilder.InitialCatalog = "Dogs";
SqlConnection sconn = new SqlConnection(cstrbuilder.ToString());
sconn.Open();
SqlCommand scmd = new SqlCommand("select * from Dogs", sconn);
SqlDataReader reader = scmd.ExecuteReader();
if (reader.HasRows)
{
OleDbConnectionStringBuilder sb = new OleDbConnectionStringBuilder();
sb.Provider = "Microsoft.Jet.OLEDB.4.0";
sb.PersistSecurityInfo = false;
sb.DataSource = @"C:\A\StackOverflog\DogBase.mdb";
OleDbConnection conn = new OleDbConnection(sb.ToString());
conn.Open();
OleDbCommand cmd = new OleDbCommand("Delete from Dogs", conn);
cmd.CommandType = CommandType.Text;
cmd.ExecuteNonQuery();
conn.Close();
OleDbConnection conn2 = new OleDbConnection(sb.ToString());
conn2.Open();
OleDbCommand icmd = new OleDbCommand("Insert into dogs (DogID, DogName, Breed, Color) values ({0}, '{1}', '{2}', '{3}');", conn2);
icmd.CommandType = CommandType.Text;
while (reader.Read())
{
string insertCommandString =
String.Format("Insert into dogs (DogID, DogName, Breed, Color) values ({0}, '{1}', '{2}', '{3}');"
, reader.GetInt32(0)
, reader.GetString(1)
, reader.GetString(2)
, reader.GetString(3)
);
icmd.CommandText = insertCommandString;
icmd.ExecuteNonQuery();
}
conn2.Close();
}
sconn.Close();
}
最好的方法是通过PInvoke您需要将CREATE_DBV3
参数传递给SqlConfigDataSource()。这是从我的 OSS 项目PlaneDisaster.NET的JetSqlUtil.cs中获取的代码:
#region PInvoke
private enum ODBC_Constants : int {
ODBC_ADD_DSN = 1,
ODBC_CONFIG_DSN,
ODBC_REMOVE_DSN,
ODBC_ADD_SYS_DSN,
ODBC_CONFIG_SYS_DSN,
ODBC_REMOVE_SYS_DSN,
ODBC_REMOVE_DEFAULT_DSN,
}
private enum SQL_RETURN_CODE : int
{
SQL_ERROR = -1,
SQL_INVALID_HANDLE = -2,
SQL_SUCCESS = 0,
SQL_SUCCESS_WITH_INFO = 1,
SQL_STILL_EXECUTING = 2,
SQL_NEED_DATA = 99,
SQL_NO_DATA = 100
}
[DllImport("ODBCCP32.DLL",CharSet=CharSet.Unicode, SetLastError=true)]
private static extern int SQLConfigDataSource (int hwndParent, ODBC_Constants fRequest, string lpszDriver, string lpszAttributes);
[DllImport("ODBCCP32.DLL", CharSet = CharSet.Auto)]
private static extern SQL_RETURN_CODE SQLInstallerError(int iError, ref int pfErrorCode, StringBuilder lpszErrorMsg, int cbErrorMsgMax, ref int pcbErrorMsg);
#endregion
internal static string GetOdbcProviderName()
{
if (string.IsNullOrEmpty(OdbcProviderName))
{
var odbcRegKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\ODBC\\ODBCINST.INI\\ODBC Drivers", false);
var drivers = new List<string>(odbcRegKey.GetValueNames());
if (drivers.Contains("Microsoft Access Driver (*.mdb, *.accdb)"))
{
OdbcProviderName = "Microsoft Access Driver (*.mdb, *.accdb)";
}
else if (drivers.Contains("Microsoft Access Driver (*.mdb)"))
{
OdbcProviderName = "Microsoft Access Driver (*.mdb)";
}
else
{
//TODO: Condider checking for 32 versus 64 bit.
//TODO: Find a better exception type. http://stackoverflow.com/questions/7221703/what-is-the-proper-exception-to-throw-if-an-odbc-driver-cannot-be-found
throw new InvalidOperationException("Cannot find an ODBC driver for Microsoft Access. Please download the Microsoft Access Database Engine 2010 Redistributable. http://www.microsoft.com/download/en/details.aspx?id=13255");
}
}
/// <summary>
/// Creates an Access 2003 database. If the filename specified exists it is
/// overwritten.
/// </summary>
/// <param name="fileName">The name of the databse to create.</param>
/// <param name="version">The version of the database to create.</param>
public static void CreateMDB (string fileName, AccessDbVersion version = AccessDbVersion.Access2003) {
;
if (File.Exists(fileName)) {
File.Delete(fileName);
}
string command = "";
switch (version)
{
case AccessDbVersion.Access95:
command = "CREATE_DBV3";
break;
case AccessDbVersion.Access2000:
command = "CREATE_DBV4";
break;
case AccessDbVersion.Access2003:
command = "CREATE_DB";
break;
}
string attributes = String.Format("{0}=\"{1}\" General\0", command, fileName);
int retCode = SQLConfigDataSource
(0, ODBC_Constants.ODBC_ADD_DSN,
GetOdbcProviderName(), attributes);
if (retCode == 0)
{
int errorCode = 0 ;
int resizeErrorMesg = 0 ;
var sbError = new StringBuilder(512);
SQLInstallerError(1, ref errorCode, sbError, sbError.MaxCapacity, ref resizeErrorMesg);
throw new ApplicationException(string.Format("Cannot create file: {0}. Error: {1}", fileName, sbError));
}
}
如果您需要从 64 位版本的 SQL Server 执行此操作,则需要安装 64 位版本的 Office 2010 或Microsoft Access Database Engine 2010 Redistributable。
我认为从 SQL Server 执行此操作很疯狂。只需为您的 SQL Server 创建一个 ODBC DSN 并将表导入您的 Access 97 MDB 并完成它。您可能想要这样做的唯一原因是如果您想自动化它并重复执行它,但这也可以在 Access 中自动化(TransferDatabase 可以执行 ODBC 导入),并且只需要与那里一样多的代码行是要导入的表。