VBA Code for Transferring ACCESS Table to SQL Server - ms-access

I was trying to Transfer my Access Table Data over to SQL server but I am getting an error which says
Object Variable or With block variable not set
I've already connected my Access database with SQL server but now facing problem transferring data to SQL server with VBA code.
Can you please help me with it?
Here is my code:
Public Sub ADOtest()
Dim ADOConn As New ADODB.Connection
Dim ADOCom As New ADODB.Command
On Error Resume Next
ADOConn.ConnectionString = "Driver={SQL Server};Server=IT-TEMP2-8470P\SQLEXPRESS2014;Database=Discrepancy;Trusted_Connection=True;"
ADOConn.Open
Debug.Print ADOConn.State
Dim db As Database
Dim Discrepancy As Database
Set db = Discrepancy
Dim ID As Variant
db.Execute "INSERT INTO [ODBC;DRIVER=SQL Server;SERVER=IT-TEMP2-8470P\SQLEXPRESS2014;DATABASE=Discrepancy].SFTransfersDB ( ID, TO ) SELECT ID,TO FROM SFTransfersDB"
End Sub
I am getting error at the 2nd last line:
db.Execute "INSERT INTO [ODBC;DRIVER=SQL Server;SERVER=IT-TEMP2-8470P\SQLEXPRESS2014;DATABASE=Discrepancy].SFTransfersDB ( ID, TO ) SELECT ID,TO FROM SFTransfersDB"

It seems you are attempting an ad hoc distributed query. If server permits it, consider executing this statement after your ADO connection. No need for calling Access objects.
ADOConn.Execute "INSERT INTO dbo.SFTransfersDB ([ID], [TO])" _
" SELECT [ID], [TO] FROM OPENDATASOURCE('Microsoft.ACE.OLEDB.12.0', " _
"'Data Source=""C:\Path\To\Access\Database.accdb""')...SFTransfersDB;"

You declare two Database variables, but don't initialize them (you don't set them to anything):
Dim db As Database
Dim Discrepancy As Database
So this
Set db = Discrepancy
is the same as
Set db = Nothing
and so when you try to use db, you get the error that db is not set, which it isn't.

Thanks for your suggestions.
I got it correct after all.
I used "Set db = CurrentDb" and it worked perfect.

Related

How to execute and query in VBA in MS Access using the ODBC Connector for MySQl?

