Migrating Access Database to SQL Server
 
Published: 14 Sep 2006
Abstract
In this article Byapti demonstrates how to migrate Access database to SQL Server with the help of sample code.
by Amrita Dash
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 39063/ 60

Introduction

Migration is the process of moving some or all database objects from an Access Database (.mdb) to a new or existing SQL Server database or new Access Project (.adp).  A move from Access to SQL Server is generally considered for performance, security and stability.  With the increased volume of databases and with a large number of database users, one may need to convert the Access database to a client-server environment of SQL Server.  Upsizing the access database to SQL server will solve this problem and provide a better application for a large number of users with less network traffic.

Different options available for migrating (upsizing) the access database

Creating a two-tier application

In this case the server based tables are linked with the database tables.  The other existing database objects (queries, forms, reports, modules and macros) are used as before with no modifications.  This creates a two-tier application in which the SQL server stores only the data and copies of the interface are stored in Access.  In this method code modification is not needed in the application because the application is still using the Jet Database Engine, but the queries are still processed locally and a large amount of network traffic is generated.  Therefore, it is not a good method to follow.

Upsizing data without making any modifications to the Access Application

In this method the application specific logic and the user interfaces are not migrated.  Only data is migrated.  You have to rewrite the whole application code and recreate the forms and reports. It is a very tedious method.

Creating a client – server application

In this method an Access Project (.adp) is created which is connected to the SQL Server database, creating a client-server application.  All tables and data definition objects, such as views and stored procedures, are stored on the server.  However, the forms, reports, etc. are stored at the client side.  Minimum code modifications are needed in this approach.  In this case, most data processing is done at the server minimizing network traffic.  We followed this approach.        

Upsizing Process

The Upsizing Wizard upsizes an Access database to a new or existing SQL Server database or new access project by migrating data and data definitions and then moving database objects to the new database structure.  The upsizing wizard provides different options for migrating the table attributes, such as indexes, validation rules, defaults and table relationships.  One should always choose the DRI (Declared Referential Integrity) option under the table relationships to enforce referential integrity.  The upsizing wizard adds a “CS” suffix to the current access database name and stores this ADP project in the same location as the existing Access Database.

After migrating the tables and queries, the upsizing wizard creates a report that provides a detailed description of all the objects created and any errors encountered during the process.  It provides information about Database details (size, device names etc.), upsizing parameters (table attributes chosen for upsizing, table information including column names, data types, indexes etc.), table relationships and any errors encountered (tables not created, inadequate permissions, queries not upsized, validation rules skipped etc.).

Access and SQL Server vary in the way data is stored, the data types available and the storage capabilities.  All the tables that are upsized should be manually inspected.  So after upsizing the database through the Upsizing Wizard, we compared the tables in the access database and SQL Server according to the Upsizing Wizard Report and then made necessary changes to the SQL tables.  All the column names, data types and the index property were checked and modified if required.  All access database data types were converted to their equivalent in SQL.

ACCESS                                              SQL

Number                                      Int/TinyInt/SmallInt

Yes/No                                                Bit

Text                                          Char/Nchar/Varchar  

Currency                                    Money

Date/Time                                  Datetime/SmallDatetime

Memo                                         Text/Ntext

OLE Object                                 Binary/Image

AutoNumber/AutoIncrement           Identity

Only simple SELECT queries were converted to views.  SQL statements in record source, control source or row source of the forms, reports and controls were not converted.  The Modules and Macros also remained the same.

Changes Made After Upsizing the Database

Some features of access are not supported by SQL server, so one has to manually analyze and rectify any such issues during and after upsizing process.

1. The Forms, Reports, Modules and Macros are imported from the Access .mdb file.  From the File ->Get External Data ->Import options all forms, reports, modules and macros were imported.

2. Then the queries were changed.  Access queries can be divided into 3 types.

Views: These are the simple SELECT statements with no input parameters or return values.  These are used as virtual tables.

Stored Procedures: These are the queries that accept input parameters.  INSERT, DELETE and UPDATE statements were also converted to SQL Stored procedures.

User-defined Functions: These are the queries that accept some input parameters and return a single value or a table.  These are the subroutines that are used repeatedly in the application.

3. To make the .adp file access data from the SQL Server we changed the connection string and converted the DAO code to its ADO equivalent.  The connection string was made pointed to the SQL Server database.

