I have got a datagrid view which is filled by a table on my microsoft mysql database my problem is i need to select a row and its values then appear in the text boxes which i have solved. but now if any changes are to occur i want to create an update function to update the records with the changes made. I've tried but failed until now.
Public Sub AddMember(FirstName As String, Surname As String, Admin As Integer)
Try
Dim strInsert As String = _
"UPDATE test Firstname='this should be the value entered in the text box' " & _
"WHERE Firstname = 'this should equal to the value selected from the datagrid view'"
MsgBox(strInsert)
SQLCon.Open()
SQLCmd = New SqlCommand(strInsert, SQLCon)
SQLCmd.ExecuteNonQuery()
SQLCon.Close()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
I you are working with MySQL then you should be using MySqlCommand instead of SqlCommand. Also use a MySqlConnection. You find both in the MySql.Data.MySqlClient namespace.
You also will need to download and install the "Connector/Net" and add a reference to MySql.Data.dll in your project if you have not done this already .
Also use command parameters instead of string concatenation. This is both safer (See: SQL injection) and easier, as you do not have to worry about formatting strings, numbers and dates the right way for SQL.
Dim sql As String = "UPDATE tst SET FirstName=#fn, Surname=#sn WHERE Id=#id"
Using conn = New MySqlConnection(connectionString)
Using cmd = New MySqlCommand(sql, conn)
cmd.Parameters.AddWithValue("#fn", FirstName)
cmd.Parameters.AddWithValue("#sn", Surname)
cmd.Parameters.AddWithValue("#id", id)
conn.Open()
cmd.ExecuteNonQuery()
End Using
End Using
Note that the WHERE-clause should identify the database row by its primary key. In MySQL a primary key is best created as AUTO_INCREMENT column. In no case use the first name in order to identify the row, as serveral persons can have the same first name. See: Using Primary Keys and SQL PRIMARY KEY Constraint.
check syntax for update here
so change your query as follows:
Dim strInsert As String = " update test Set FirstName= '" & FirstName & "'," & _
"Surname='" & Surname & "'," & _
"admin='" & Admin & "')"
This is the query you should use.
Parameters with # are actually values you're sending to SQL.
Update test Set FirstName=#FirstName where Id=#Id
Related
Can you please help me, what the problem of my code:
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
'UPDATE Data
openCon()
Try
cmd.Connection = con
cmd.CommandText = "UPDATE emp_table SET FNAME = '" & TextBox1.Text & "', LNAME= '" & TextBox2.Text & "', AGE = '" & TextBox3.Text & "', GENDER ='" & Gender & "', OFFICE STAFF= '" & ComboBox1.Text & "' Where ID ='" & TxtID.Text & "' "
cmd.ExecuteNonQuery()
con.Close()
MsgBox("Suceessfully Updated Record")
TxtID.Clear()
TextBox1.Clear()
TextBox2.Clear()
TextBox3.Clear()
RBMale.Checked = False
RBFemale.Checked = False
ComboBox1.Text = ""
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
There are many problems in your code and if you look around this site I think you will find many partial answers that step by step will help you solve your problems. So I try to give you an answer where all the problems are examined, discussed and solved.
First problem: How do you handle the connection.
It seems that you have a global connection instance called con that you open with openCon. This is not a good approach and always a source of problems. You always need to check if the connection is closed properly or not. For example, in the code above you have forgot to close the connection in case of exception and this will lead to other exceptions in some code not related to this one. You keep resources on the server locked to you and this will decrease the performance of every one connection to that server.
I would change your openCon to this
Public Function openCon() as MySqlConnection
Dim con as MySqlConnection = new MySqlConnection(....here connection string ...)
con.Open()
return con
End Function
This will create a new instance of the MySqlConnection every time you call this method Now you can remove the global connection instance and use the one returned by openCon in this way
Using con As MySqlConnection = openCon()
.... code that use the local con object
End Using
This will close and destroy the connection even if an exception occurs inside the Using block and the ADO.NET libraries are smart enough to use a thing called Connection Pooling to reduce the time required to build and open a connection with the same connection string.
Second problem: The syntax error.
Looking at the point of the error suggested by the message I can see a field name composed by two words separated by a space. This is fine, but then you should remember that the sql parser cannot understand this and you need to help it enclosing the two words in a backtick character (ALT+096) so the parser understand that this is a single field name. Given the fact column names are an internal information of no concern for your end user then why use spaces in column names? If possible remove the space in column names.
Third problem: Sql Injection and other syntax errors
You are concatenating strings to build an sql command. But this is an easy target for wannabe hackers. Suppose that I write in your textBox1 this string instead of a First Name: Mario'; --
Then your command becomes
UPDATE emp_table SET FNAME = 'Mario'; -- xxxxxxxxxxxx
everything after -- is considered a comment and the query is still executable, but it changes every record in emp_table to have a first name equal to Mario.
But the query could fail as well if someone writes a Last Name that contains an apostrophe like O'Leary just now the query is no more syntactically valid.
The solution to this is always one. Use Parameters.
Recap of changes to your code.
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Dim cmdText as String = "UPDATE emp_table SET FNAME = #fname,
LNAME= #lname, AGE = #age, GENDER =#gender,
`OFFICE STAFF` = #staff
Where ID =#id"
Using con as MySqlConnection = openCon()
Using cmd as MySqlCommand = new MySqlCommand(cmdText, con)
Try
cmd.Parameters.Add("#fname", MySqlDbType.VarChar).Value = textBox1.Text
cmd.Parameters.Add("#lname", MySqlDbType.VarChar).Value = textBox2.Text
cmd.Parameters.Add("#age", MySqlDbType.VarChar).Value = textBox3.Text
cmd.Parameters.Add("#gender", MySqlDbType.VarChar).Value = gender
cmd.Parameters.Add("#staff", MySqlDbType.VarChar).Value = combobox1.Text
cmd.Parameters.Add("#id", MySqlDbType.VarChar).Value = txtID.Text
cmd.ExecuteNonQuery()
MsgBox("Suceessfully Updated Record")
TxtID.Clear()
TextBox1.Clear()
TextBox2.Clear()
TextBox3.Clear()
RBMale.Checked = False
RBFemale.Checked = False
ComboBox1.Text = ""
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Using
End Using
End Sub
In the recap I have added parameters for every single field that you want to update. But remember. Parameters should have a Type (The MySqlDbType here) that should match the type of the field and the value should be of the same type. For example it seems improbable that Age is a varchar field. So you should convert TextBox3.Text to an integer if the field is an integer.
I've searched around the web looking for samples on how to use MySqlHelper.UpdateDataSet but all I've found is:
Public Shared Sub UpdateDataSet( _
ByVal connectionString As String, _
ByVal commandText As String, _
ByVal ds As DataSet, _
ByVal tablename As String _
)
I'll be grateful if someone will give me:
an example of commandText because I didn't understand what kind of command I need to give;
an explanation of tablename because I need to know if is the name of a table of the DB or of the DataSet or both (with the same name);
a vb.net code example (to start testing).
I tryed to use the command this way:
Private Sub Btn_Mod_Dataset_Click(sender As Object, e As EventArgs) Handles Btn_Mod_Dataset.Click
Dim SqlStr$ = "SELECT * FROM MyTest.Users"
Using DS_Test As DataSet = DB_Functions.mQuery(SqlStr)
With DS_Test
.Tables(0).TableName = "Users"
Dim User$ = .Tables(0).Rows(0)("UserName").ToString
MsgBox(User)
.Tables(0).Rows(0)("User") = "Upd_Test"
User = .Tables(0).Rows(0)("UserName").ToString
MsgBox(User)
End With
Dim DB_Name = "MyTest"
Dim connectionString$ = "datasource=localhost;username=" + UserDB _
+ ";password=" + Password + ";database=" + DB_Name
MySqlHelper.UpdateDataSet(connectionString, _
"Update MyTest.Users Set UserName = 'Test_Ok' WHERE UserName = 'Steve'", _
DS_Test, "Users")
End Using
End Sub
This gives me
System.NullReferenceException' in System.Data.dll
EDIT (to explain my code):
a) DB_Functions is a sepate class where I've stored some function to use on a MySql DataBase. mQuery is a function who extract query result into a dataset;
b) 'User' is a field Name : I've changed it to 'UserName' but same result;
d) The code between With and End With is just a test to see what happens;
NOTE that the code gives error but my DB is updated as in the commandText String. I don't understand what happens
This might get you part of the way.
First get rid of DB_Functions. MySQLHelper has a method to create the DataSet for you; in general, db Ops are so query-specific that there is very little that is generic and reusable. The exception to this is building the ConnectionString: MySQL has gobs of cool options you can enable/disable via the connection string. But for that you just need the standard MySqlConnectionStringBuilder.
Build a DataSet:
' form/class level vars
Private dsSample As DataSet
Private MySqlConnStr As String = "..."
...
Dim SQL = "SELECT Id, FirstName, Middle, LastName FROM Employee"
Using dbcon As New MySqlConnection(MySQLConnStr)
dsSample = MySqlHelper.ExecuteDataset(dbcon, SQL)
dsSample.Tables(0).TableName = "Emps"
End Using
There does not appear to be a way to specify a tablename when you build it, so that is a separate step.
Update a Record
To update a single row, you want ExecuteNonQuery; this will also allow you to use Parameters:
Dim uSQL = "UPDATE Employee SET Middle = #p1 WHERE Id = #p2"
Using dbcon As New MySqlConnection(MySQLConnStr)
Dim params(1) As MySqlParameter
params(0) = New MySqlParameter("#p1", MySqlDbType.String)
params(0).Value = "Q"
params(1) = New MySqlParameter("#p2", MySqlDbType.Int32)
params(1).Value = 4583
dbcon.Open()
Dim rows = MySqlHelper.ExecuteNonQuery(dbcon, uSQL, params)
End Using
Again, this is not really any simpler than using a fully configured DataAdapter, which would be simply:
dsSample.Tables("Emps").Rows(1).Item("Middle") = "X"
daSample.Update(dsSample.Tables("Emps"))
I am not exactly sure what value the UpdateDataSet method adds. I think it is the "helper" counterpart for the above, but since it doesn't provide for Parameters, I don't have much use for it. The docs for it are sketchy.
The commandtext would appear to be the SQL for a single row. Note that the DataAdapter.Update method above would add any new rows added, delete the deleted ones and update values for any row with changed values - potentially dozens or even hundreds of db Ops with one line of code.
My funtion gets string query and returns datatable. So u can set dataset.tables .
Public Function mysql(ByVal str_query As String) As DataTable
Dim adptr As New MySqlDataAdapter
Dim filltab As New DataTable
Try
Using cnn As New MySqlConnection("server=" & mysql_server & _
";user=" & mysql_user & ";password=" & mysql_password & _
";database=" & mysql_database & ";Allow User Variables=True")
Using cmd As New MySqlCommand(str_query, cnn)
cnn.Open()
adptr = New MySqlDataAdapter(cmd)
adptr.Fill(filltab)
cnn.Close()
End Using
End Using
Catch ex As Exception
'you can log mysql errors into a file here log(ex.ToString)
End Try
Return filltab
End Function
I've just heard about the mysql connector and I want now to take a single row from my database(every row is unique). I don't want to use a loop because it would be useless(only for one row?..). I know how to connect to a database but I just can't figure out how to select a single row. This is my code :
''Register user in dtb
cmd = New MySqlCommand("INSERT INTO `users`(`name`, `ip`, `status`) VALUES ('" & My.User.Name.Split("\")(1) & "','" & ip_temp & "','1')", conn)
cmd.ExecuteNonQuery()
''Get user's Id from dtb -->this is where I'm having troubles
cmd = New MySqlCommand("SELECT 'id' FROM `users` WHERE name='" & My.User.Name.Split("\")(1) & "' ", conn)
dtb_data = cmd.ExecuteScalar
Debug.Print(dtb_data(0))
It doesn't work. The error is: "Unable to cast object of type 'System.String' to type 'MySql.Data.MySqlClient.MySqlDataReader'." (of course...). I know that it must look something like "dtb_data['id']" (from php) but this command doesn't exist in VB.Net. What should I do?
ExecuteScalar returns single value from single row. Therefore in your case dtb_data must be declared as String. Most probably this is mistake and it should be declared as Int or Long as you probably want to return id, not 'id' as literal.
So the full example should be:
Dim dtb_data as Long
cmd = New MySqlCommand("SELECT id FROM `users` WHERE name='" & My.User.Name.Split("\")(1) & "' ", conn)
dtb_data = cmd.ExecuteScalar
Debug.Print(dtb_data)
Why won't this delete the data in my MySQL database!?
Private Sub Button4_Click(sender As System.Object, e As System.EventArgs) Handles Button4.Click
Dim dbCon As MySqlConnection
Dim strQuery As String = ""
Dim SQLCmd As MySqlCommand
Dim DR As MySqlDataReader
Try
dbCon = New MySqlConnection("Server=Localhost;Database=myusers;Uid=root;Pwd=Mypassword")
strQuery = "DELETE settings FROM settings WHERE user=" & Me.loginuser.Text
'* FROM settings WHERE user = "Testuser"'
SQLCmd = New MySqlCommand(strQuery, dbCon)
' OPEN THE DB AND KICKOFF THE QUERY
dbCon.Open()
DR = SQLCmd.ExecuteReader
While DR.Read
req1.Text = "" And exlink.Text = ""
End While
' DONE! Close DB
DR.Close()
dbCon.Close()
Catch ex As Exception
TextBox8.Text = ("Fail" & vbCrLf & vbCrLf & ex.Message)
End Try
Here is a picture of my database:
Alternatively I could somehow make it replace what is already in the database, in which case please help me with that.
Try
strQuery = "DELETE FROM settings " _
& " WHERE user = '" & Me.loginuser.Text & "'"
but as was stated earlier, you should be using parameterized queries. If you had a user named O'Brien then your query (as composed above) would fail because of the embedded single quote. When you use DELETE, you are deleting entire records and you already specify the table name in the FROM clause.
I will try to change your code in this way
Using con = New MySqlConnection("Server=.....")
con.Open()
Dim sqlText = "DELETE * FROM settings WHERE user = #ulogin"
Using cmd = new MySqlCommand(sqlText, con)
cmd.Parameters.AddWithValue("#ulogin", Me.loginuser.Text)
cmd.ExecuteNonQuery()
End Using
End Using
First and foremost, do not use string concatenation to create command texts to pass to the database engine. In that way you risk Sql Injections, also, if the user name contains a single quote (i.e. O'Hara) your code will fail with a syntax error (Same problems arise for date formatting, parsing numeric decimals and other globalization issues). Instead a parametrized query like the one in code above will avoid all of these problems.
In a parametrized query, the text of the query doesn't contains the actual value for the search condition or the update or insert data. Instead it contains placeholders ( in our case it is called #ulogin). The correct value to insert at the placeholders position is specified using one or more MySqlParameter added to the Parameters collection of the MySqlCommand. In this case I have used the AddWithValue method that derives the correct datatype directly from the datatype of the value. Because Me.loginuser.Text is a string value then the parameter will be treated as a string value replacing incorrect single quotes and removing extraneus characters usually used to Mount Sql Injections Attacks. The engine will do the rest inserting the correct value at the placeholder at execution time
EDIT: Seeing your comment about the MySql connector used, I will try to update my answer to show a semi-equivalent version for NET 1.
Try
Dim con As MySqlConnection = New MySqlConnection("Server=.....")
con.Open()
Dim sqlText as String = "DELETE * FROM settings WHERE user = #ulogin"
Dim cmd As MySqlCommand = new MySqlCommand(sqlText, con)
Dim par As MySqlParameter = New MySqlParameter("#ulogin", MySqlDbType.VarChar)
par.Value = Me.loginuser.Text
cmd.Parameters.Add(par)
cmd.ExecuteNonQuery()
Finally
con.Close()
End Try
I am not sure if the connector 1.0.10 supports the parameter name with the # prefix or just the : prefix
i dont think you can use double quotes in mysql, i think its single quotes only. try
Query = "DELETE * FROM settings WHERE user = '" & Me.loginuser.Text & "'"
Good evening,
I'm using the following code to truncate a table in my MySQL database. From what I can tell, the query is running fine and the tables are being truncated. However, the if statement that I'm using to test if rows are affected is being evaluated on the Else statement.
So how come the table in the database is being truncated - as expected - but the Else statement is being evaluated - as if no rows are affected? What am I doing wrong?
HERE'S THE CODE:
Public Sub purgeCC()
Dim dbAdapter As New MySqlDataAdapter
Dim dbCmd As New MySqlCommand
Dim ConnectionString As String = String.Format("Server={0};Port={1};Uid={2};Password={3};Database=accounting", FormLogin.ComboBoxServerIP.SelectedItem, My.Settings.DB_Port, My.Settings.DB_UserID, My.Settings.DB_Password)
Dim myQuery As String = "TRUNCATE TABLE cc_master"
Using dbConn As New MySqlConnection(ConnectionString)
Using dbComm As New MySqlCommand()
With dbComm
.Connection = dbConn
.CommandType = CommandType.Text
.CommandText = myQuery
End With
Try
Dim affectedRow As Integer
dbConn.Open()
affectedRow = dbComm.ExecuteNonQuery()
If affectedRow > 0 Then
MsgBox("Credit Card Master table has been successfully purged!", MsgBoxStyle.Information, "DATABASE PURGED!")
Else
MsgBox("Credit Card Master table was not purged!", MsgBoxStyle.Critical, "ATTENTION")
End If
Catch ex As Exception
MessageBox.Show("A DATABASE ERROR HAS OCCURED" & vbCrLf & vbCrLf & ex.Message & vbCrLf & _
vbCrLf + "Please report this to the IT/Systems Helpdesk at Ext 131.")
End Try
dbConn.Close()
dbComm.Dispose()
End Using
End Using
End Sub
Per this document http://dev.mysql.com/doc/refman/5.0/en/truncate-table.html
the truncate command may not always return the rows affected if the DB version is greater than 5.somthing and the table does not have foreign key constraints. if you do have FKs then a delete is processed for each row and you get the return value you are seeking, but if you don't then mysql will drop and re-add the table (which is much faster), which means it has no ideas how many records were affected.
Your if statement is being evaluated correctly, it's just that affectedRow (which should probably be affectedRows by the way, but I'm just being pedantic there) is not being set as you expect.
It's not wise to depend on the affected rows count for a truncation as per the online docs for truncate table.
In some cases, it's only accurate if it gets mapped to a delete (such as specific versions with the InnoDB engine where there are foreign key constraints, since they have to be checked or cascaded).
With other engines, you may get 0 because it drops the table and then recreates it.
If you really want the information, execute a select count(*) before and after the truncation. The after should usually be zero, of course (unless the truncation fails).