Our program when I click update button it updates all the data in the data grid view, what's wrong with our codes?
This is our code
Private Sub btnUpdate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnUpdate.Click
con.ConnectionString = ("server=localhost;user id=root;password=;database=sample4")
Try
con.Open()
With cmd
.Connection = con
.CommandText = "UPDATE inventory SET product_name='" & txtPN2.Text & "',product_quantity='" & txtQuan2.Text & "',date='" & txtDate2.Text & "' WHERE 1"
result = cmd.ExecuteNonQuery
If result = 0 Then
MsgBox("Data has been already updated!")
Else
MsgBox("Successfully updated!")
.CommandText = "Select product_name,product_quantity,date from inventory"
txtPN2.Clear()
txtQuan2.Clear()
txtDate2.Clear()
txtPN2.Focus()
End If
End With
Catch ex As Exception
MsgBox(ex.Message)
End Try
con.Close()
End Sub
There are a lot of errors here, both logical and bad practices at work.
Starting from the logical errors first:
What do you think this statement does? WHERE 1 (I don't even know if it is accepted by your database but suppose that it works). It doesn't locate a precise record to update, it let every record in your table to receive the same values specified in the SET list. You need to pass a key to identify a precise record to update. Something like WHERE KeyField=KeyValue where KeyField is the name of a column in your table Invetory whose values are unique so just one record is selected for the update
Second logical problem: If result = 0 Then this is wrong because the result of ExecuteNonQuery is the number of records updated/inserted/deleted. In your case the UPDATE sql updates always a record if it finds one. It update the record also if the values are the same as before. Zero instead means that no record has been found by the WHERE clause (after fixing it in the first step). Thus if you get zero as result then no record exists in your table that match the WHERE clause.
Now the bad practices.
SET product_name='" & txtPN2.Text &.....
This is a string concatenation that builds an sql statement. Wrong on many levels. If one of your textboxes contains a single quote the whole text becomes syntactically invalid. Finally a malicious user could write anything in those textbox and create an Sql Injection hack that could destroy your database or grab sensitive informations. You should use a parameterized query
.CommandText = "UPDATE inventory SET product_name=#prod " & _
",product_quantity=#qty,date=#dt WHERE keyField=#kvalue"
.Parameters.Add("#prod", SqlDbType.NVarChar).Value = txtPN2.Text
.Parameters.Add("#qty", SqlDbType.Int).Value = Convert.ToInt32(txtQuan2.Text)
.Parameters.Add("#qty", SqlDbType.DateTime).Value = Convert.TODateTime(txtDate2.Text)
.Parameters.Add("#kvalue", SqlDbType.Int).Value = kvalue
result = cmd.ExecuteNonQuery
Second bad practice: Keeping global objects for connection and commands. These are disposable objects, they should be used in a well know pattern. Create, Use, Destroy to free as soon as possible precious system resources. Keeping them global gains to you nothing and you are at risk to leak resources. Keep global (or better read from the app.config) just the connection string and apply the using statement around the connection and the command
Related
coding noob here. I'm looking for help after hours of googling and watching YouTube tutorials provided no success. I've also tried looking at many of the posts on this website. I keep running into the same problem.
In Visual Studio I am attempting to create a solution with VB.net, it is currently successfully linked to an Access Database with which I can view, add, edit, and save records live.
I am trying to fetch data from the Access database based on a search of one of the fields, and then save that data as a variable.
(Code shown below)
Upon attempting to click the search button, I received the following exception: System.Data.OleDb.OleDbException: 'Syntax error (missing operator) in query expression 'First Name'.'
I believe it is because my field names are two words, but I have no idea how to fix this. Just typing it with one word gives this exception instead:
System.Data.OleDb.OleDbException: 'No value given for one or more required parameters.'
I have been completely unable to make progress despite watching multiple different versions of tutorials on how to perform this. Could someone please help me out?
Here is the code:
Public Class FormTraits
Private Sub FormTraits_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub FNButton_Click(sender As Object, e As EventArgs) Handles FNButton.Click
Dim conn As New OleDbConnection
conn.ConnectionString = ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Access Database.accdb")
conn.Open()
Dim strsql As String
strsql = "select ID, First Name, Last Name from PlayerData where First Name=" + TextBoxSearch.Text + ""
Dim cmd As New OleDbCommand(strsql, conn)
Dim myreader As OleDbDataReader
myreader = cmd.ExecuteReader
myreader.Read()
TextBoxFirstName.Text = myreader("First Name")
TextBoxLastName.Text = myreader("Last Name")
TextBoxID.Text = myreader("ID")
conn.Close()
End Sub
End Class
You should avoid using names including spaces or other special characters for tables, columns, etc, in your database. Just as you would do for a variable name or the like in VB - and as you have done for your table name - you should name your columns FirstName and LastName. If you must include spaces or other special characters, you must escape the identifiers in your SQL code. You also need to wrap text literals in single quotes, much as you wrap them in double quotes in VB:
strsql = "SELECT ID, [First Name], [Last Name] FROM PlayerData WHERE [First Name] = '" & TextBoxSearch.Text & "'"
It would be better if you used parameters instead of string concatenation, but that's beyond the scope of this question.
adding updating everything is fine even delete command is working but the strange part is after executing del command from vb.net application it swipes the position of EMPLOYEE_IDAND NAMEit shows normally in datagridviewafter adding or updating but specifically after deleting the record position of these to column changes until I stop the application and re run the entire project for debugging
Dim con As New MySqlConnection("server=localhost; user=root; password=Masoom1; database=airtech_db; convert zero datetime=true;")
Dim cmd As New MySqlCommand
Dim dt As New DataTable
Dim da As New MySqlDataAdapter
Dim sql As String
Dim DR As MySqlDataReader
Dim SQL_CMD_TXT As String
SQL_CMD_TXT = "DELETE FROM `employees` WHERE (`EMPLOYEE_ID` ='" &
EMPLOYEE_DEL_FRM.DEL_ID_TXT.Text & "'); SELECT * FROM `employees`;"
EMPLOYEE_DEL_FRM.Controls.Add(OBJECT_DATAGRIDVIEW)
With OBJECT_DATAGRIDVIEW
.Size = New Size(587, 242)
.Location = New Size(221, 171)
End With
Try
'DB CMD EXECUTION
con.Open()
With cmd
sql = SQL_CMD_TXT
.Connection = con
.CommandText = sql
End With
da.SelectCommand = cmd
da.Fill(dt)
'Command for datagridview object
With OBJECT_DATAGRIDVIEW
.DataSource = dt
'Scroll to the last row.
.Name = "MYDATAGRIDVIEW"
.FirstDisplayedScrollingRowIndex = .RowCount - 1
End With
con.Close()
Catch ex As Exception
Dim MEB = MessageBox.Show("ERROR FOR SQL CMD EXECUTION SECTION-" & ex.Message,
"SQL CMD EXECUTION", MessageBoxButtons.OK, MessageBoxIcon.Error)
Exit Sub
End Try
attaching the normal and after delete result in images
enter image description here
I am not sure I completely understood your problem, but your problem could that the datagridview generates the columns automatically. See: DataGridView.AutoGenerateColumns
Instead of doing SELECT * FROM is would better to select just the fields you need. If you add more fields to your table in the future, the columns in the datagridview may be displaced because they are in no particular order.
Rather than add the datagridview to your form at runtime:
EMPLOYEE_DEL_FRM.Controls.Add(OBJECT_DATAGRIDVIEW)
I would add it directly in the form layout (so you can see it at design time), and then customize it, bind each column to a database field. The appearance of the grid will be more predictable. Here is a small guide: How to bind datatable/list to datagridview with headers?
Relying on AutoGenerateColumns is not a great idea, because this will show all columns (usually not desirable) and not necessarily in the order that you want.
Other remarks:
Records can be edited or deleted directly in the datagridview, by simply selecting one or more rows, and pressing the Del key. Then just invoke the DataAdapter to commit the changes to the database. You should not even be doing DELETE FROM. Just let the user use the datagridview. The benefit is that if the user makes a mistake, you can roll back changes because you are using a datatable. Here you are deleting immediately and without warning.
Don't do stuff like:
SQL_CMD_TXT = "DELETE FROM `employees` WHERE (`EMPLOYEE_ID` ='" &
EMPLOYEE_DEL_FRM.DEL_ID_TXT.Text & "'); SELECT * FROM `employees`;"
Use parameterized queries instead, this code is insecure and will choke on single quotes or special characters (try it !). Here is a simple example: FAQ: How do I make a parameterized query in the database with VB.NET?. Please use parameterized queries from now on, don't develop bad habits that will always bite you sooner or later. The security risk alone is too high.
Also I am wondering why you did stacked queries. It would better to separate the SELECT from the DELETE.
In this code variable sql is not needed:
With cmd
sql = SQL_CMD_TXT
.Connection = con
.CommandText = sql
End With
Just use SQL_CMD_TXT directly. Otherwise it makes the code more difficult to follow.
I have created a database that holds 3 values, the ID, UserName, and Score. I need to create a new entry to this database when the save button is clicked. My program needs to create a new row with the Username and score provided by the application.
This is my code to update an existing database:
Private Sub ButtonSaveScore_Click(sender As Object, e As EventArgs) Handles ButtonSaveScore.Click
provider = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source="
dataFile = "F:\Documents\Class Documents\CSC289 - K6A - Programming Capstone Project\Project\Scoreboard.accdb"
connString = provider & dataFile
myConnection.ConnectionString = connString
Using con As New OleDbConnection(connString),
cmd As New OleDbCommand("UPDATE [Scores] SET [UserName] = ?, [Score] = ? WHERE [ID] = ?", con)
con.Open()
cmd.Parameters.Add("#ID", OleDbType.Char).Value = "NEW"
cmd.Parameters.Add("#UserName", OleDbType.Char).Value = playerName
cmd.Parameters.Add("#Score", OleDbType.Char).Value = wins
cmd.ExecuteNonQuery()
End Using
End Sub
I get
oledb exception was unhandled
It highlights cmd.ExecuteNonQuery() and says data criteria mismatch.
Can someone give me advice to get this working?
You have a couple of issues there. Firstly, at least one of your parameters is the wrong data type. Secondly, your parameters are in the wrong order.
The Jet and ACE OLE DB providers only partially support named parameters, in that they allow you to use names so that your code can be clearer but they ignore the names and just use the positions. That means that you need to add the parameters to your OleDbCommand in the same order as they appear in the SQL code. You're not doing that so you have one issue there, although that's not the direct cause of your error message.
Even if those providers did fully support named parameters though, you're not using names in your SQL code. That means that there would be no way to match up parameters by name anyway, so how did you think that adding them in the wrong order wouldn't be an issue?
Given that all three of your parameters are specified as the same data type though, the incorrect order would not cause the error message you're seeing. If that data type was correct, you'd just find that the wrong data was saved to some of the columns, which would be even worse, i.e. appearing to work but not rather than just failing. You need to make sure that you use the correct OleDbType value for the column you're trying to save to. If your ID column in the database is specified to contain 32-bit numbers then you should be using OleDbType.Integer for the corresponding parameters. I'd also suggest using VarChar rather than Char unless your column is specifically fixed-width, which a Text column in Access is unlikely to be and I'm not sure even can be.
I'm new to VB. It's been few weeks since I started learning VB.My question is I'm having difficulty in adding Data in to the Database (I'm using MS Access) from VB. So far I got this code but it isn't running well:
Imports System.Data.OleDb
Public Class CraeteAccount
Dim connString As String
Dim myConnection As OleDbConnection = New OleDbConnection
Dim cmd As New OleDbCommand
Dim dr As OleDbDataReader
Public Sub btnCreate_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCreate.Click
connString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & IO.Path.Combine(My.Application.Info.DirectoryPath, "LogIn1.accdb")
Dim cmd As New OleDbCommand
Dim cnn As OleDbConnection = New OleDbConnection(connString)
Dim str As String
Dim UserName As String
Dim Password As String
If txtPassword.Text = txtRetype.Text Then
cnn.Open()
Try
UserName = txtUserName.Text
Password = txtPassword.Text
str = "UPDATE Users SET UserName= '" & UserName & "', Password= '" & Password
cmd = New OleDbCommand(str, myConnection)
cmd.Parameters.AddWithValue("#UserName", UserName)
cmd.Parameters.AddWithValue("#Password", Password)
cmd.ExecuteNonQuery()
MsgBox("New User has been Created!")
cnn.Close()
Me.Hide()
Catch ex As Exception
MsgBox("Error Occured!")
cnn.Close()
End Try
Me.Close()
Else
MsgBox("Check your Password!")
cnn.Close()
txtPassword.Focus()
End If
End Sub
When the code runs It donot add data and quickly goes to catch to show the Message Box which reads "Error Occured". So Can anyone Please Help me?
At a quick glance, the SQL query is broken in several ways:
str = "UPDATE Users SET UserName= '" & UserName & "', Password= '" & Password
The first thing to notice is that you're not closing the quotes after the password. However, even that isn't what you really want to do. What you want to do is this:
str = "UPDATE Users SET UserName=#UserName, Password=#Password"
This creates query parameters, which your next two lines are looking to populate with values:
cmd.Parameters.AddWithValue("#UserName", UserName)
cmd.Parameters.AddWithValue("#Password", Password)
Putting user values directly into the query is called a SQL injection vulnerability. It allows users to execute arbitrary code on your database, which is clearly a bad thing. So you're definitely going to want to stick with using these parameters instead.
The second problem here is that this query is going to update every record int he table. So it's basically going to overwrite all Users records with multiple copies of this one record.
If this really should be an UPDATE statement when you're going to want to add a WHERE clause to it which would identify the specific record you want to update.
However, I suspect based on the context that this should instead be an INSERT statement, since it's creating a new record:
str = "INSERT INTO Users (UserName, Password) VALUES (#UserName, #Password)"
Additionally, and this is important, you are storing user passwords in plain text. This is grossly irresponsible to your users. You should be obscuring user passwords with a 1-way hash so that they can never be retrieved in their original form. Not even by you as the system administrator.
(The language and emphasis used here may be a bit harsh for a beginner. Especially if you're working on a purely academic project with no actual users. But it's seriously that important. And there's no time like the present to learn about it.)
Another issue here is that you're assuming success of the query:
cmd.ExecuteNonQuery()
MsgBox("New User has been Created!")
At the very least you should be checking the return value to make sure a record was actually affected:
Dim rowsAffected As Int32 = cmd.ExecuteNonQuery()
If rowsAffected > 0 Then
MsgBox("New User has been Created!")
Else
'no record was inserted, handle error condition
End If
Another issue that you're facing, which isn't directly related to your problem but is making it much more difficult for you to debug your problem, is that you're ignoring error information:
Catch ex As Exception
MsgBox("Error Occured!")
cnn.Close()
In this code block the ex variable contains all of the information that the .NET Framework can give you about the error that took place. What you're basically doing is replacing all of that diagnostic information (error message, stack trace, etc.) with a single custom error message that contains no information.
Best not to do that.
Note that, given these issues, there may very well be other problems with the code. But this should at least get you going for a bit.
You're simultaneously trying to concatenate an update statement with user input (bad) and using parameterized values (good). Try
str = "UPDATE Users SET UserName=#UserName, Password=#Password"
cmd = New OleDbCommand(str, myConnection)
cmd.Parameters.AddWithValue("#UserName", UserName)
cmd.Parameters.AddWithValue("#Password", Password)
But this still won't work because this update statement will update all the records in the database with these values. Are you trying to update an existing record or create a new one? If you're updating an existing one, you need a WHERE clause; if you're trying to create a new one, you need to use INSERT instead.
I am new to this forum, please could you help me get this code to work, when i execute it, it simply does nothing and does not update the DB. If i remove the square brackets it gives an error: "SYNTAX ERROR in UPDATE statement"
Any help appreciated!
Dim connection As OleDbConnection
connection = New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=UserDB.accdb;Jet OLEDB:Database;")
connection.Open()
Dim pass As String
pass = txtconfirm.Text
Dim user As String
user = LoginForm.UsernameTextBox.Text
Dim query As String = "UPDATE [Users] SET [Password]= '" & pass & "' WHERE [Username]= '" & user & "';"
Dim command As New OleDbCommand(query, connection)
command.ExecuteNonQuery()
connection.Close()
Given your actual connection string, the database that will be updated is the one in the directory where your application starts. This means that if you work with a WinForms application this folder is \BIN\DEBUG or x86 variant. If there is not error then you could get the return value of the ExecuteNonQuery call to verify if a record has been updated or not
Dim rowsUpdated = command.ExecuteNonQuery()
MessageBox.Show("Record updated count = " & rowsUpdated)
If this value is not zero then your database has been updated and you are looking for changes in the wrong database. Check the one in the BIN\DEBUG folder.
In any case your code has big problems. If your variables user or pass contain a single quote, then your code will crash again because your string concatenation will form an invalid SQL. As usual the only workaround is to use a parameterized query
Dim pass = txtconfirm.Text
Dim user = LoginForm.UsernameTextBox.Text
Dim query As String = "UPDATE [Users] SET [Password]= #p1 WHERE [Username]= #p2"
Using connection = New OleDbConnection("...........")
Using command As New OleDbCommand(query, connection)
connection.Open()
command.Parameters.Add("#p1", OleDbType.VarWChar).Value = pass
command.Parameters.Add("#p2", OleDbType.VarWChar).Value = user
command.ExecuteNonQuery()
End Using
End Using
The parameterized approach has many advantages. Your query text is more readable, there is no misunderstanding between your code and the values expected by your database engine. And while not easy to exploit with MS-Access there is no problem with Sql Injection
I think Steve presents a much better approach for you coding this...
Let me just throw out a few more things:
The reason you can't take those brackets out is some of your column names are reserved words; just FYI.
Since you report "it does nothing..." when you execute, it sounds like you have a valid connection and sql syntax, in which case my next step would be to copy the sql command text while in debug mode, change it to a select and run it in your DB. You should get one result when you do. If not, either your criteria or field contents are not what you think they are...
Just change the Update table SET field-value ... to SELECT * FROM table and leave the WHERE clause as is.