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
Related
Picture this, I have a table in excel that is connected to power query that refreshes every minute, Im trying to use vba to export the live table to mysql , whenever the table in excel refreshes , the data also refreshes in the mySQL table, I need it to update the table where anything changes and also decrease rows if they no longer exist in the excel table, whenever the table refresh and update the new values to the SQL table
The code I have here is of a Insert and delete system, which takes time to load about 3 minutes depending on the data in the table, I want to use the UPDATE statement in my code instead of deleting and inserting the whole
is it possible, can someone please reply as an answer with the update statement
How do I Edit That In My Code?
My SQL Table Has
COL 1,
COl 2,
COL 3,
COL 4,
COL 5,
COL 6,
COL 7
As the column Names,same applies to the table in excel, it has 7 columns too
Dim oConn As ADODB.Connection
Dim rs As ADODB.Recordset
'remove dangerous characters
Function esc(txt As String)
esc = Trim(Replace(txt, "'", "\'"))
End Function
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Set rs = New ADODB.Recordset
Set oConn = New ADODB.Connection
oConn.Open "DRIVER={MySQL ODBC 8.0 ANSI Driver};" & _
"SERVER=localhost;" & _
"DATABASE=engine;" & _
"USER=root;" & _
"PASSWORD=;" & _
"Option=3"
Dim del As String
del = "DELETE FROM `feed`"
rs.Open del, oConn ',adOpenDynamic, adLockOptimistic
'number of rows with records. testingupload is the sheetname.
Dim height As Integer
height = Worksheets("Feed").UsedRange.Rows.Count
'insert data into SQL table. testingupload is the sheetname.
With Worksheets("Feed")
Dim rowtable As Integer
Dim strSQL As String
For rowtable = 2 To height
strSQL = "INSERT INTO `feed` (`COL 1`, `COL 2`, `COL 3`, `COL 4`, `COL 5`, `COL 6`, `COL 7`) " & _
"VALUES ('" & esc(Trim(.Cells(rowtable, 1).Value)) & "', '" & _
esc(Trim(.Cells(rowtable, 2).Value)) & "', '" & _
esc(Trim(.Cells(rowtable, 3).Value)) & "', '" & _
esc(Trim(.Cells(rowtable, 4).Value)) & "', '" & _
esc(Trim(.Cells(rowtable, 5).Value)) & "', '" & _
esc(Trim(.Cells(rowtable, 6).Value)) & "', '" & _
esc(Trim(.Cells(rowtable, 7).Value)) & "')"
rs.Open strSQL, oConn ',adOpenDynamic, adLockOptimistic
Next rowtable
End With
End Sub
So, as said in the comments, my understanding is that you would like to copy all the data from the excel table into the MySql Table. As you did not give any hint how to identify a single row by a key I assume that one just can delete the data from the MySql table and then insert all the data from the excel sheet into the MySql table.
Let
Dim cn As ADODB.Connection
' your code to establish the connection
be the connection to the MySql database then you can delete the data quite simple
Dim sSQL As String
sSQL = "DELETE * FROM tbl1"
cn.Execute sSQL
tbl1 is the name of the table in question from the MySql database
After you have deleted the data from the MySql table you just insert all data from the excel table into the MySql table
sSQL = " INSERT INTO tbl1 SELECT * FROM [Excel 12.0;HDR=YES;DATABASE=" _
& ThisWorkbook.FullName & "].[Sheet1$A1:B5]"
cn.Execute sSQL
The tricky part here is left for you as you know in which excel sheet the data is stored and what range it covers. That means you probably have to adjust the sheetname Sheet1 and the range A1:B5. Please do not remove the $ beetween the sheet name and the range. It is needed for the code to work.
As you have seven columns I guess the range will be similar to
" .... [Sheet1$A1:G" & Height & "]"
where height is the number of the rows (see your code above).
Your code might look like that at the end
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Dim Cn As ADODB.Connection
Set cn = New ADODB.Connection
cn.Open "DRIVER={MySQL ODBC 8.0 ANSI Driver};" & _
"SERVER=localhost;" & _
"DATABASE=engine;" & _
"USER=root;" & _
"PASSWORD=;" & _
"Option=3"
'number of rows with records. testingupload is the sheetname.
Dim height As Integer
height = Worksheets("Feed").UsedRange.Rows.Count
Dim sSQL As String
sSQL = "DELETE * FROM tbl1"
cn.Execute sSQL
sSQL = " INSERT INTO tbl1 SELECT * FROM [Excel 12.0;HDR=YES;DATABASE=" _
& ThisWorkbook.FullName & "].[Sheet1$A1:G" & height & "]"
cn.Execute sSQL
cn.Close
End Sub
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
I have a simple macro to insert data from Excel into a MySQL database:
Dim conn As ADODB.Connection
Dim sqlstr As String
Dim rs As ADODB.Recordset
Dim Crow As Long, Lrow As Long
Dim Item As String, Price As Long, weight As Long, category As String
Set conn = New ADODB.Connection
conn.Open "DRIVER={MySQL ODBC 5.1 Driver};" & _
"SERVER=localhost;" & _
"PORT=3306" & _
"DATABASE=spendings;" & _
"USER=root;" & _
"PASSWORD=root;" & _
"Option=3"
Set rs = New ADODB.Recordset
Lrow = Cells(Rows.Count, 1).End(xlUp).Row
For Crow = Lrow To 2 Step -1
Item = Sheets("Sheet1").Range("A" & Crow).Value
Price = Sheets("Sheet1").Range("B" & Crow).Value
weight = Sheets("Sheet1").Range("C" & Crow).Value
category = Sheets("Sheet1").Range("D" & Crow).Value
sqlstr = "INSERT INTO items VALUES('" & Item & "','" & Price & "','" & weight _
& "', (SELECT idCategory FROM category WHERE Name='" & category & "'))"
rs.Open sqlstr, conn, adOpenStatic
Next
I am getting an error on the following line:
rs.Open sqlstr, conn, adOpenStatic
and no idea how to proceed.
As others have suggested, there is definitely a problem with your SQL string. Check out the syntax for the INSERT INTO SELECT statement here. Its often useful to test and debug your SQL strings in a database design tool such as MySQL Workbench before putting them into your code. You could also debug.print(sqlstr) to see what your string is returning e.g:
sqlstr = "INSERT INTO items ('" & Item & "','" & Price & "','" & weight _
& "', (SELECT idCategory FROM category WHERE Name='" & category & "'))"
debug.print(sqlstr)
rs.Open sqlstr, conn, adOpenStatic
I don't know your database structure but I can see some syntax errors in your string. You don't need VALUES before your columns (see above documentation). Also, you're trying insert data into 3 columns:
INSERT INTO items VALUES('" & Item & "','" & Price & "','" & weight _ & "')
but your SELECT query is only returning 1 column:
SELECT idCategory FROM category WHERE Name='" & category & "'.
Posting the debug.print output might help with further debugging.
Query was wrong. Thank you. Fixed it to
sqlstr = "INSERT INTO items (Name, Price, weight, store_Id, category_Id) VALUES('" & Item & "','" & Price & "','" & weight_
& "', (SELECT idCategory FROM category WHERE Name='" & category & "'),'" & store & "');"
Copied into workbench and it works:
mysql
But I am still getting the same error: run time error -2147217887(80040e21)
hello I have a userform in excel which is connected to mysql server.
everything works except when I leave the textbox for date empty, I get an error that the value for date is incorrect
on further research I found that the textbox return zero length string when empty and mysql allows only null.
Is there anyway to set the textbox as null when I click on the save button.
Heres my attempt at a solution, hopefully this will help.
Basically its a quick check to see if the textbox in question is empty, and if so, then make it null:
If textbox1.value = "" then
textbox1.value = null
end if
Finally a solution, but this will be a pain in the b, if you have 20 date columns. Unfortunately I have 20 date columns..:(
This is the code which for me, hope this helps someone in the future
Private Sub CommandButton1_Click()
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
strCon = "Driver={MySQL ODBC 5.3 Unicode Driver};Server=localhost;Database=sample;" _
& "User=root;Password=Password;Option=3;"
cn.Open strCon
If txt5.Value = "" Then
SQLStr = "insert into sample.details (ID,Name,Age,Gender,Date_of_Birth) values ('" & txt1.Value & "', '" & txt2.Value & "','" & txt3.Value & "','" & txt4.Value & "',Null);"
cn.Execute SQLStr
Else
SQLStr = "insert into sample.details (ID,Name,Age,Gender,Date_of_Birth) values ('" & txt1.Value & "', '" & txt2.Value & "','" & txt3.Value & "','" & txt4.Value & "','" & Format(txt5.Value, "yyyy-mm-dd") & "');"
cn.Execute SQLStr
End If
End Sub
In an event of a Form I write some code to select value from a table and insert it into another table. This is my code:
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("SELECT std_crs_absence.std_name, std_crs_absence.stg_number, std_crs_absence.crs_name, Sum(std_crs_absence.absence_time) AS SumOfabsence_time, Sum(std_crs_absence.molat) AS SumOfmolat " & _
"FROM std_crs_absence GROUP BY std_crs_absence.std_name, std_crs_absence.stg_number, std_crs_absence.crs_name ", dbOpenDynaset)
rs.MoveFirst
Do Until rs.EOF
sqlinsert = "INSERT INTO abs_summary ([std_name],[stg_number],[crs_name],[SumOfabsence_time],[SumOfmolat])" & _
" VALUES ('" & rs("std_name") & "','" & rs("stg_number") & "','" & rs("crs_name") & "'," & rs("absence_time") & "," & rs("molat") & ")"
DoCmd.RunSQL (sqlinsert)
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
When the event is executed it gives me an error that says "Item not found in this collection". What am I doing wrong?
When you first SELECT the data you retrieve the sums as SumOfabsence_time and SumOfmolat, but for the INSERT you try to use rs("absence_time") and rs("molat"). Those columns don't exist in the Recordset so you get the error. You'll need to use rs("SumOfabsence_time") and rs("SumOfmolat") instead.
(Obligatory comment: You really should be using a parameterized query instead of dynamic SQL.)