I am trying to create a simple ticketing software for myself with a VB.Net front end and an Access 2003 back end. I have with allowing new rows to be added, but when I try to code the Update row button, it is giving me the error that says Microsoft JET Database Engine - Syntax error in UPDATE statement. I cannot find what the problem is.
Private Sub btnUpdate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnUpdate.Click
Dim da As New OleDbDataAdapter
Dim dt As New DataTable
Dim ConnectString As String = ("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Documents and Settings\aaron-pister\Desktop\New Role Notes\Issue Tracker Express\Issue Tracker Express\Issue Tracker.mdb")
Dim con As New OleDbConnection(ConnectString)
con.Open()
Dim Green42 As String = "UPDATE Issues Basic Details SET [Company Name] = '" & txtClientName.Text & "', [Status] = '" & cbStatus.Text & "', [Company Contact] = '" & txtClientContact.Text & "', [Description] = '" & txtDesc.Text & "', [Notes] = '" & txtRes.Text & "' WHERE [TicketNum] = '" & txtTicket.Text & "'"
'con.Open()
If txtClientName.Text <> "" Then
Try
'MyCom.CommandText = "UPDATE [Issues Basic Details] SET Company Name = '" & txtClientName.Text & "', Status = '" & cbStatus.Text & "', Company Contact = '" & txtClientContact.Text & "', Description = '" & txtDesc.Text & "', Notes = '" & txtRes.Text & "' WHERE TicketNum = '" & txtTicket.Text & "')"
da = New OleDbDataAdapter(Green42.ToString, ConnectString)
da.Fill(dt)
da.Update(EsInfo1, "Issues Basic Details")
MsgBox("Your record has been updated successfully.", MsgBoxStyle.DefaultButton1, "New Ticket Submitted")
Catch ex As Exception
MsgBox(ex.Source & "-" & ex.Message)
con.Close()
Exit Sub
End Try
Else
MsgBox("You must have an entry in the Client Name, Client Contact and Status fields. It is recommended to also have a value in the Description field.", MsgBoxStyle.OkOnly, "Issue Tracker Express")
btnNewIncident_Click(sender, e)
Exit Sub
End If
End Sub
Your table name has to be bracketed too:
Dim Green42 As String = "UPDATE [Issues Basic Details] SET [Company Name]..."
Also, use parameters instead of putting the values into the string. It avoids SQL Injection.
This:
UPDATE Issues Basic Details SET ...
Is not valid SQL. You need to help it by qualifying your table name:
UPDATE [Issues Basic Details] SET ...
A few other suggestions:
Use prepared statements (parameterize your SQL to avoid SQL injection attacks)
Don't define this type of behavior in a click event handler -- have a helper class to do this work so it can be re-used and isn't coupled directly to the UI.
Use Using statements. Your OleDbConnection class implements IDisposable. You aren't properly disposing this connection.
While it's hard to read your code at the moment, it does look like you are trying to do an "AdHoc" query, which can cause a lot of problems.
I'd recommend first changing your statement to a parameterized query to help diagnose issues too.
Related
I am trying to save multiple data to my database with this code:
repNo = MainForm.StaffMixname.Text.Substring(0, 3) & DateTime.Now.ToString("yyyyMMddhhmmss")
MetroGrid5.DataSource = Nothing
Dim ds As DataSet = New DataSet
Dim Query As String = "SELECT ci.seq_id, CONCAT(ci.lastname, ci.firstname) AS fullname, ci.amountApplied, ci.province, co.kind, co.specifications, co.regOwner, co.location FROM clientinformation ci LEFT JOIN collateraloffered co ON ci.seq_id=co.seq_id WHERE co.kind IS NOT NULL AND ci.province = '" & MetroComboBox8.Text & "' AND ci.seq_id BETWEEN '" & convertedstrFrom.ToString("yyMMdd") & "%' AND '" & convertedstrTo.ToString("yyMMdd") & "%'"
Dim fetch As New MySqlDataAdapter(Query, connect)
fetch.Fill(ds, "collateral")
MetroGrid5.DataSource = ds.Tables("collateral")
If MetroGrid5.Rows.Count > 0 Then
Dim cm As New MySqlCommand
With cm
.Connection = connect
For i As Integer = 0 To MetroGrid5.RowCount - 1
.CommandText = _
"INSERT INTO collateralrpt Values('" & repNo & _
"', '" & MetroGrid5.Rows(i).Cells("seq_id").Value & _
"', '" & MetroGrid5.Rows(i).Cells("fullname").Value & _
"', '" & MetroGrid5.Rows(i).Cells("amountApplied").Value & _
"', '" & MetroGrid5.Rows(i).Cells("kind").Value & _
"', '" & MetroGrid5.Rows(i).Cells("specifications").Value & _
"', '" & MetroGrid5.Rows(i).Cells("regOwner").Value & _
"', '" & MetroGrid5.Rows(i).Cells("location").Value & _
"', '" & MetroGrid5.Rows(i).Cells("province").Value & "')"
.ExecuteNonQuery()
Next
End With
cm.Dispose()
cm = Nothing
With connect
.Close()
.Dispose()
End With
Else
MsgBox("No Data!")
End If
but unfortunately It shows MySqlException Column count doesn't match value count at row 1.
Is there any mistake with the code above? thanks in advance.
If you want to retrieve data from one table(s) and insert into another, just use a single data adapter. You can even do so if the tables are in a different database - you just need a different connection for the SelectCommand and InsertCommand. Only a single connection is required for a single database though. E.g.
Dim selectSql = "SELECT Column1A, Column1B FROM Table1"
Dim insertSql = "INSERT INTO Table2
(
Column2A,
Column2B
)
VALUES
(
#Column2A,
#Column2B
)"
Using connection As New MySqlConnection("connection string here"),
insertCommand As New MySqlCommand(insertSql, connection),
adapter As New MySqlDataAdapter(selectSql, connection) With {.InsertCommand = insertCommand, .AcceptChangesDuringFill = False}
With insertCommand.Parameters
.Add("#Column2A", MySqlDbType.Int, 0, "Column1A")
.Add("#Column2B", MySqlDbType.VarChar, 50, "Column1B")
End With
Dim table As New DataTable
connection.Open()
adapter.Fill(table)
adapter.Update(table)
End Using
There are a few things to note here.
I wrote the SQL code using a single, multiline literal. That is far
more readable that concatenating every line.
I used parameters. That prevents numerous issues that have been
written about ad nauseum so I won't go into it here.
There's no grid control involved here. You can add one and bind the DataTable after calling Fill but that is only so you can see the data. It has nothing to do with the actual code of retrieving and saving.
The connection is opened explicitly. You can normally let a Fill or Update call open and close the connection implicitly but, in this case, we want to perform both operations and closing and reopening the connection in between is an unnecessary overhead.
The disposable objects are created with a Using statement, which means they will be implicitly disposed at the end of the block. That inclides closing the connection.
The AcceptChangesDuringFill property of the data adapter is set to True so that all RowStates are left as Added so that all DataRows are ready to be inserted.
I am trying to do a simple update to an Access 2016 database. I am using Visual Studio/VB.net. I have been able to do this already on a different form with no issues using the same type of coding (it's pretty basic, it was for a school project but not anymore). I have tried two different ways to do this...using the update table adapter, for example:
MediatorsListTableAdapter.UpdateMediators(MediatorIDTextBox.Text, MediatorNameTextBox.Text, MaskedTextBox1.Text, MaskedTextBox2.Text, DateTimePicker1.Value,
AvailabilityTextBox.Text, EmailTextBox.Text)
Using that method I always get a notImplemented exception thrown even though I have used a similar type of adapter elsewhere. Also I tried using a strung method (I know, not ideal):
saveInfo = "UPDATE mediatorsList(mediatorName, email, mediatorPrimaryPhone, mediatorSecondaryPhone, lastMediationDate, availability)
VALUES('" & MediatorNameTextBox.Text & "','" & EmailTextBox.Text & "','" & MaskedTextBox1.Text & "','" & MaskedTextBox2.Text & "',
'" & DateTimePicker1.Value & "','" & AvailabilityTextBox.Text & "', WHERE mediatorID = '" & MediatorIDTextBox.Text & "') "
But this method gives me the error of Syntax Error in UPDATE statement. Again I have used this method elsewhere with no problems. Below I will post all the code for this form.
Imports System.Data
Imports System.Data.Odbc ' Import ODBC class
Imports System.Data.OleDb
Imports System.Data.SqlClient
Public Class editMediators
Dim NewData As Boolean
Dim objConnection As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\ECRDatabase.accdb")
' create functions for save or update
Private Sub runAccessSQL(ByVal sql As String)
Dim cmd As New OleDbCommand
connect() ' open our connection
Try
cmd.Connection = conn
cmd.CommandType = CommandType.Text
cmd.CommandText = sql
cmd.ExecuteNonQuery()
cmd.Dispose()
conn.Close()
MsgBox("Data Has Been Saved !", vbInformation)
Catch ex As Exception
MsgBox("Error when saving data: " & ex.Message)
End Try
End Sub
Private Sub editMediators_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.MediatorsListTableAdapter.Fill(Me.ECRDatabaseDataSet.mediatorsList) 'loads current mediator information
DateTimePicker1.Value = Today()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click 'update button
NewData = True
alertMsgBox2()
End Sub
Private Sub alertMsgBox2()
Select Case MsgBox("Yes: Saves Changes," & vbNewLine &
"No: Exits the mediator update window without saving," & vbNewLine &
"Cancel: Returns to the mediator update window.", MsgBoxStyle.YesNoCancel, "Update Mediator Information")
Case MsgBoxResult.Yes
MediatorsListBindingSource.EndEdit()
updateMediator()
'intentionally commented out
'MediatorsListTableAdapter.UpdateMediators(MediatorIDTextBox.Text, MediatorNameTextBox.Text, MaskedTextBox1.Text, MaskedTextBox2.Text, DateTimePicker1.Value,
'AvailabilityTextBox.Text, EmailTextBox.Text)
' Me.Close()
Case MsgBoxResult.No
MediatorsListBindingSource.CancelEdit()
Me.Close()
End Select
End Sub
Private Sub updateMediator()
Dim saveInfo As String
If NewData Then
Dim Message = MsgBox("Are you sure you want to update mediator information? ", vbYesNo + vbInformation, "Information")
If Message = vbNo Then
Exit Sub
End If
Try
'Update mediator information
saveInfo = "UPDATE mediatorsList(mediatorName, email, mediatorPrimaryPhone, mediatorSecondaryPhone, lastMediationDate, availability)
VALUES('" & MediatorNameTextBox.Text & "','" & EmailTextBox.Text & "','" & MaskedTextBox1.Text & "','" & MaskedTextBox2.Text & "',
'" & DateTimePicker1.Value & "','" & AvailabilityTextBox.Text & "', WHERE mediatorID = '" & MediatorIDTextBox.Text & "') "
Catch ex As Exception
End Try
Else
Exit Sub
End If
runAccessSQL(saveInfo)
End Sub
There is obviously something I am missing, though I am not sure it is missing from the code. I checked my database fields and set them to string/text fields just to see if I could get it working. At one time, I had two 2 phone number fields that were set to to the wrong data type so you could only enter a number per int32 requirements. I actually had one of these methods working/updating the db several months ago but I can't figure out what happened since. I do know Visual Studio gave me some problems which probably contributed but it's been too long to remember what happened.
I am rather lost on what else to try as this seems like it should work one way or another. Any ideas what to look at and/or try?? Hopefully I can be pointed in the right direction.
Thanks :)
Your update statement is incorrect, the WHERE clause is inside the VALUES() segment, and should be after it.
Try this instead:
(Edited)
saveInfo = "UPDATE mediatorsList SET mediatorName='" & _
MediatorNameTextBox.Text & "', email='" & EmailTextBox.Text & "', .... WHERE " & _
mediatorID = '" & MediatorIDTextBox.Text & "'"
Also be sure to handle the date correctly. I usually force formatting in yyyy/mmm/dd format.
In my current code, I keep getting the error data type mismatch most of it worked before I added the SQL where statement to select a specific id
Private Sub UpdateButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles UpdateButton.Click
'tells your program the data source
provider = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" 'refrences to the provider
datafile = "C:\Users\Abdulaleem\Documents\Books.accdb" 'refers to the location of the file
connectstring = provider & datafile ' combines the 2 variables
myconnect.ConnectionString = connectstring ' this class allows you to connect to the database
myconnect.Open() ' opens the databse
Dim sqlupdate As String
sqlupdate = "Update BooksTbl set BookName='" & TitleTEXT.Text & "' , [BookAuthor]='" & AuthorTEXT.Text & "',[Genre] ='" & GenreTEXT.Text & "',[IsAvailable] = " & status & ",[DatePublished] = '" & DateTimeCHANGER.Text & "' , [PictureLocation] = '" & PiclocTEXT.Text & "' WHERE [ID] = '" & idshower.Text & "'"
Dim cmd As OleDbCommand = New OleDbCommand(sqlupdate, myconnect) 'creating new database object
Try
cmd.ExecuteNonQuery() ' executes our sql query
cmd.Dispose() 'deleting from ram to stop interferences
myconnect.Close() 'closes database and connection
TitleTEXT.Clear()
AuthorTEXT.Clear()
GenreTEXT.Clear()
Catch ex As Exception ' if the programs crashes then it will be caught here and put into the ex variable
MsgBox(ex.Message) ' shows what error occured
myconnect.Close()
End Try
myconnect.Close()
Assuming that your [ID] column is an integer, try changing it from:
...WHERE [ID] = '" & idshower.Text & "'"
to
...WHERE [ID] = " & idshower.Text
In access, attempting to compare a number with a string results in the message "Data type mismatch in criteria expression".
Note: Unless you are certain the idshower.text actually contains a number, it'd be good practice to check this before executing the query, or access will think you're trying to use a parameter.
Also: You might want to look into parameterised queries which, although they usually result in more lines of code, protect you against things like SQL injection attacks and can perform some basic type conversion for you.
I didnt have much luck when I posted about this when I was programming this application a different way, so I redid the program using DataAdapter instead of the TableAdapter method.
I need help getting data to display inside the DataGridView tool in vb.net Im not sure what i'm doing wrong here... The data displays in the listbox just fine. but will not display in the DataGridView tool. The DataGridView will display the length of the string. Unsure why... See my code below. (BTW, I created the listbox just for testing purposes and dont want to use that)
What the program does: A user places a checkmark on each house project (ex: cement work) and the project gets the list of tools required for the selected project(s). The project names are in checkboxes and checkChanged event assings the text to the variable "ProjectName" in the SQL select statement.
Private Sub Button1_Click_2(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim connection As OleDbConnection
Dim cmdString As String = "Select Distinct ToolName,Notes From Tools Where ProjectName = '" & carpentry & "' or ProjectName = '" & cementWork & "' Or ProjectName= '" & dryWall & "' Or ProjectName = '" & electrical _
& "' Or ProjectName = '" & HVAC & "' Or ProjectName = '" & laminateFlooring & "' Or ProjectName = '" & painting & "' Or ProjectName = '" & plumbing _
& "' Or ProjectName = '" & texture & "' Or ProjectName = '" & tileWork & "' Or ProjectName = '" & vinylFlooring & "'"
connection = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=SaintEnterprises.mdb")
Dim adapter As New OleDbDataAdapter(cmdString, connection)
Dim tools As New DataSet
connection.Open()
adapter.Fill(tools)
Dim toolslist As New List(Of String)
ListBox1.Items.Clear()
For Each row As DataRow In tools.Tables(0).Rows
Dim s As String = row("toolname").ToString
'toolslist.Add(row("toolName").ToString) 'Does same thing as line toollist.add(s) below
toolslist.Add(s.ToString) 'add to List
ListBox1.Items.Add(s.ToString) 'Displays the type of tools based on the query.
Next
ToolsDataGridView.DataSource = toolslist 'displays the length (Total # of letters) of each toolname'
End Sub
Although I probably wont go back to doing it using Table adapter, if you'd like To see my way of programming this application using TableAdapter, see this link.
I think you need a DataTable to fill your DataGridView. Convert you DataSet-Rows to a DataTable.
I've tried this and this works fine for me (assuming, your database connection is working).
Dim oData As New System.Data.DataTable
For Each oRow As System.Data.DataRow In tools.Tables(0).Rows
oData.ImportRow(oRow)
Next
ToolsDataGridView.DataSource = oData
I'm trying to use a VB button to insert data into a database, but it keeps bringing up the error message I have in place for exceptions.
Can anyone help me with why this does not update the database?
Protected Sub Button1_Click(sender As Object, e As System.EventArgs) Handles Button1.Click
Dim connetionString As String
Dim sqlCnn As SqlConnection
Dim sql As String
Dim adapter As New SqlDataAdapter
Dim Customer As String = TextBox1.Text
Dim Product As String = TextBox2.Text
Dim Location As String = TextBox3.Text
Dim Details As String = TextBox4.Text
Dim Owners As String = DropDownList1.Text
Dim Urgency As String = DropDownList2.Text
connetionString = "Data Source=ZUK55APP02;Initial Catalog=BugFixPortal;User ID=SLC***;Password=rep***"
sql = "INSERT INTO Requests (Owner, Customer, Product, Location, Urgency, Details) VALUES ('" & Owners & ", " & Customer & ", " & Product & ", " & Location & ", " & Urgency & ", " & Details & "')"
sqlCnn = New SqlConnection(connetionString)
Try
sqlCnn.Open()
adapter.UpdateCommand = sqlCnn.CreateCommand
adapter.UpdateCommand.CommandText = sql
adapter.UpdateCommand.ExecuteNonQuery()
sqlCnn.Close()
Catch ex As Exception
MsgBox("Unable to update Database with Request - Please speak to Supervisor!")
End Try
End Sub
I would not go down this road as your code is weak against SQL Injection
you should use parameters instead.Something like the below
c.Open();
string insertString = #"insert into YourTable(name, street, city,....) values(#par1, #par2, #parN,....)"
SqlCommand cmd = new SqlCeCommand(insertString, c);
cmd.Parameters.Add("#par1", SqlDbType.VarChar).Value = "MyName";
//etc
cmd.ExecuteNonQuery();
c.Close();
You are incorrectly quoting your values.
This string has an opening and closing single quote around ALL the values, which is incorrect.
VALUES ('" & Owners & ", " & Customer & ", " & Product & ", " & Location & ", " & Urgency & ", " & Details & "')"
Instead, put single quotes around character data, eg., if Product is a varchar, it would look like this:
VALUES (" & Owners & ", " & Customer & ", '" & Product & "', " & Location & ", " & Urgency & ", " & Details & ")"
The real problem, though, is that you should be using parameterized queries instead. This code is prone to SQL injection attacks.
Change this;
MsgBox("Unable to update Database with Request - Please speak to Supervisor!")
to Something like this;
MsgBox("Unable to update Database with Request - Please speak to Supervisor!" & ex.Message)
It will give you more details on the exception, however at a quick glance I can see a problem, the values you are trying to insert are strings, you've enclosed all your values in a single set of ' characters, rather than enclosing each string parameter in a pair of ' values, i.e.
sql = "INSERT INTO Requests (Owner, Customer, Product, Location, Urgency, Details) VALUES ('" & Owners & "', '" & Customer & "', '" & Product & "',' " & Location & "', '" & Urgency & "', '" & Details & "')"
You really should look at parameterizing your queries as you're wide open to SQL injection attacks. See HERE
In terms of your code itself, your SQL syntax is wrong as you need to put apostrophes around each value. Try this:
sql = "INSERT INTO Requests (Owner, Customer, Product, Location, Urgency, Details)
VALUES ('" & Owners & "', '" & Customer & "', '" & Product &
"', '" & Location & "', '" & Urgency & "', '" & Details & "')"
Here's an example using Parameters
sql = "INSERT INTO Requests (Owner, Customer, Product, Location, Urgency, Details)
VALUES ('#Owners', '#Customer', '#Product', '#Location', '#Urgency', '#Details')"
Then add parameters like so:
command.Parameters.AddWithValue("#Owners", Owners)
command.Parameters.AddWithValue("#Customer", Customer)
command.Parameters.AddWithValue("#Product", Product)
command.Parameters.AddWithValue("#Location", Location)
command.Parameters.AddWithValue("#Urgency", Urgency)
command.Parameters.AddWithValue("#Details", Details)
I think you want to use adapter.InsertCommand instead of adapter.UpdateCommand
in
Try
sqlCnn.Open()
adapter.UpdateCommand = sqlCnn.CreateCommand //(adapter.InsertCommand)
adapter.UpdateCommand.CommandText = sql //(adapter.InsertCommand)
adapter.UpdateCommand.ExecuteNonQuery() //(adapter.InsertCommand)
sqlCnn.Close()
Catch ex As Exception
MsgBox("Unable to update Database with Request - Please speak to Supervisor!")
End Try
and agree with parametrized sql query
see http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldataadapter.aspx for more infos