Data Access Object (DAO)

DAO is a data access technology primarily designed to use the Jet databases like Microsoft Access or dBase, FoxPro, etc.

ActiveX Data Objects (ADO)

ADO uses the OLE DB technology to gain access to any type of data source.  The ADO object model is based on three types of objects namely Connection, Command and Record set. The connection object holds data source connection information like data source name, its location, the user id and password, the name of the OLE DB provider, etc.  The command object is used to execute SQL commands, queries and stored procedures.  The Record set object holds the results returned by the queries and used for adding records to the tables and updating the database.  In ADO, "CurrentProject. Connection" determines the connection string.

The connection string is:

Provider=Microsoft.Access.OLEDB.10.0; Persist Security
 Info=False; Data Source=192.168.10.3; User ID=sa; Initial Catalog= Database
 Name; Data Provider=SQLOLEDB.1

Opening and Adding Value to a Record Set

Let us now examine how to open and add value to a recordset using DAO and ADO.

Listing 1 - DAO    

Dim db as Database
Dim rs as DAO.Recordset
Set db = CurrentDb( )
Set rs = db.OpenRecordset(“tblPeople”)
rs.Edit
rs(“TextFieldName”) = “New Value”
rs.Update

Listing 2 - ADO

Dim rs As New ADODB.Recordset
rs.Open "tblPeople", CurrentProject.Connection, _
adOpenKeyset, adLockOptimistic           
rs.AddNew
rs("TextFieldName ") = NewValue
rs.Update
rs.Close

Executing a Query

Listing 3 - DAO

db.Execute "SELECT ……………………………."

Listing 4 - ADO

Dim CommandText As String
CommandText = "SELECT……………………….."
rs.Open CommandText, CurrentProject.Connection, _
adOpenStatic, adLockReadOnly, adCmdText   

These changes were made throughout the code in the application.

4. The record source, control source or the row source of all the forms and reports remained unchanged after upsizing.  So we had to manually change the record source properties of all the forms and reports used.  The record source of all the Forms and Reports were modified to make them compatible with the SQL.  Listed below are some keywords that need to be changed for making them compatible with SQL Server.

ACCESS                                              SQL

TRIM                                         LTRIM/RTRIM

DISTINCTROW                             DISTINCT

IIF (expr)                                   CASE…WHEN

TRUE/FALSE                                1/0

& (for string concatenation)           +

FORMAT ( )                                 CONVERT ( )

CINT                                          CAST

UCASE                                       UPPER

LCASE                                        LOWER

ORDER BY in Views                       Not Supported

NOW ( )                                     GETDATE ( )

In Access the ISNULL () function returns 1 if the supplied parameter is NULL and 0 if it is not.  In SQL Server there are two parameters and the function works more like a CASE statement.

5. When a Form’s Record Source takes some parameters it has to be changed to a Stored Procedure and the parameters are to be passed through the input parameter property of the form.

Record Source: Stored Procedure Name

Input Parameter: [Forms]! [Form Name]! [Fieldname]

The Sub forms record sources that took the input value from the Main Form are converted to stored procedures so that they will be populated according to the value in the main form.

Problems Faced and Their Solutions

Complex queries

The cross tab queries and other complex queries were not converted to their equivalent in SQL.  We had to manually convert those complex queries to make them compatible with SQL Server. Those were converted to views, stored procedures or functions.

Write-Conflict Error

“This record has been changed by another user since you started editing it. If you save the record, you will overwrite the changes the other user made. Copying the changes to the clipboard will let you look at the values the other user entered, and then paste your changes back in if you decide to make changes.”

Parent!LastUpdateBy = CurrentUser( ) and Parent!LastUpdateDate = Date.  These two lines of code were not supported in Access ADP and we found this to be the reason for the Write Conflict error on the sub forms in our project.  We removed these two lines of code to avoid a write conflict error.  However, we had to add LastUpdatedBy = CurrentUser () and LastUpdateDate = Date only in the Save Button Function to update the forms at the end.  In this case, the main form did not get updated immediately after any modifications were made to the sub forms value.  It only got updated after pressing the “Save Button.”  The cause of write conflict error may be different for other ADP applications.  It may be due to not assigning a default value to a bit data type in SQL or due to some primary key problems.