The following VBA code will allow you to run a sql query in the current access database
I tried this in a MS Access file that is connected to a MySQL database through the ODBC Connector. However this code does not work, presumably because it's not a normal access DB.
How can I query the database using the existing ODBC connection?
EDIT: I always get a "Runtime error 3024 cannot find file"
Try 1
Dim mydb As Database
Dim myrs As DAO.Recordset
Set mydb = CurrentDb
Set myrs = mydb.OpenRecordset("select from blah blah...")
Try 2
Dim dbMine As DAO.Database
Set dbMine = CurrentDb
Dim qr As String
qr = "select count(*) as `result` from floatinp_appdb2.clientes where cliente_email = 'tiagovalente#float-in.pt';"
'debug.print qr
dbMine.Execute qr, dbFailOnError
Requirements are:
Linked table has a PK defined.
So, this should work:
Set myrs = mydb.OpenRecordset("select from blah blah...",dbOpenDynaset, dbSeeChanges)
Also:
any true/false columns (bit fields) should have default value of 0 set. (don't allow nulls for the true/false columns).
You can and should also consider adding a rowversion column, but above should suffice.
Though the error was "runtime error 3024 cannot find file", my mistake was including the database name before the table
e.g. Select * From DB2.Table1

SQL command in ecel VBA gives db server error - MariaDB

I have problem with part of excel VBA macro that should load data from csv file, to MariaDB tables. SQL command, which works in HeidiSQL, return error when used in VBA. The error message is:
[ma-3.0.3][10.2.13-MariaDB]This command is not supported in the prepared statement protocol yet.
Here is the VBA code.
DBConn = "DSN=Fundusze;UID=login;PWD=pass;"
Command = "Load data low_priority local infile '" + Replace(Plik, "\", "/") + "' replace into table _kurs_" + ID + " fields terminated by ';' lines terminated by '\r\n' ignore 0 lines (`Data`, `Notowanie`);"
Call ZapisDB(Command, DBConn)
Sub ZapisDB(SQL_Com As String, Connection As String)
Dim DBConn As ADODB.Connection
Set DBConn = New ADODB.Connection
DBConn.ConnectionString = Connection
DBConn.Open
DBConn.Execute (SQL_Com)
DBConn.Close
Set DBConn = Nothing
End Sub
I am aware that this is rather db server side problem, but what can I do if I need to load lot of data into lot od tables ? Why SQL command which is fine and works in HeidiSQL cannot be send via ODBC ?
EDIT - problem solved by making workaround
I have made a workaround to not use 'load data infile' as it seems that it is not supported by DB engine accessed via ODBC. I'm using 'insert into' query preparing string of values from csv which should be inserted.
I might be going out on a limb here and bet that you will find the problem(s) by adding this line at the very top of this module:
Option Explicit
(and in the future, always adding that to every module.)
This "forces" you to properly declare and refer to variables, objects, properties, etc.
I thinks it's better to use ExecuteNonQuery() as it's for Insert/Delete/Update :
Dim con As MySqlConnection = New MySqlConnection("DataSource=dev;Database=mydb;User ID=myUser;Password=mypass;")
Try
con.Open()
Dim sql As MySqlCommand = New MySqlCommand(Command, con)
sql.ExecuteNonQuery()
Catch ex As Exception
con.Close()
MsgBox("Record is not Inserted" + ex.Message)
End Try
One other thing you need to verify are the / you may have to transform in \

Calling from Access To Stored Procedure that Use Linked Server

I have Access that is used as Front End (UI) for the users, let's call it Acc1.
Acc1, is linked to tables on SQL Server.
From Acc1 I want to call to Stored Procedure, let's call it SP1.
SP1, is a simple select on a table in Linked Server. The Linked Server is an Access DB that has only tables. Let's call this DB Acc2.
Note: In the future SP1 will query more complex query that will use table from the Acc2 and from the SQL Server database. Right now as first step I want to execute this simple select query.
When I do in SP1 a simple Select query on a table from the SQL Server table, and try to cal it from Acc1, that's work.
When I try to query the linked server table in SP1 and try to call it from Acc1 it fails with error:
When I run this SP1 from SQL Server it is working.
Any ideas why it happened? How can I do it?
Following is the code:
The SP1:
ALTER PROC [dbo].[spSpanDates_BMPWorkFlowSpanCounts]
AS
BEGIN
SELECT *
FROM
[Supplemental_Form_master_tables]...[tblBPMWorkflows]
END
The code in Acc1:
Private Sub Button_BPMStartEndDatesALL_Click()
Dim qdf As DAO.QueryDef, rst As DAO.Recordset
Dim FindRecordCount As Long
Set qdf = CurrentDb.CreateQueryDef("")
qdf.Connect = "ODBC;DRIVER={sql server};DATABASE=PLMScheduling; SERVER=USCLES425\INST2; Trusted_Connection=Yes;"
qdf.sql = "EXEC dbo.spSpanDates_BMPWorkFlowSpanCounts"
qdf.ReturnsRecords = True
Set rst = qdf.OpenRecordset(dbOpenSnapshot)
If rst.EOF Then
FindRecordCount = 0
Else
rst.MoveLast
FindRecordCount = rst.RecordCount
End If
rst.Close
Set rst = Nothing
Set qdf = Nothing
End Sub
I'm using SQL Server 2008 and Access 2010.
Thank you very much for the help!
The answer is very simple. When SP1 run from Acc1, SQL Server uses the permissions of Acc1. So when try to query in SP1 tables from Acc2 with the permissions of Acc1 this fail.

Bulk Insert from VBA into SQL Server

I'm using SQL Server 2008 R2 and I've created a User Defined Type:
create type dbo.UDT as table (FirstName varchar(50) null, LastName varchar(50) null)
I've create a stored procedure that has this UDT as a parameter:
create procedure dbo.InsertIntoMyTableUsingUDT (#udt dbo.UDT readonly)
as
begin
set nocount on;
insert into dbo.MyTable (FirstName, LastName)
select FirstName, LastName from #udt;
return;
end
I would like to use VBA's ADO (ADO.COM/OLE DB) to bulk upload 10,000+ records using this stored procedure.
I've tried passing an ADODB.Recordset as a parameter in an ADODB.Command:
<code that creates ADODB.Recordset 'rst' here...>
Dim com as ADODB.Command
Set com = new ADODB.Command
With com
.ActiveConnection = "Provider=SQLOLEDB.1;Data Source=localhost;Initial Catalog=TestDB;Integrated Security=SSPI;"
.CommandText = "dbo.InsertIntoMyTableUsingUDT"
.CommandType = adCmdStoredProc
.Parameters.Refresh
.Parameters(1).Value = rst '<----the ADODB.Recordset created above
.Execute
End With
but I get the runtime error:
Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another.
Checking the parameter's type in the Immediate Window I get:
?com.Parameters(1).Type
143
which I can't see in MSFT's list of OLE DB DataTypeEnums:
http://msdn.microsoft.com/en-gb/library/windows/desktop/ms675318(v=vs.85).aspx
So I tried passing in a 2-dimensional array instead of the ADODB.Recordset but then I got the error:
Bad variable type.
Both attempts failed and it's got me stumped.
I know it can be done in VB.NET using ADO.NET and the SqlParameterCollection.AddWithValue method.
I would like to know if there is a way of doing it in VBA using ADO.COM. Has anyone done it?
Alternatively, is there a different way of achieving the same thing (bulk upload rather than calling an ADODB.Command 10,000+ times in a loop)?
Cheers

How to obtain value of auto_increment field in Access linked to MySQL?

I'm trying to modify and existing Access application to use MySQL as a database via ODBC with the minimal amount of recoding.
The current code will often insert a new record using DAO then obtain the ID by using LastModified. This doesn't work with MySQL. Instead I'm trying to use the approach using
SELECT * FROM tbl_name WHERE auto_col IS NULL
Suggested for Access in the MySQL documentation. However if I set up a sample table consisting of just an id and text data field and execute this
CurrentDb.Execute ("INSERT INTO tbl_scratch (DATA) VALUES ('X')")
Set rst = CurrentDb.OpenRecordset("SELECT id FROM tbl_scratch WHERE id IS NULL")
myid = rst!id
Id is returned as null. However if I execute
INSERT INTO tbl_scratch (DATA) VALUES ('X');
SELECT id FROM tbl_scratch WHERE id IS NULL;
using a direct MySQL editor then id is returned correctly, so my database and approach is fine but my implementation inside Access must be incorrect. Frustratingly the MySQL documentation gives the SQL statement to retrieve the id as an example that works in Access (as it states LAST_INSERT_ID() doesn't) but gives no further details.
How might I fix this?
Solved (and blogged) as below
I've been implementing an upgrade for a set of Access databases to replace the Access file database with MySQL linked by ODBC. Everything seems to be going remarkably smoothly except for the common concept of inserting a record into a table with an auto-increment id column and retrieving the value of the id just created. Of course on PHP or the like one would just use the
SELECT LAST_INSERT_ID()
Function to retrieve the ID. However the MySQL documentation itself says that this doesn't work for certain ODBC applications such as Delphi or Access and suggests using
SELECT * FROM tbl WHERE auto IS NULL;
Unfortunately this simply didn't work for me when called from inside the Access application I was working with, and there seems to be several comments around the web that indeed this is unreliable as Access may drop the data connection and reconnect behind the scenes - thus invalidating the call.
As an alternative I decided to use a MySQL function to add a blank record to the table, returning the id which Access would then use to update the record (which fits well with the code-style of the existing application). Unfortunately this apparently straightforward work-around fails to be simple either as long-standing bugs in MySQL make finding valid code that can both send and return a variable something of a challenge. Several examples on the web will work within the limited domain of using either just IN or OUT variables but fail to work with both.
My final solution, which works on the MySQL 5.1 and Access 2003 combination I am deploying, is as follows
MySQL procedure
DELIMITER $$
CREATE
PROCEDURE `alicedata`.`sp_ins_identity`(IN tablename VARCHAR(50))
BEGIN
SET #result = 0;
SET #sqlproc = CONCAT("INSERT INTO ",tablename," () VALUES ();");
PREPARE s1 FROM #sqlproc;
EXECUTE s1;
DEALLOCATE PREPARE s1;
SELECT LAST_INSERT_ID();
END$$
This procedure is useful in that it will insert a row and return the id for any table where a row contains all null fields or non-null fields with defaults defined. To call this I use the following function:
Public Function InsertMySQLIdentityRow(DSN As String, Tablename As String) As Integer
On Error GoTo Err_InsertMySQLIdentity
Dim cnnSQL As New ADODB.Connection
Dim cmdSQL As ADODB.Command
Dim pid As Integer
Dim rs
Dim strSQL As String
' initialize
pid = 0
' set up ADO connection
Set cnnSQL = New ADODB.Connection
cnnSQL.Open DSN
' execute the procedure - note that assembling by parameter fails to handle IN or OUT correctly
Set cmdSQL = New ADODB.Command
cmdSQL.ActiveConnection = cnnSQL
strSQL = "call sp_ins_identity('" & Tablename & "');"
Set rs = CreateObject("ADODB.Recordset")
Set rs = cnnSQL.Execute(strSQL)
If Not rs.EOF Then
pid = rs(0)
End If
' clean up
Set rs = Nothing
Set cmdSQL = Nothing
cnnSQL.Close
Set cnnSQL = Nothing
Exit_InsertMySQLIdentity:
InsertMySQLIdentityRow = pid
Exit Function
Err_InsertMySQLIdentity:
MsgBox Err.Number & Err.Description
Resume Exit_InsertMySQLIdentity
End Function
This code is somewhat unusual in that normally, on MSSQL, you would use a parametrized procedure call, but due to bugs in the MySQL ODBC (or at least incompatibilities with Access) the above seems to be the only way that allows both data to be passed and returned.