Getting the newly added AutoID of MySQL using VBA in MS Access - mysql

I have a MS Access app with a MySQL database. I have tried numerous ways from Stack Overflow but can't get the primary key of a newly added row.
I have tried everything I can find with no luck.
Set pxRST = db.OpenRecordset("SELECT * from tblPatients WHERE dispenseID = " & oPxID & " AND ChemistID = " & chemID, dbOpenDynaset, dbSeeChanges)
if pxrst.eof then
pxRST.AddNew
pxRST("dispenseid") = oPxID
pxRST("chemistID") = chemID
pxRST("firstname") = firstName
pxRST("lastname") = lastName
pxRST("address") = Address
pxRST("postcode") = postcode
pxRST("phonenumber") = phonenumber
pxRST.Update
pxRST.Bookmark = pxRST.LastModified
gPxID = pxRST!PatientID
Debug.Print gPxID
end if
This gave a "record is deleted" error
I have also tried using one that had
gPxID = currentdb.openrecordset("SELECT ##identity").value(0)
This just game me 0 as a figure
I did go into MYSQL workbench and try
INSERT INTO tblpatients
SELECT ##IDENTITY
and I did get a new record's ID.
So I've tried hard and got so far but I just can't figure it out from here and how to get this working in VBA.
I'm currently working on using QueryDefs, but I'm very new to this and haven't really got there I don't think.
Dim qdf2 As DAO.QueryDef
strSQL = "INSERT INTO tblPatients (dispenseid,chemistID,firstname,lastname,address,postcode,phonenumber) " & _
"VALUES (" & oPxID & "," & chemID & ",'" & firstName & "','" & lastName & "','" & Address & "','" & postcode & "','" & phonenumber & "' )"
Set qdf2 = db.QueryDefs("quGetPxDetails")
With qdf2
.SQL = strSQL
.Connect = oCon
qdf2.Execute
End With

It rather depend upon whether your tblPatients has an auto increment primary key or not.
If it does then you should not be assigning it a value manually, ie your
INSERT INTO tblPatients (dispenseid,chemistID,firstname,lastname,address,postcode,phonenumber) " & _
"VALUES (" & oPxID & "," & chemID & ",'" & firstName & "','" & lastName & "','" & Address & "','" & postcode & "','" & phonenumber & "' )"
is not inserting anything into the PK.
Lets assume that you do have a column in tblPatients called
PatientID of type int(11) NOT NULL AUTO_INCREMENT,
Now, after you insert a new record you can get back the id of that inserted record using the function
LAST_INSERT_ID()
so
Select LAST_INSERT_ID() as my_last_pk;
would return the PK of the record you just inserted in a column called my_last_pk.
Note that this is session specific so if you and someone else both insert a new record at more or less the same time you would each get back your own inserted PK.

So my answer comes from both ComputerVersteher and User2834566 info.
I had to run two queries, both as passthrough and running on the same db instance to make sure it returned the right value:
Dim strSQL As String
Dim qdf As DAO.QueryDef
Dim db As DAO.Database
Dim rst As DAO.Recordset
strSQL = "INSERT INTO medstome_masterdb.tblChemists (chemName) VALUES ('newchem')"
strGETID = "SELECT ##IDENTITY"
Set db = CurrentDb
With db
Set qdf = db.CreateQueryDef("")
With qdf
.ReturnsRecords = False
.Connect = oCon
.SQL = strSQL
.Execute
End With
With qdf
.ReturnsRecords = True
.Connect = oCon
.SQL = strGETID
Set rst = .OpenRecordset(dbOpenSnapshot)
gPxID = rst(0)
Debug.Print gPxID
End With
End With
This works perfectly!
Thanks to the guys responding and helping

Related

How to get bigdata from one table and insert into another in VBA?