The Write Conflict error may appear when two forms that update the same data source are opened at the same time.  The first form puts an edit lock on the record(s) and then the second form changes the record(s) and saves the changes.  When the first form tries to close and write back to the table, the changes that were made by the second form are detected.  This causes the error to be returned.

Docmd.TransferText and Docmd.TransferSpreadSheet

These commands are used to export records to a text file or an excel sheet with proper format and are not supported by Access ADP.

For the Docmd.TransferText Command we had to create a file system object and use that to write the whole record into a text file.  The record was fetched by executing a view or stored procedure.  All the columns of each record were written into the text file using a loop.  The CreateTextFile and Writeline function of the file system object were used to write the records into a specific text file in a specified location.

Listing 5

In Access: 
DoCmd.TransferText acExportDelim, , "QueryName", sPath & "\FileName.txt", True, , 65001
 
Modified Code:
Dim CommandText As String
Dim rs As New ADODB.Recordset
Dim strMsg As String
Dim strText As String
Dim strFileText As String
Dim strHeaderText As String
Dim fs
Dim a
 
CommandText = "Exec QueryName '" & parameter& "'"
rs.Open CommandText, CurrentProject.Connection, adOpenKeyset, adLockOptimistic, adCmdText
  
If rs.RecordCount = 0 Then
  DoCmd.Hourglass False
  MsgBox "No Records to Export!"
  Exit Sub
  End If
 
strHeaderText = strHeaderText & """FieldName1""" & ","
strHeaderText = strHeaderText & """FieldName2"""
strFileText = strFileText & strHeaderText & vbCrLf
 
rs1.MoveFirst
 Do While Not rs.EOF
    strText = strText & """" & rs1 ("FieldName1") & """" & ","
    strText = strText & """" & rs1("FieldName2") & """"
    strFileText = strFileText & strText & vbCrLf
    strText = ""
    rs.MoveNext
 Loop
     
     Set fs = CreateObject("Scripting.FileSystemObject")
     Set a = fs.CreateTextFile(sPath & "\FileName.txt", True)
     a.WriteLine (strFileText)
     a.Close
     rs.Close
     Set rs = Nothing
Docmd.TransferSpreadSheet:
For this command also we changed the syntax accordingly.
 
In Access: 
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, "QueryName", sFilename, True
 
Modified Code:
DoCmd.OutputTo acOutputServerView, _
 “ViewName ", acFormatXLS, sFilename, False
OR
DoCmd.OutputTo acOutputStoredProcedure, _
 "StoredProcedureName ParameterName", acFormatXLS, sFilename, False

Docmd.OpenForm Taking Parameter

Docmd.OpenForm taking input parameters was not supported in access ADP.  We had to convert the record source of the form to a view.  Only then did this command work.

DoCmd.OpenForm FormName, , , Condition

Print Functionality

In the print functionality we faced the problem of Header Record Delimiter Error.  For that, a header file with all the columns with appropriate delimiters had to be written.  We added the header file with “,” as field delimiter and “enter” as record delimiter and that solved our problem.

Updatable View

If the record source of a form is not an updatable view then one cannot edit any field of the form.  And the status bar always shows the error message “The Recordset is Not Updatable.”  Tables without unique index will be upsized, but they will be read-only in SQL Server.   We added a unique index to each of the tables used and made the required view updatable.  The view should not contain the following things to be updatable.

- A Set Operator (Union, Intersect, Minus, Union All)

- Distinct Operator

- Aggregate Functions (Sum, Avg, Count, etc.)

- A Group By Clause

- The select list with components other than column specification or more than one specification of the same column.

Error While Inserting Records to a Form

Sometimes when adding a record to an ADP form an error message appears:

“The data was added to the database but the data won't be displayed in the form because it doesn't satisfy the criteria in the underlying record source.”

For this we have to set the ResyncCommand Property of the Form in the design view to a SQL statement.

For Example: Resync Command: Select * From tblName where FieldName = ?

If the Rowsource contains a stored procedure with multiple tables joined together then the Resync Command Property of the form should be set to an SQL statement that selects the same fields as the stored procedure and parameterize the primary key of the table that is designated as the Unique Table.

Compromises Made In Our ADP Application

In the MDB application, after changing anything in the sub forms, the main form used to be updated immediately.  However, in our ADP application we had to press the “save button” to update the main form after any modifications were made to any of the sub forms due to the “write conflict error” problem.

