Question : Copy/Export SQL Server Database to Access

I have a routine that is called with the click of a button in VB6. I am using MS SQL Server 2005 Express, and MS Access 97-2003 databases. The routine deletes my existing Access DB, recreates an empty one, then loops through the tables in the SQL Server DB, creating them then filling them with the table's data. It works perfectly, except it is slow on tables with large amounts of data. That is because for each SQL table, it opens a recordset, builds an "insert" string, and adds the row to the Access DB.

I have commented out the code I need to be replaced. I would like this code replaced with one statement that copies the records in one go. I have tried every permutation of statements like "SELECT * INTO <Target> FROM <Source>" (doesn't work because it tries to create the already-existing table). Also tried "INSERT INTO <Target> SELECT * FROM <Source>", and a million other things. There must be a way, I just can't find it, or maybe I have but had syntax errors.

This is going to be a tough one. I don't want to create my tables any differently, I don't want to hear about DTS or SSIS, stored procedures, or linked databases. At the point where the code is commented out, both databases are open, all table names are known and exist in both DB's, and everything's ready for the copying procedure. I just want a nice clean SQL statement/query that will copy the records faster than running through the recordsets. The only other answer I might accept is cutting out the commented code, closing the databases, and copying the tables differently. But remember, you will lose the table names that way and will need to fetch them again. The idea of this routine is to copy any SQL database to an Access DB, without knowing anything about the tables or their structure.

Sounds easy, but it's been driving me nuts. Can anyone help? Below is the routine:

Function SQLtoAccess() As Boolean
   Dim sqlDB As New ADODB.Connection
   Dim jetDB As New ADODB.Connection
   Dim rs As New ADODB.Recordset
   Dim rt As New ADODB.Recordset
   ReDim Tables$(0)
   
   On Local Error GoTo Hell
   
   Rem *** Delete old Jet database ***
   If Len(Dir$(DBFileSpec$)) Then
      Call CRFO(DBFileSpec$, "k", h%, 0)  'kill file
   End If
   
   Rem *** Create new Jet database ***
   Call CreateAccessDB(DBFileSpec$)
   
   Rem *** Open SQL Server ***
   sqlDB.Open SQLFileSpec$

   Rem *** Grab all SQL tables ***
   SQL$ = "SELECT * FROM INFORMATION_SCHEMA.Tables ORDER by Table_Type, Table_Name"
   rs.Open SQL$, sqlDB, adOpenForwardOnly, adLockReadOnly
   While Not rs.EOF
      Rem *** Save table name ***
      ReDim Preserve Tables$(UBound(Tables$) + 1)
      Tables$(UBound(Tables$)) = rs!Table_Name
      rs.MoveNext
   Wend
   rs.Close
   
   Screen.MousePointer = 11   'hourglass
   
   Rem *** Connect to Jet database ***
   jetDB.Provider = "Microsoft.Jet.OLEDB.4.0"
   jetDB.Open DBFileSpec$
   
   Rem *** Cycle thru tables, making and filling them ***
   For i% = 1 To UBound(Tables$)
      Rem *** Get table info ***
      mesa$ = Tables$(i%)
      SQL$ = "SELECT '" & mesa$ & "' FROM INFORMATION_SCHEMA.Tables"
      rs.Open SQL$, sqlDB, adOpenForwardOnly, adLockReadOnly
      If Not rs.EOF Then
         Rem *** Get Column info ***
         SQL$ = "SELECT Column_Name, Data_Type, Character_Maximum_Length, Is_Nullable "
         SQL$ = SQL$ & "FROM INFORMATION_SCHEMA.Columns WHERE "
         SQL$ = SQL$ & "Table_Name = '" & mesa$ & "'"
         rt.Open SQL$, sqlDB, adOpenForwardOnly, adLockReadOnly
         tbl$ = "("
         While Not rt.EOF
            Select Case rt!Data_Type
               Case "bit"
                  Rem *** Yes/No ***
                  txt$ = "YESNO"
               Case "tinyint"
                  Rem *** Byte ***
                  txt$ = "BYTE"
               Case "smallint"
                  Rem *** Integer ***
                  txt$ = "INTEGER"
               Case "int"
                  Rem *** Long Integer ***
                  txt$ = "LONG"
               Case "smallmoney", "money"
                  Rem *** Currency ***
                  txt$ = "CURRENCY"
               Case "real"
                  Rem *** Single ***
                  txt$ = "SINGLE"
               Case "float"
                  Rem *** Double ***
                  txt$ = "DOUBLE"
               Case "datetime", "smalldatetime", "timestamp"
                  Rem *** Date/Time ***
                  txt$ = "DATETIME"
               Case 9
                  Rem *** Binary ***
                  txt$ = "BINARY"
               Case "nvarchar", "varchar", "nchar", "char"
                  Rem *** Text ***
                  ds$ = CStr(rt!Character_Maximum_Length)
                  txt$ = "NVARCHAR(" & ds$ & ")"
               Case "image"
                  Rem *** OLE Object ***
               Case "memo"
                  Rem *** Memo or Hyperlink ***
                  txt$ = "MEMO"
            End Select
            If rt!Is_Nullable = "NO" Then
               txt$ = txt$ & " NOT NULL"
            End If
            tbl$ = tbl$ & "[" & rt!Column_Name & "]" & " " & txt$ & ","
            rt.MoveNext
         Wend
         Mid$(tbl$, Len(tbl$), 1) = ")"
         rt.Close
         rs.Close
         Rem *** Create the damn thing already! ***
         SQL$ = "CREATE TABLE [" & mesa$ & "] " & tbl$
         jetDB.Execute SQL$, , adExecuteNoRecords
         Rem *** Find all Primary Keys ***
         SQL$ = "SELECT s.name AS TABLE_SCHEMA, t.name AS TABLE_NAME, k.name AS CONSTRAINT_NAME, k.type_desc AS CONSTRAINT_TYPE, "
         SQL$ = SQL$ & "c.name AS COLUMN_NAME, ic.key_ordinal AS ORDINAL_POSITION "
         SQL$ = SQL$ & "FROM sys.key_constraints AS k "
         SQL$ = SQL$ & "JOIN sys.tables AS t ON t.object_id = k.parent_object_id "
         SQL$ = SQL$ & "JOIN sys.schemas AS s ON s.schema_id = t.schema_id "
         SQL$ = SQL$ & "JOIN sys.index_columns AS ic ON ic.object_id = t.object_id AND ic.index_id = k.unique_index_id "
         SQL$ = SQL$ & "JOIN sys.columns AS c ON c.object_id = t.object_id AND c.column_id = ic.column_id "
         SQL$ = SQL$ & "ORDER BY TABLE_SCHEMA, TABLE_NAME, CONSTRAINT_TYPE, CONSTRAINT_NAME, ORDINAL_POSITION"
         rt.Open SQL$, sqlDB, adOpenForwardOnly, adLockReadOnly
         Rem *** Set the table's Primary Keys ***
         txt$ = ""
         While Not rt.EOF
            If rt!Table_Name = mesa$ Then
               If rt!Constraint_Type = "PRIMARY_KEY_CONSTRAINT" Then
                  ConName$ = rt!Constraint_Name
                  txt$ = txt$ & "[" & rt!Column_Name & "],"
               End If
            End If
            rt.MoveNext
         Wend
         rt.Close
         If Len(txt$) Then
            Mid$(txt$, Len(txt$), 1) = ")"
            SQL$ = "ALTER TABLE [" & mesa$ & "] ADD CONSTRAINT [" & ConName$ & "] PRIMARY KEY (" & txt$
            jetDB.Execute SQL$, , adExecuteNoRecords
         End If
      End If
      Rem *** Fill 'er up! ***
      SQL$ = "SELECT * FROM [" & mesa$ & "]"
      rs.Open SQL$, sqlDB, adOpenForwardOnly, adLockReadOnly
      While Not rs.EOF
         SQL$ = "INSERT INTO [" & mesa$ & "] VALUES ("
         For f% = 0 To rs.Fields.Count - 1
            txt$ = SQLStr$(rs.Fields(f%).value)
            If txt$ = "'True'" Then
               txt$ = "-1"
            ElseIf txt$ = "'False'" Then
               txt$ = "0"
            End If
            SQL$ = SQL$ & txt$
            If f% < rs.Fields.Count - 1 Then
               SQL$ = SQL$ & ","
            End If
         Next f%
         SQL$ = SQL$ & ")"
         jetDB.Execute SQL$, , adExecuteNoRecords
         rs.MoveNext
      Wend
      rs.Close
   Next i%
   
   sqlDB.Close
   jetDB.Close
   
   Set rs = Nothing
   Set rt = Nothing
   Set sqlDB = Nothing
   Set jetDB = Nothing
   
   Screen.MousePointer = 0 'normal
   
   SQLtoAccess = True
   
   Exit Function
   
Hell:
   If rs.State = 1 Then
      rs.Close
      Set rs = Nothing
   End If
   If rt.State = 1 Then
      rt.Close
      Set rt = Nothing
   End If
   If sqlDB.State <> adStateClosed Then
      ssiDB.Close
      Set sqlDB = Nothing
   End If
   If jetDB.State <> adStateClosed Then
      jetDB.Close
      Set jetDB = Nothing
   End If
   i% = MsgBox("Internal error", vbCritical, "SQLtoAccess" & vbCrLf & vbCrLf & Err.desription)
   Screen.MousePointer = 0 'normal

End Function

For reference, an example of SQLFileSpec$ is:
Provider=SQLOLEDB.1;Persist Security Info=FALSE;User ID=MyUserName;Password=MyUserPassword;Initial Catalog=MyDatabase;Data Source=(local)\SQLEXPRESS;Connect Timeout=5

And DBFileSpec$ is:
C:\Database\MyAccess.mdb

TIA for any assistance anyone can lend.

Answer : Copy/Export SQL Server Database to Access

I understand that, as you have stated, using the IP works but not the 'DNS' name, or FDQN as I like to call it.
The difference in the process or 'routing' of the request to authenticate is the issue as you have stated it.
Let's examine the differences: The XP VM is logged in to the domain, and therefore has a certificate at the ready, and it knows the user's fully-qualified name and password. Hence the automatic or 'pass-through' login.

How do we simulate this on the server?
When you log in from the server, using the built-in IE, you are using the administrator's (or an admin-type) for credentials.
To the IIS this looks like [email protected]sion OR NETBIOSNAME/username OR username.domain.extension OR username@NETBIOSNAME, OR CN=administrator, OU=etc , OU=etc,  etc.
This leaves a lot of iterations to find the proper login for a user.
HOWEVER: when you use the IP, the IE doesn't forward the Windows credentials. IT BLANKS OUT THOSE FIELDS.
The most likely failure is that the server is appending the domain to an already existing domain name; like this: username.domain.com.domain.com
This user doesn't exist, and can't login. Nevermind that you just typed in username or username.domain.com
Since you state that the XP and the clustered servers all point to the exact same DNS, then the problem must lie in one of three places:
1. The IE
2. The domain settings in the NIC interface are somehow different than the XP unit. Look at the DNS settings and compare the XP VM with the server. Look at the domain settings.
3. The IIS -- this could be an issue with the credentials required and the forms as well as the virtual directory.
There should be an error in the event viewer when the login fails. It will tell you which issue you're facing, at least in the sense that it will identify wrong name or password (remember, it doesn't matter that you put it in right, it matters that it agrees with the format IIS wants it and that format is altered when you are on the local machine), or something like 'requires SSH' or something.

My guess is: The servers are adding domain tags or something when you login directly from them. If you use a FQDN, the DNS provides the IP, the SRV records etc. etc. This information is being auto-added to the credentials you type in. This exact problem happens on non-clustered Exchange if you log in to the server as local admin (when the Exchange server is not a DC). The local admin's name is followed by the machine name (admin.termserver1) and then when you try to use OWA, your name comes out like administrator.domain.extension@termserver1
It fails. Use the IP, and it accepts the typed in creds.
Random Solutions  
 
programming4us programming4us