I have table with columns like key,English Phrase and that phrase with other 40 languages.See in following image :
I want to break the records of these table by it's language column like following image:
I did this using the following code:
Sub InsertIntoMasterPhrases()
Dim objRecordsetMaster As ADODB.Recordset
Set objRecordsetMaster = New ADODB.Recordset
Dim objRecordset As ADODB.Recordset
Set objRecordset = New ADODB.Recordset
objRecordsetMaster.ActiveConnection = CurrentProject.Connection
objRecordset.ActiveConnection = CurrentProject.Connection
objRecordsetMaster.Open ("SELECT [Master Table].* FROM [Master Table];")
While objRecordsetMaster.EOF = False
objRecordset.Open ("Select [SAP_LANGUAGE to LANG].[LANGUAGE NAME], [SAP_LANGUAGE to LANG].[LANGUAGE] " & _
"From [SAP_LANGUAGE to LANG]")
While objRecordset.EOF = False
key = objRecordsetMaster.Fields("Key").Value
englishPhrase = objRecordsetMaster.Fields("English Phrase").Value
language = objRecordset.Fields("LANGUAGE").Value
translation = objRecordsetMaster.Fields(languageName).Value
If (GetRecordsExist(CStr(key), CStr(englishPhrase), CStr(language)) = "") Then
Query = "INSERT INTO [Language Sample](Key,English,Translation,Language)VALUES ('" & key & "','" & englishPhrase & "','" & translation & "','" & language & "');"
CurrentDb.Execute Query
End If
objRecordset.MoveNext
Wend
objRecordset.Close
objRecordsetMaster.MoveNext
Wend
objRecordsetMaster.Close
End Sub
//Checking records already exist in table
Function GetRecordsExist(key As String, english As String, language As String) As String
Dim db As Database
Dim Lrs As DAO.Recordset
Dim LGST As String
Set db = CurrentDb()
Set Lrs = db.OpenRecordset("SELECT KEY FROM [Language Sample] where KEY='" & key & "' and English='" & english & "' and Language = '" & language & "'")
If Lrs.EOF = False Then
LGST = "Found"
Else
LGST = ""
End If
Lrs.Close
Set Lrs = Nothing
GetRecordsExist = LGST
End Function
In the Master table i have 15000 records and when its breaking 15000 records it becomes 15000 * 40 = 600000. above code inserting almost 10000 records per minutes and after few hour it' hangs up . But also it don't produce any error then i have to restart the access. Kindly help how can i do it in better way.
Alternative 1:
Use a large UNION query to append many records with one SQL statement, as described here:
How to simulate UNPIVOT in Access 2010?
You will probably want to split it into several chunks (e.g. 5 or 10 languages at a time), or Access might choke on the query.
Alternative 2:
Instead of running INSERT statements for each record, use a DAO recordset with .AddNew. This is faster by magnitudes, see this answer:
https://stackoverflow.com/a/33025620/3820271

Query Returns Multiple Rows Instead of the max

I have a table in Access with the relevant fields EFTRecID, EFTRecIDNum and CreatedBy. EFTRecIDNum is an auto number field, and EFTRecID concatenates the required format of "CE" & EFTRedIDNum. I am attempting to return the highest value in the EFTRecID field that was created by the current user. To do this I am trying to do a sub query that finds the Max(EFTRecIDNum) WHERE Created = my name. However instead of returning the max, it is returning all values with my name. I know I could use the format option to just format the EFTRecIDNum field, but I need to be able to search in the format CE456.
TL;DR: Query returns all records with my name, rather then max with my name.
Public Sub DownloadMyRecords()
Dim intI As Integer 'Used for looping in a variety of locations
strSQL = "SELECT EFTRecID FROM tblEFTRec WHERE (SELECT MAX(EFTRecIDNum) FROM tblEFTRec WHERE CreatedBy = '" & Application.UserName & "')"
Set cnn = New ADODB.Connection
With cnn
.Provider = "Microsoft.ACE.OLEDB.12.0;Data Source=" & dbLocation & "\" & dbName & ";Jet OLEDB:Database Password=" & DBPWord
.Open dbLocation & "\" & dbName
End With
Debug.Print strSQL
Set rst = New ADODB.Recordset
rst.CursorLocation = adUseServer
rst.Open Source:=strSQL, ActiveConnection:=cnn, _
CursorType:=adOpenForwardOnly, LockType:=adLockOptimistic, _
Options:=adCmdText
Debug.Print (rst.GetString)
rst.Close
cnn.Close
Set rst = Nothing
Set cnn = Nothing
End Sub
Try this SQL statement instead:
strSQL = "SELECT EFTRecID
FROM tblEFTRec
WHERE EFTRecIDNum = (SELECT MAX(EFTRecIDNum) FROM tblEFTRec WHERE CreatedBy = '" & Application.UserName & "')"
Try using:
"SELECT EFTRecID FROM tblEFTRec
WHERE EFTRecIDNum = (SELECT MAX(EFTRecIDNum) FROM tblEFTRec
WHERE CreatedBy = '" & Application.UserName & "')"
Is there a reason the following doesn't work?
"SELECT MAX(EFTRecID) FROM tblEFTRec
WHERE CreatedBy = '" & Application.UserName & "'"

Update syntax error in the WHERE clause

