Мне нужно написать файл Access 97 .mdb
Мне нужно экспортировать данные из базы данных SQL Server 2005 в файл Access 97 .mdb. Клиент, которому это нужно, должен быть Access 97, потому что системе, в которую они импортируют, требуется формат файла Access 97 (не начинайте меня). Любые предложения, как написать старый файл Access из SQL или.Net (или VB6 или Ruby или Python..)?
Заранее спасибо Ли
6 ответов
Что вам нужно сделать, так это экспортировать в файл Access любую версию Access, которую вы установили (если это 2000...2003; Access 2007 не может записывать в файлы Access 97). Я полагаю, вы уже знаете, как это сделать.
Затем вы можете создать объект Access через COM и попросить его преобразовать ваш новый файл.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 в этой версии. Конечно, вам не нужно конвертировать файл в этом случае в любом случае.
Я бы позволил Sql 2005 сделать это за тебя.
В Sql Management Stuidio щелкните правой кнопкой мыши исходную базу данных, затем "Задачи", затем "Экспорт данных". Вы можете использовать это для экспорта непосредственно в базу данных Access, просто следуйте инструкциям. Или вы можете вывести его в формат файла, который вы можете использовать для доступа в Access.
Лучший способ сделать это через PInvoke. Вам нужно будет передать CREATE_DBV3
параметр для SqlConfigDataSource (). Вот код, взятый из JetSqlUtil.cs моего проекта OSS PlaneDisaster.NET:
#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://stackru.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-сервера, вам потребуется 64-разрядная версия Office 2010 или установленный распространяемый компонент Microsoft Access Database Engine 2010.
Это большой вопрос! Я на самом деле хотел иметь возможность делать такие вещи программным способом, но в прошлом у меня не было ничего, кроме проблем с этим. Тем не менее, с годами я немного повзрослел в своих навыках.NET, и я подумал, что смогу написать решение, которое можно было бы выполнить как консольное приложение. Это может быть реализовано в виде запланированной задачи на сервере Windows или SQL Server (с использованием агента Sql Server). Я не понимаю, почему это не может быть автоматизировано с сервера Sql без следующего кода, но я действительно получил удовольствие от этого, поэтому мне просто нужно выложить его там. Таблица в Sql и Access - это список собак с идентификатором, именем, породой и окрасом. Общие вещи. Это на самом деле работает на моем рабочем столе между локальным экземпляром 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();
}
Это может дать вам отправную точку. И эта статья немного старая, но вы можете кое-что поднять. Я могу найти только те, кто использует Jet 4.0, который совместим с Access 2000, как в предыдущей статье. Использование драйвера MS Access может дать вам то, что вы хотите.
После того, как вы создали базу данных, используйте обычные вещи, связанные с ODBC / OLE DB, в ADO.NET, чтобы создать свою таблицу и заполнить их данными.
Я думаю, что это безумие делать это из SQL Server. Просто создайте ODBC DSN для своего SQL Server, импортируйте таблицы в MDB Access 97 и покончите с этим. Единственная причина, по которой вы могли бы сделать это иначе, - это если вы хотите автоматизировать это и делать это многократно, но это может быть автоматизировано и в Access (TransferDatabase может выполнять импорт ODBC), и будет занимать столько же строк кода, сколько имеется это таблицы для импорта.