Using Insert Command to Upsert to MySQL DB - mysql

I'm creating an update Sub class in VB and use the insert instead of Update in Query because i want to update a multiple data in one run.
this is my references in multiple update data: SQL - Update multiple records in one query
but when I run it there is an error message.
"Missing semicolon (;) at end of SQL statement."
but in the end of my Query there is a Semicolon.
Here is my Query:
Insert into IngredientStock(IngredientID,CategoryId,UnitID,IngredientName,Price)
values(46,2,1,'Beans', 100) ON DUPLICATE KEY
UPDATE
ingredientID= Values(IngredientID),
CategoryID = Values(CategoryID),
UnitID = Values(UnitID),
IngredientName = Values(IngredientName),
Price = values(Price);
Here is my update Sub class
Sub UpdateInfo(ByVal table As String, ByVal PrimaryKey As String, ByVal C1 As String, ByVal C2 As String, ByVal C3 As String, ByVal C4 As String, ByVal Datas As String)
con.Close()
con.Open()
Query = "Insert into " & table & "(" & PrimaryKey & "," & C1 & "," & C2 & "," & C3 & "," & C4 & ") values (" & Datas & ") ON DUPLICATE KEY UPDATE " & PrimaryKey & "= Values(" & PrimaryKey & "), " & C1 & " = values(" & C1 & ")," & C2 & " = values(" & C2 & "), " & C3 & " = values(" & C3 & ")," & C4 & " = values(" & C4 & ");"
cmd = New OleDbCommand(Query, con)
DR = cmd.ExecuteScalar
con.Close()
End Sub