Generating a Report from Query; capturing data from several tables. The Report has two calculated boxes and I want to UPDATE the data back to one of the tables. Debugging shows I'm capturing the variables but keeps giving me Syntax errors in the WHERE clause. I've tried lots of syntax iterations from scouring the net.
Private Sub Report_Load()
Dim sqls As String
Dim TEP As Single
Dim PPS As Single
Dim RecipeN As String
TEP = Reports![RecipeBuild]![txtTEP]
PPS = Reports![RecipeBuild]![txtPPS]
RecipeN = Reports![RecipeBuild]![RecipeName]
sqls = "Update [tblRecipeBuild] " _
& "Set TEP = " & TEP & " " _
& "Set PPS = " & PPS & " " _
& "WHERE [RecipeName] = '" & RecipeN & "';"
DoCmd.SetWarnings False
DoCmd.RunSQL sqls
DoCmd.SetWarnings True
End Sub
An Access SQL UPDATE should include the SET keyword only once.
When you want to update more than one field, use SET once, and then use a comma between the pairs of FieldName=Value segments.
sqls = "Update [tblRecipeBuild] " _
& "Set TEP = " & TEP & ", PPS = " & PPS & " " _
& "WHERE [RecipeName] = '" & RecipeN & "';"
I think that should work but suggest you consider a parameter query instead of concatenating values into an UPDATE statement.
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim strUpdate As String
strUpdate = "UPDATE tblRecipeBuild SET TEP=pTEP, PPS=pPPS WHERE RecipeName=pRecipeN;"
Debug.Print strUpdate
Set db = CurrentDb
Set qdf = db.CreateQueryDef(vbNullString, strUpdate)
With qdf
.Parameters("pTEP").Value = TEP
.Parameters("pPPS").Value = PPS
.Parameters("pRecipeN").Value = RecipeN
End With
qdf.Execute dbFailOnError

How to locate data source for unbound control?

I've inherited some Access VBA code and there are controls on a form (such as a listbox named lstOrderID, mentioned below) which have no RowSource property set (an empty string). I look in the code and find statements like this in various places:
Forms!frm_Customer.lstOrderID = rstCust!OrderID ' set from a record set
Forms!frm_Customer.lstOrderID.Requery
Me.lstOrderID = Me.lstOrderID.ItemData(0) ' set to first item in self
But nowhere in the code is lstOrderID.RowSource being set.
How can Requery be called on a listbox that has no RowSource?
How can a listbox be set to a single value (rstCust!OrderID) from a record set, unless this is a list of values (although the debugger shows an integer in lstOrderID.Value)?
Here is more code:
Dim rstCust As Recordset
Set db = CurrentDb
Set rstCust = db.OpenRecordset("SELECT * FROM Orders WHERE CustID=" & ID & _
"AND Datetaken =Date() " & _
"AND VendorID='" & Forms!frm_Customer.cboVendorID & "'")
Forms!frm_Customer.lstOrderID = rstCust!OrderID
rstCust.Close
db.Close
Another section:
Dim rstCust As Recordset
Dim blStatus As Boolean
Dim strSql As String
Set db = CurrentDb
strSql = "SELECT Orders.OrderID " & _
"FROM Orders " & _
"WHERE (((Orders.DateTaken)=#" & Date & "#) " & _
"AND ((Orders.VendorID)='" & Forms!frm_Customer.cboVendorID & "') " & _
"AND ((Orders.CustID)=" & ID & "));"
Set rstCust = db.OpenRecordset(strSql)
Forms!frm_Customer.lstOrderID = rstCust!OrderID
Forms!frm_Customer.lstOrderID.Requery
Forms!frm_Customer.lstOrderID = rstCust!OrderID
rstCust.Close
db.Close
Also this:
Me.lstOrderID.Requery
Me.lstOrderID = Me.lstOrderID.ItemData(0)

Adding data from Excel to Mysql via VBA