Summary

An ADP is a specific Access file type that stores user objects such as forms, reports, macros, and Visual Basic for Applications (VBA) code modules.  All the other objects—the tables, stored procedures, views, and so on—are stored on the database server.  It has its own advantages and disadvantages.  Here the server is responsible for all query processing and fewer resources are needed at the client side.  It can handle a large number of database users.  On the other hand, one cannot create local tables or local queries.  It is tied to one database engine and cannot be linked to multiple data sources.

We had a very good experience working on this project.  We learned a lot about the differences between Access and SQL Server database.  Not many code modifications were needed.  Only DAO to ADO code conversion was applied throughout the application.  Creating an ADP file was the best option we had for migrating the Access database to SQL server.

Amrita Dash
Mindfire Solutions


User Comments

Title: Mr   
Name: Ajayi Gbolahan
Date: 2011-10-17 12:54:49 PM
Comment:
This is exactly the challenge i am confronted with at present i hope this will solve my promlem
Title: Academic Professor   
Name: Dr. Fekry Fouad
Date: 2010-08-01 10:42:12 AM
Comment:
Hi

Finally I got what I was looking for , it is an excellent step to migrate from ACCESS database into SQL and VB.NET.

I am Egyptian professor , currently I am on Saudi Arabia for consultancy (maily migration) , I would like to know more - if possible - about the methodology . in case you like the idea , please advise how we can cooperate , a lot of business and the backlog of access is so much , all of them are very much willing to have a saved migration.

Please send this answer to info@ittg.org

Regards

Dr. Fekry Fouad
00966560037271
Title: Academic Professor   
Name: Dr. Fekry Fouad
Date: 2010-08-01 10:40:13 AM
Comment:
Hi

Finally I got what I was looking for , it is an excellent step to migrate from ACCESS database into SQL and VB.NET.

I am Egyptian professor , currently I am on Saudi Arabia for consultancy (maily migration) , I would like to know more - if possible - about the methodology . in case you like the idea , please advise how we can cooperate , a lot of business and the backlog of access is so much , all of them are very much willing to have a saved migration.

Regards

Dr. Fekry Fouad
00966560037271
Title: SQL Svr DBA   
Name: KLM
Date: 2010-04-09 9:10:03 AM
Comment:
Hello Amrita.
I am currently involved in Migrating our Access2007 based application back-end (database) to SQL Server2005.
That said, I am using the client – server application approach that requires me to modify the ADO connect string.
Thus my question to you is:
How do I or where do I go to change the Connect string in the generated __.adp project file?

Thank you.

KK.

Please send this answer to kkmore@yahoo.com
Title: Migration   
Name: Sudhir Kumar
Date: 2010-01-29 6:12:37 AM
Comment:
i neeed urgently a code to transfer access table to sql server 2000
please help out
Title: Mr   
Name: Keith
Date: 2009-12-17 8:51:46 AM
Comment:
This type of article helps new computer profeshnals.
Title: migration   
Name: ashish
Date: 2009-07-13 9:37:39 AM
Comment:
i neeed urgently a code to transfer access table to sql table
please help out
Title: stored procedures   
Name: raimund popp
Date: 2007-04-12 10:12:25 AM
Comment:
did you also find a way how to get the sql-property of a stored procedure like querydefs(xx).sql

regards
raimund
Title: Covert excel file data into a MSSQL server databases   
Name: indu
Date: 2007-01-30 9:50:26 PM
Comment:
I want to upload a Excel file datas into MSSQL serve databae
Title: Great Article   
Name: Mike
Date: 2007-01-22 3:41:25 PM
Comment:
That has to be one of the best examples I have seen, saving me hours of writing stored procedures. Great example, especially the DAO / ADO comparison.
The only suggestion is to remove the space from the line:
rs("TextFieldName ") = NewValue
it should read rs("TextFieldName") = NewValue as that extra space cause Access to Error on Item not in collection (Error 3265). Thanks for saving me many hours.
Title: Problems with relation database   
Name: Ananda
Date: 2006-12-05 2:44:27 AM
Comment:
Hi!

Its excellent article.
But problem is relational database.
If you have primary id of one table as foreign key to another table then exporting database by this way will not slove that problem.
Relation will not work as the new id will be different that what you have in your your foreign table.






Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-04-19 3:46:51 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search