First, never ever concat strings to create a SQL query. If something like the ingredient contains special characters (e.g. Palmer's Condensed Milk) it will fail.
SQL Parameters also preserve the data type - according to the one snippet, only one item is string, but the code is forcing them all to text. Additionally (and most importantly) SQL Parameters avoid SQL injection.
You need something like this for a MySQL Upsert:
Dim sql = <sql>
INSERT INTO SampleZ
(Id, Name, Country, Animal, Color, Price, ItemDate, Active)
VALUES
(#id, #n, #c, #a, #clr, #p, #dt, #act)
ON DUPLICATE KEY UPDATE
Name=#n, Country=#c,
Animal=#a, Color=#clr, Price=#p,
ItemDate=#dt, Active=#act
WHERE id = #id
</sql>.Value
Using dbcon As New MySqlConnection(connStr)
Using cmd As New MySqlCommand(sql, dbcon)
cmd.Parameters.Add("#id", MySqlDbType.Int32).Value = thisID
If thisID = -1 Then
cmd.Parameters("#id").Value = DBNull.Value
End If
cmd.Parameters.Add("#n", MySqlDbType.String).Value = TextBox1.Text
cmd.Parameters.Add("#c", MySqlDbType.String).Value = ComboBox1.Text
cmd.Parameters.Add("#a", MySqlDbType.String).Value = TextBox2.Text
cmd.Parameters.Add("#clr", MySqlDbType.String).Value = TextBox3.Text
cmd.Parameters.Add("#p", MySqlDbType.Decimal).Value = NumericUpDown1.Value
cmd.Parameters.Add("#dt", MySqlDbType.DateTime).Value = DateTimePicker1.Value
cmd.Parameters.Add("#act", MySqlDbType.Bit).Value = chkActive.Checked
dbcon.Open()
Dim rows = cmd.ExecuteNonQuery()
End Using
End Using
Important Notes:
The above uses an XML literal so the query can be formatted to make sense
Each value is a Parameter with the datatype specified (MySqlDbType.DateTime
The Using blocks assure that the DbCOnnection and DbCommand object are properly closed and disposed at the end so the app doesnt leak resources
The UPDATE portion gets the data by assigning the same parameters.
MySql ON DUPLICATE KEY UPDATE Syntax

ingredientID= Values () <-- here
values clause is not required.
Liink --> On Duplicate Key Update same as insert

Related

Updating Integer value in Mysql/VB.Net

SQL = "UPDATE `tblitems` SET `itemsOnHand` = `itemsOnHand` - '" & PartnumItemsNumericUpDown.Value & "' WHERE `itemID` = '" & itemIDTextBoxX.Text & "' ;"
SQL = "UPDATE `tblitems` SET `itemsOnHand` = `itemsOnHand` + '" & PartnumItemsNumericUpDown.Value & "' WHERE `itemID` = '" & itemIDTextBoxX.Text & "' ;"
--- Just want to ask why the first sub function sql command (-) works but (+) wont...please help. itemsOnHand is integer type.
Please DO NOT concatenate strings to build sql command text. ALWAYS use Parameters it avoid sql injection. Parameter values are not executable code but a simple concatenation can hold "Delete * From tblitems."
I had to guess at the datatypes for the parameters.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim ItemId As Integer
If Not Integer.TryParse(itemIDTextBoxX.Text, ItemId) Then
MessageBox.Show("Please enter a number in Item Id.")
Return
End If
Dim Sql = "UPDATE `tblitems` SET `itemsOnHand` = `itemsOnHand` - #PartNumber WHERE `itemID` = #ItemID"
Using con As New MySqlConnection(ConStr),
cmd As New MySqlCommand(Sql, con)
cmd.Parameters.Add("#PartNumber", MySqlDbType.Int32).Value = PartnumItemsNumericUpDown.Value
cmd.Parameters.Add("#ItemID", MySqlDbType.Int32).Value = ItemID
con.Open()
cmd.ExecuteNonQuery()
End Using
End Sub
You are much less likely to run into problems with + and - using parameters since you don't need all the single quotes and double quotes.
The minus sign was interpreted as an arithmetic operator and the plus sign was interpreted as a concatenation character.

Microsoft Access VBA INSERT SQL statement

I have created a database within Microsoft access and with it a form.
I have a button attached to the form and when it's clicked I want to insert a new record into the table customerHeader.
There are four fields within that table one being an autonumber. In my SQL statement, I don't include the orderNumber since it is an autofield.
When I try to click the button and the on click event is executed, I get an error saying that Microsoft Access cannot append the records in the append query.
Any ideas, I have looked everywhere and I have not been able to find the solution.
Private Sub addOrder_Click()
Dim mySql As String
Dim rowNum As Integer
Dim recCount As Long
Dim orderNumber As Long
Dim myBool As Boolean
Dim todayDate As Date
todayDate = CDate(Date)
myBool = False
MsgBox todayDate
rowNum = Form.CurrentRecord
rowNum = CInt(rowNum - 1)
'DoCmd.GoToRecord , , acNewRec
mySql = "INSERT INTO orderHeader (orderDate,custNumber,printed) VALUES (" & todayDate & "," & rowNum & "," & myBool & ")"
DoCmd.RunSQL mySql
Me!orderNum.Requery
You don't have to much around - just use the ISO sequence for the format of the string expression for the date value:
mySql = "INSERT INTO orderHeader (orderDate,custNumber,printed) VALUES (#" & Format(todayDate, "yyyy\/mm\/dd") & "#," & rowNum & "," & myBool & ")"
However, it it's today, simply use:
mySql = "INSERT INTO orderHeader (orderDate,custNumber,printed) VALUES (Date()," & rowNum & "," & myBool & ")"

parsing database columns and values to MySQL statement in module

I'm trying to create a dynamic MySQL INSERT INTO...WHERE NOT EXIST statement by parsing the table name, array of columns, array of values and conditional column and value to a subroutine in a separate module but i keep hitting the Column count doesn't match value count at row 1 error. Below is the code:
Sub InsertRecord(ByVal tbl As String, ByVal cols() As String, ByVal params() As String, _
ByVal colCondition As String, ByVal paramCondition As String) 'As String
'Create new string of columns
Dim myCols As String = ""
For Each col As String In cols
myCols &= col & ", "
Next
Dim newCols As String = myCols.Remove(myCols.Count - 2, 2)
MsgBox(newCols)
Dim scols As String = newCols.Insert(0, "`").Replace(", ", "`, `") & "`"
MsgBox(scols)
'Create new string of parameters
Dim myParams As String = ""
For Each param In params
myParams &= param & ", "
Next
Dim newParams As String = myParams.Remove(myParams.Count - 2, 2)
MsgBox(newParams)
Dim sparams As String = newParams.Insert(0, "'").Replace(", ", "', '") & "'"
MsgBox(sparams)
'End
Dim p As String = paramCondition.Insert(0, "'") & "'"
'Try
'Dim insRemarks As String = "done"
con = New MySqlConnection("Server=localhost; Database=etms; Uid=root; Pwd=;")
comA = New MySqlCommand
'INSERT NEW RECORD.
'THIS GIVES THE ERROR
comA.CommandText = "INSERT INTO " & tbl & " (" & scols & ") SELECT * FROM (SELECT #params) AS tmp "
comA.CommandText &= "WHERE NOT EXISTS (SELECT " & colCondition & " FROM " & tbl & " WHERE " & colCondition & " = #param) limit 1"
comA.Parameters.AddWithValue("#param", p)
comA.Parameters.AddWithValue("#params", sparams)
'THIS STATIC CODE WORKS FINE.
'comA.CommandText = "INSERT INTO state (`st_state`, `ctry_Id`) SELECT * FROM (SELECT 'a', '1') AS tmp "
'comA.CommandText &= "WHERE NOT EXISTS (SELECT st_state FROM state WHERE st_state = 'a') limit 1"
comA.Connection = con
con.Open()
comA.ExecuteNonQuery()
con.Close()
'Release used up components
comA.Parameters.Clear()
comA.Dispose()
comA = Nothing
con = Nothing
MsgBox("done.")
'Return insRemarks
'Catch ex As Exception
'MsgBox(ex.Message.ToString & vbCrLf & vbCrLf & comA.CommandText.ToString)
'Return "Error"
'End Try
End Sub
As seen, i tried a lot of permutations (introducing inverted quotation marks) to no avail.
I'll be glad if someone could help out.

Importing data from excel to mysql database using vba

I´m trying to import data into a MySQL Database, i have searched for many examples and solutions but it didn´t working and i have no idea why. Below is my vba code. I am getting runtime error 2147217900(80040e14) saying that you have an error in your sql syntax; chek the manual that corrsponds to your mysqlfor the right syntax to use near '='41282'
Sub Getdata()
Dim conn As New ADODB.Connection
Dim server_name As String
Dim database_name As String
Dim user_id As String
Dim password As String
Dim a As Long ' counter
Dim i As Long, j As Variant, k As Long
Dim sqlstr As String ' SQL to perform various actions
Dim table1 As String, table2 As String
Dim field1 As String, field2 As String
Dim field3 As String
Dim rs As ADODB.Recordset
sqlstr = "INSERT INTO" & table1 & "SET" _
& field1 & " = '" & i & "', " _
& field2 & " = '" & j & "', " _
& field3 & " = '" & k & "'"
conn.Execute sqlstr
Next a
End With
skipwrite:
End Sub
Simply, space out the table name and SET command in the concatenated string. Also, add tick marks before and after due to the reserved words used in column names (which by the way should be avoided as best practices):
sqlstr = "INSERT INTO " & table1 & " SET " _
& "`" & field1 & "` = '" & Format(i, "YYYY-MM-DD") & "', " _
& "`" & field2 & "` = '" & j & "', " _
& "`" & field3 & "` = '" & k & "';"
Also as mentioned by #Lelio, format the date to read properly into a MySQL Date column.
Date in Excel are stored as number of days between 1899-12-31 and the actual date. What you are trying to do is to store a number in a field that has a numeric format.
41282 is the number of days. So you should calculate something like:
'1899-12-31' + 'i days'
to get the date in mysql format (that by default is YYYY-MM-DD). I don't know the exact string manipulation command for VBA to get this but on the MYSQL side this should fix your error

Select / Insert using dates and union-vb

I am trying to use a single SQL command to do two selects I want to select related data and insert it in another table from another database, but it isn't working, I am new to this, can someone help me? Thanks in advance.
Try
If CreateAccessDatabase("C:\Users\Utilizador.Utilizador-PC\Documents\Visual Studio 2013\Projects\WindowsApplication1\WindowsApplication1\Doc_Vendas_Cab.mdb") = True Then
MsgBox("Database Created")
Else
MsgBox("Database Creation Failed")
End If
Dim Sql As String = "Select strCodSeccao,strAbrevTpDoc,strCodExercicio,intNumero " & _
"From Mov_Venda_Cab where dtmdata between #d1 and #d2; Union" & _
"Select Mov_Venda_Lin.Strcodartigo" & _
"from Mov_Venda_Lin,Mov_Venda_Cab where Mov_Venda_Cab.intnumero=Mov_Venda_Lin.intnumero;"
Dim data1, data2 As DateTime
data1 = DateTime.Parse(txtData1.Text)
data2 = DateTime.Parse(txtData2.Text)
data2 = data2.AddMinutes(0)
data2 = data2.AddHours(0)
data2 = data2.AddSeconds(0)
data1 = data1.AddMinutes(0)
data1 = data1.AddHours(0)
data1 = data1.AddSeconds(0)
Dim x As Integer = 0
Dim temp1, temp2, temp3, temp4, temp5 As String
Using con = New SqlConnection("Data Source=" & txtserv.Text & ";" & "Initial Catalog=" & txtBD.Text & ";" & "User ID=" & txtuser.Text & ";" & "Password=" & txtPass.Text & "")
Using cmd = New SqlCommand(Sql, con)
con.Open()
cmd.Parameters.AddWithValue("#d1", data1)
cmd.Parameters.AddWithValue("#d2", data2)
Using reader = cmd.ExecuteReader()
While reader.Read()
Dim strCodSeccao = reader("strCodSeccao").ToString()
temp1 = reader.Item(x)
temp2 = reader.Item(x + 1)
temp3 = reader.Item(x + 2)
temp4 = reader.Item(x + 3)
temp5 = reader.Item(x + 4)
Dim Con2 As New OleDb.OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\Utilizador.Utilizador-PC\Documents\Visual Studio 2013\Projects\WindowsApplication1\WindowsApplication1\Doc_Vendas_Cab.mdb;Persist Security Info=True")
Con2.Open()
Dim Ole2 As String = "Insert into Mov_Venda_Cab values('" & temp1 & "','" & temp2 & "','" & temp3 & "','" & temp4 & "','" & temp5 & "');"
Dim OledbCom2 As New OleDb.OleDbCommand(Ole2, Con2)
Try
OledbCom2.ExecuteNonQuery()
Catch Ex As Exception
MsgBox(Ex)
End Try
Con2.Close()
End While
End Using
End Using
End Using
Catch Ex As Exception
MsgBox(Ex)
End Try
Your INSERT statement encloses all the values in single quotes. This will only work if the corresponding columns are all text columns (varchar, nvarchar etc.). Use command parameters instead:
Dim Ole2 As String = "Insert into Mov_Venda_Cab values(#p1, #p2, #p3, #p4, #p5);"
Dim OledbCom2 As New OleDb.OleDbCommand(Ole2, Con2)
OledbCom2.Parameters.AddWithValue("#p1", temp1)
OledbCom2.Parameters.AddWithValue("#p2", temp2)
OledbCom2.Parameters.AddWithValue("#p3", temp3)
OledbCom2.Parameters.AddWithValue("#p4", temp4)
OledbCom2.Parameters.AddWithValue("#p5", temp5)
This will work for any column type.
Also your SELECT statement lists only four columns, but you are accessing five columns in the reader.
SELECT strCodSeccao, strAbrevTpDoc, strCodExercicio, intNumero FROM ...
Other things in your code are strange as well. Your are defining two connections that are never used later.
You are adding zero hours, minutes and seconds to a date (this will not change the date). If you want the date part of the date without the time part, use the Date property instead, which returns the date component of the DateTime structure:
data1 = DateTime.Parse(txtData1.Text).Date
You are using a variable x for constant values.
You are opening and closing Con2 in the While-loop. Open it before the loop and close it after the loop. (You can do it with a Using-statement as for the other connection.)