UPDATED QUESTION...SEE BELOW
I have an excel sheet which accesses a MySQL db as a backend....
I insert new records into MySql the following way, but I am not sure if this is the best way.
For rowline = 1 To 50
strSQL = myquerystring (INSERT 5 columns per excel row)
rs.Open strSQL, oConn, adOpenDynamic, adLockOptimistic
Next rowline
Basically the query string goes through each row in excel sheet (from 1 to 50) and the data on certain cells are added to the sql query and then inserted with rs.Open ....
(each row has some 5 columns which are inserted as a record)
Everything runs well, however I just want to know if there is a faster way (just one INSERT query), inserting all 50 (and 5 columns on each), from row 1 to 50, all at once.
At the moment it is doing 50 individual INSERT queries, so I am trying to reduce that to 1 but I don't know if it is possible.
NEW INFORMATION:
Hi, following your advice and links (thanks!) and some Googling, I ended up with the following code...
It works fine, HOWEVER to INSERT 100 rows it takes approx 15 seconds....this is far too much.
I am hoping I can get some code/ideas on how to Execute the query once, (inserting all 100 rows in one hit).
Please note that I am a beginner on this so if you can stir me into some samples on how it should be done it will be much appreciated.
Public Sub INSERT_to_MySQL()
Dim conn As ADODB.Connection
Dim cmd As ADODB.Command
Dim strSQL As String
app_enable_false
On Error GoTo no_DB_connection_error
resume_after_connecting:
Set cmd = New ADODB.Command
cmd.ActiveConnection = oConn
' LOOP and INSERT the data
' 100 rows take approx 15 seconds to INSERT
For rowcursor= 1 To 100
the_table = "`global`.`filesaved` "
strSQL = "INSERT INTO " & the_table & " (Client_Name, OriginCity, DestinationCity, ValidFrom, ValidTo, Quote_Number, Cost1, Cost2, Cost3) "
strSQL = strSQL & " VALUES ('" & esc(Range("BB" & rowcursor)) & "','" & esc(Range("BC" & rowcursor)) & "','" & esc(Range("BD" & rowcursor)) & "','" & Format(Range("BE" & rowcursor), "yyyy-mm-dd") & "','" & Format(Range("BF" & rowcursor), "yyyy-mm-dd")
strSQL = strSQL & "','" & esc(Range("BH" & rowcursor)) & "','" & esc(Range("BJ" & rowcursor)) & "','" & esc(Range("BK" & rowcursor)) & "','" & esc(Range("BJ" & rowcursor)) & "')"
cmd.CommandText = strSQL
cmd.Execute
Next rowcursor
app_enable_true
Exit Sub
no_DB_connection_error:
ConnectDB
GoTo resume_after_connecting
End Sub
I would move the open command outside the loop, then use the Execute method to do the inserts in the loop. You don't want to do an open on the database every time.
Here's a good page of ADO methods.
Here's a question on Batch Inserting (and Updating).
EDIT: Looking at Remou's link in his comment, I realized that you probably don't even need the open. Just use the Execute method for the Inserts.
Find below a process which works, in case someone else has in future same problem.
Might not be the best solution but 100 records are saved all at once in less than a second, which is what I was after. Also there is only one INSERT query done (instead of 100 different ones for each row.
Thanks to all for your guidance.
Dim conn As ADODB.Connection
Dim cmd As ADODB.Command
Dim rst_recordset As ADODB.Recordset
Dim strSQL As String
Dim strSQL2 as string
On Error GoTo no_DB_connection_error
resume_after_connecting:
Set cmd = New ADODB.Command
cmd.ActiveConnection = oConn
' LOOP and INSERT the data
lastrow = Range("BB65536").End(xlUp).Row
the_table = "`global`.`filesaved` "
strSQL = "INSERT INTO `global`.`filesaved` " & " (Client_Name, OriginCity, DestCity, ValidFrom, ValidTo, Quote_Number, Cost1, Cost2, Cost3) VALUES "
strSQL2 = ""
For excel_row = 1 To lastrow
strSQL2 = strSQL2 & " ('" & cells(excel_row,1) & "','" & cells(excel_row,2) & "','" & cells(excel_row,3) & "','" & cells(excel_row,4) & "','" & cells(excel_row,5) & "','" & cells(excel_row,6) & "','" & cells(excel_row,7) & "','" & cells(excel_row,8) & "','" & cells(excel_row,9) & "') ,"
next excel_row
strSQL = strSQL & strSQL2
Mid(strSQL, Len(strSQL), 1) = ";" ' gets rid of the last comma
cmd.CommandText = strSQL
cmd.Execute
If I run a statement and do not expect a reply back, I usually go for the Command object in VBA.
This code worked for me
Sub insertdata()
Dim year As String
Set rs = CreateObject("ADODB.Recordset")
Database_Name = Range("b3").Value ' Name of database
User_ID = Range("b4").Value 'id user or username
Password = Range("b5").Value 'Password
Server_Name =Range("b2").Value
' Query for fetching Maximum Date
' LOOP and INSERT the data
lastrow = Range("BB65536").End(xlUp).Row
the_table = "`admin`.`test` "
strSQL = "INSERT INTO `drawing`.`test` " & " (tests,test2) VALUES "
strSQL2 = ""
For excel_row = 1 To 100
strSQL2 = strSQL2 & " ('" & Cells(excel_row, 1) & "','" & Cells(excel_row, 2) & "') ,"
Next excel_row
strSQL = strSQL & strSQL2
Mid(strSQL, Len(strSQL), 1) = ";" '
' ADODB connection
Set Cn = CreateObject("ADODB.Connection") 'NEW STATEMENT
Cn.Open "Driver={MySQL ODBC 5.1 Driver};Server=" & Server_Name & ";Database=" & Database_Name & _
";Uid=" & User_ID & ";Pwd=" & Password & ";"
rs.Open strSQL, Cn, adOpenStatic
Dim myArray()
End Sub