MySql query statement syntax error - mysql

I am getting a syntax error for the code below.
I am trying to create a user in the mysql database and add their information to a datagrid control all in one button click using two statements; one to create the actual user, and one to add the user and their additional information to a table on the database and then refresh the datasource which will display the new user's information in the datagrid control.
If anyone knows where i went wrong please feel free to critique my code and let me know; or simply offer more efficient alternatives to what im hoping to achieve.
For those of you that must know, i am running the latest version of MySql server, MySql Workbench, and Visual Basic 2010 Express on a windows 7 based laptop. I'm writing this program in VB.net.
Thanks!
Private Sub Button8_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button8.Click
Dim sqluser As MySqlCommand = New MySqlCommand(
"CREATE USER " & txtuser.Text & "#" & frmLogin.txtserver.Text & " IDENTIFIED BY '" & txtpass.Text & "';", con)
Dim sqlinfo As MySqlCommand = New MySqlCommand(
"INSERT INTO employee(Name ,Title) VALUES('" & txtname.Text & "','" & txttitle.Text & "';", con)
Try
con.Close()
con.Open()
sqluser.ExecuteNonQuery()
MessageBox.Show("User Account successfully created!!")
sqlinfo.ExecuteNonQuery()
' retrieving the administration table.
DataAdapter1.SelectCommand = sqladmin
DataAdapter1.Fill(ds, "stratos")
DataGrid1.DataSource = ds
DataGrid1.DataMember = "stratos"
con.Close()
MessageBox.Show("User Information successfully created!!")
Catch myerror As MySqlException
MessageBox.Show("Error Setting Up Account: " & myerror.Message)
End Try
End Sub

You are missing a ')' at the end of your insert statement.
Dim sqlinfo As MySqlCommand = New MySqlCommand("INSERT INTO employee(Name ,Title ) VALUES('" & txtname.Text & "','" & txttitle.Text & "');"
I would also like to point out that this code will fail if the text has an apostrophe in it, and that it is wide open to SQL Injection. Please read up.
I think you may also need apostrophes around the username and host.
CREATE USER '" & txtuser.Text & "'#'" & frmLogin.txtserver.Text & "' IDENTIFIED BY '" & txtpass.Text & "';"
As for SQL Injection, I would recommend you consider reworking your code to use prepared statements like this. Replace those first two lines with this instead. Basically, you put in little placeholders in your query, and let the database driver handle all of the complex escaping and quoting of things for you. I'm not 100% sure this will work, but I think it's close.
Dim sqluser As MySqlCommand = New MySqlCommand("CREATE USER ?user#?host IDENTIFIED BY ?pass;", con)
sqluser.Parameters.Add("?user", txtuser.Text)
sqluser.Parameters.Add("?host", frmLogin.txtserver.Text)
sqluser.Parameters.Add("?pass", txtpass.Text)
sqluser.Prepare()
Dim sqlinfo As MySqlCommand = New MySqlCommand("INSERT INTO employee(Name ,Title) VALUES( ?user, ?title );", con)
sqlinfo.Parameters.Add("?user", txtuser.Text)
sqlinfo.Parameters.Add("?title", txttitle.Text)
sqlinfo.Prepare()
It has been ages since I did any VB, so this is mostly based on this page. Try to look here if this doesn't quite work. Documentation on Prepare

Related

I get two error messages when trying to insert a data to MySQL table

I get these two error messages,
'ExecuteReader' is not a member of 'WindowsApplication1.MySqlCommand'
Too many arguments to 'Public Sub New()' {This error occurs in (query, conn) field}
Little explanation about what I am trying to do
Here I am trying to make an application that will input data to separate databases (Men, Women and Kids) using If pub = "" (pub is mentioned in another) Then according to ComboBox1 the table may get differ. According to the table the values need to be inserted.
This is the code I am using
Dim T As String
T = ComboBox1.Text
If pub = "Women" Then
conn = New MySqlConnection
conn.ConnectionString = "server=localhost;user=root;password=1234;database=women_clothing"
Dim reader As MySqlDataReader
Try
conn.Open()
Dim query As String
query = "INSERT INTO [" + T + "] VALUES ('" & TextBox1.Text & "','" & TextBox2.Text & "','" & TextBox3.Text & "','" & TextBox4.Text & "'," & Val(TextBox5.Text) & "," & Val(TextBox6.Text) & ");"
command = New MySqlCommand(query, conn)
reader = Command.ExecuteReader
MessageBox.Show("Data Saved")
conn.Close()
Catch ex As Exception
MessageBox.Show(ex.Message)
Finally
conn.Dispose()
End Try
loadtable()
ElseIf pub = "Men" Then
Else
End If
loadtable()
Thank You
You shouldn't use ExecuteReader for executing a statement that inserts data. ExecuteReader is for SELECT queries. ExecuteNonQuery is for INSERTs
Your code should look like:
Using conn = New MySqlConnection("server=localhost;user=root;password=1234;database=women_clothing")
Using cmd = New MySqlCommand("INSERT INTO tableName VALUES (#p1,#p2,#p3,#p4,#p5,#p6)", conn)
conn.Open()
cmd.Parameters.AddWithValue("#p1", TextBox1.Text)
cmd.Parameters.AddWithValue("#p2", TextBox2.Text)
cmd.Parameters.AddWithValue("#p3", TextBox3.Text)
cmd.Parameters.AddWithValue("#p4", TextBox4.Text)
cmd.Parameters.AddWithValue("#p5", TextBox5.Text)
cmd.Parameters.AddWithValue("#p6", TextBox6.Text)
cmd.ExecuteNonQuery()
End Using
End Using
I've also demonstrated how to use parameters; always use parameters. Your code as it stands is massively at risk of SQL injection attack hacking, and if that doesn't dissuade you enough to not write code in this way, bear in mind that your app will crash if anyone enters an apostrophe in one of your textboxes (which will then give the more astute tech whizzkids using it the idea that it's prone to injection hacking, then they will break into it) which looks bad to the end user (and makes them complain to your helpdesk/you).
It doesn't matter that "it's only a simple app for my grandma to index her vinyl collection" - this is about NOT learning a pattern of behavior that is plain risky, bordering on career-limiting if you want to take your coding skills into the software development world. As the VTech hack linked above shows, there are now 5 million images of children floating around out there whose parents never authorized their release, all because a few people didn't take proper precautions in doing their job. If any of my developers wrote an injection prone SQL, given the nature of one of the industries I work in, they'd just get fired.
Also, please get into the habit of renaming your textboxes after you add them to the form. It's incredibly difficult for anyone (yourself included, 6 months down the line) to have to constantly look up "hmm, what is the first name textbox? is it textbox2 or textbox3?" it takes about 2 seconds to type something new in the (Name) line of the property grid after you add the textbox to the form; firstNameTextBox is far better than textBox2
With credit to #Caius, this is a variation using ConnectionStringBuilder, a With block, a composite Using block and string interpolation, just for illustration.
NOTE the use of As in lieu of = when declaring the connection and command; this is to formally set the types rather than rely on Infer to determine them.
Dim connStr As New MySqlConnectionStringBuilder() With {
.Server = "localhost",
.Database = "women_clothing",
.UserID = "root",
.Password = "1234"
}
' -> "server=localhost;database=women_clothing;user id=root;password=1234"
Using conn As New MySqlConnection(connStr.ConnectionString),
cmd As New MySqlCommand($"INSERT INTO [{T}] VALUES (#p1, #p2, #p3, #p4, #p5, #p6)", conn)
conn.Open()
With cmd
.Parameters.AddWithValue("#p1", TextBox1.Text)
.Parameters.AddWithValue("#p2", TextBox2.Text)
.Parameters.AddWithValue("#p3", TextBox3.Text)
.Parameters.AddWithValue("#p4", TextBox4.Text)
.Parameters.AddWithValue("#p5", TextBox5.Text)
.Parameters.AddWithValue("#p6", TextBox6.Text)
.ExecuteNonQuery()
End With
conn.Close()
End Using

Im trying to insert a data into database using vb

I am trying to add a new data in mySql database using vb . But the error always says [unit_type] is not allowed to be null . I even changed the column's setting in the main database . I disabled the not null checkbox .
Dim datetoday = Date.Today
Try
command = "INSERT INTO assets_table ([date_created], [unit_type]) VALUES ('" & datetoday & "' , '" & frm_viewAssets.lbl_fetch.Text & "')"
Dim cmd As MySqlCommand = New MySqlCommand(command, myconn.open())
cmd.Parameters.Add(New MySqlParameter("date_created", CType(datetoday, String)))
cmd.Parameters.Add(New MySqlParameter("unit_type", CType(frm_viewAssets.lbl_fetch.Text, String)))
Try
cmd.ExecuteNonQuery()
cmd.Dispose()
myconn.close()
Catch ex As Exception
myconn.close()
End Try
You did the right thing by trying to use parameters but you did it wrong. You added the parameters to the command but, instead of using parameter place-holders in your SQL, you still inserted the literal values. This:
command = "INSERT INTO assets_table ([date_created], [unit_type]) VALUES ('" & datetoday & "' , '" & frm_viewAssets.lbl_fetch.Text & "')"
should be this:
command = "INSERT INTO assets_table ([date_created], [unit_type]) VALUES (#date_created, #unit_type)"
and then I think that you will need to add the "#" prefix to the parameter names when you create them as well.
Keep the database objects local so you can be sure they are closed and disposed. Using...End Using blocks will handle that for you even if there is an error.
Don't open the connection until directly before the .Execute.
I assumed the type of date_created to be a Date.
It can improve the efficiency of your sql to include the datatypes of your parameters.
If all you are doing in your Try/Catch is closing the connection you are just swallowing errors.
Private Sub OPCode()
Dim datetoday = Date.Today
Dim Command = "INSERT INTO assets_table ([date_created], [unit_type]) VALUES (#date_created , #unit_type);"
Using myconn As New MySqlConnection("Your connection string"),
cmd As New MySqlCommand(Command, myconn)
cmd.Parameters.Add("#date_created", MySqlDbType.Date).Value = datetoday
cmd.Parameters.Add("#unit_type", MySqlDbType.VarChar).Value = frm_viewAssets.lbl_fetch.Text
myconn.Open()
cmd.ExecuteNonQuery()
End Using
End Sub

Checking if the user is already registered

I'm trying to create a register for using mysql table as if username and pass is already added it output a msgbox saying you are already registered but what happen is that it always add it even if it already exists ..
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim cn As New SqlConnection
Dim cmd As New SqlCommand
Dim cmd2 As New SqlCommand
Dim dr As SqlDataReader
cn.ConnectionString = "Server=localhost;Database=test;Uid=sa;Pwd=fadyjoseph21"
cmd.Connection = cn
cmd.CommandText = "INSERT INTO test2(Username,Password) VALUES('" & TextBox1.Text & "','" & TextBox2.Text & "')"
cmd2.CommandText = cmd.CommandText = "SELECT username, password FROM test2 WHERE username = '" & TextBox1.Text & "' and password = '" & TextBox2.Text & "'"
cn.Open()
MsgBox("Registered")
cmd.ExecuteNonQuery()
dr = cmd.ExecuteReader
If dr.HasRows Then
MsgBox("You're already registered")
End If
End Sub
End Class
You never actually check to see if the username exists.
You define a query here:
cmd2.CommandText = cmd.CommandText = "SELECT username, password FROM test2 WHERE username = '" & TextBox1.Text & "' and password = '" & TextBox2.Text & "'"
But never execute that query. Instead, you just execute the INSERT query:
dr = cmd.ExecuteReader
So the INSERT is always performed. And since an INSERT doesn't return rows, you don't see the message box.
First thing's first, fix your SQL injection vulnerability. (Personal policy, I don't like writing SQL-injectable code in an answer.) Use query parameters instead of directly concatenating user input as code:
cmd2.CommandText = "SELECT * FROM test2 WHERE username = #Username"
cmd2.Parameters.Add("#Username", SqlDbType.VarChar, 50).Value = TextBox1.Text
dr = cmd2.ExecuteReader
If dr.HasRows Then
MsgBox("You're already registered")
Return
End If
Note a couple of things here:
The use of a query parameter. I had to guess on the type and size of the column in the database, adjust that as necessary.
Only executing this one query. Don't try to execute both queries at the same time, perform the first one and then perform the second one.
You don't need, or even want, to include the password in this query. You're checking if the username already exists, that's all.
Return after showing the message, so the rest of the function doesn't execute.
Then, after that is done, you can perform the INSERT operation:
cmd.CommandText = "INSERT INTO test2(Username,Password) VALUES(#Username,#Password)"
cmd.Parameters.Add("#Username", SqlDbType.VarChar, 50).Value = TextBox1.Text
cmd.Parameters.Add("#Password", SqlDbType.VarChar, 50).Value = TextBox2.Text
cmd.ExecuteNonQuery()
This will perform the INSERT operation. So if the Return above was never encountered then the username is unique and can be inserted.
Also: You should not be storing user passwords in plain text. This is grossly irresponsible to your users and exposes their private data to attackers. Instead, obscure the password with a one-way hash so that it can't be read in its original form.
A couple other things:
Use meaningful variable names. The whole reason you were having this problem was because you were getting confused between cmd and cmd2. If your variable names carry semantic meaning, your code is a lot easier to read and understand.
Make use of the Using block when you have disposable resources, such as a database connection. In general you want to open, use, and close a database connection in as small a scope as possible. Leaving open connections hanging around is a Bad Thing.
Add unique key constraint on username and hence when it already exist it will throw duplicate entry exception.
Secondly, never save plain text password in Database, it must be hasheh and encrypted. I would suggest to better use Bcrypt of atleast level 10 to generate hashed password and also use Bcrypt dynamic salt which is mostly preferred now.
Thirdly, always use parameterized query to avoid your program from mysql injection.
For example:-
Normal:
SELECT * FROM customers WHERE username = 'timmy'
Injection:
SELECT * FROM customers WHERE username = '' OR 1''

how can i open execuete a query in VB while there is reader opened?

is there any possible way to execute this without getting this error "There is already an open DataReader associated with this Connection which must be closed first." i already tried using "dr.close()" and i get another error that says "Invalid attempt to Read when reader is closed." can you help me out?
Heres my code:
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
Label2.Text = AllPicker1.Text
Label3.Text = AllPicker2.Text
If AllPicker1.Value >= AllPicker2.Value Then
MsgBox("End Date Must be Greater!")
Else
Dim SQLstatement As String = "SELECT * FROM tblStudInfo,tbl_studentLog WHERE tblStudInfo.StudID = tbl_studentLog.StudentNumber AND tbl_studentLog.LoginDate BETWEEN '" & AllPicker1.Text & "' AND '" & AllPicker2.Text & "'"
OpenData(SQLstatement)
End If
End Sub
Public Sub OpenData(ByRef SQLstatement As String)
Dim cmd As MySqlCommand = New MySqlCommand
With cmd
.CommandText = SQLstatement
.CommandType = CommandType.Text
.Connection = SqlConnection
dr = .ExecuteReader()
End With
While dr.Read
Dim SQLstatementSave As String = "INSERT INTO tbl_report (RepStudNo,RepName,RepCourse,RepDept,RepLogTime,RepLogdate) VALUES ('" & dr("StudID") & "','" & dr("Name") & "','" & dr("Course") & "','" & dr("Dept") & "','" & dr("LoginTime") & "','" & dr("LoginDate") & "') "
dr.Close()
Save(SQLstatementSave)
End While
SqlConnection.Close()
SqlConnection.Dispose()
SqlConnection.Open()
End Sub
Public Sub Save(ByRef SQLstatementSave As String)
Dim cmd As MySqlCommand = New MySqlCommand
With cmd
.CommandText = SQLstatementSave
.CommandType = CommandType.Text
.Connection = SqlConnection
.ExecuteNonQuery()
End With
SqlConnection.Close()
SqlConnection.Dispose()
SqlConnection.Open()
End Sub
End Class
It seems you are using only one SqlConnection. For most database systems you cannot reuse the connection while you are reading from it. You can either read all data into memory / DataTable and work on the rows after that or use a different SqlConnection for your Inserts.
When working with SqlConnections, Readers and Commands I find the Using Statement very helpful to visualize object usage and creation.
We can reduce this down to a single query:
INSERT INTO tbl_report
(RepStudNo,RepName,RepCourse,RepDept,RepLogTime,RepLogdate)
SELECT StudID, Name, Course, Dept, LoginTime, LoginDate
FROM tblStudInfo
INNER JOIN tbl_studentLog ON tblStudInfo.StudID = tbl_studentLog.StudentNumber
WHERE tbl_studentLog.LoginDate BETWEEN #StartDate AND #EndDate
Note the use of the full INNER JOIN syntax. The older TableA,TableB syntax for joins should be avoided. Also note the use of placeholders for your dates. This is important.
Now I need to draw attention to a couple functions I saw: OpenData(), and Save().
Those two functions are fundamentally broken, because they force you to build your queries in a way that leaves you vulnerable to sql injection hacking. Someday soon, someone will put a value like this into a textbox that is included with a query:
';DROP Table tbl_studentLog;--
Think carefully about what would happen now if someone entered that into your AllPicker1.Text. It would be hard to do that to a date picker, but I'll bet you have other plain text fields that would allow this. The first character (single quote) in my proposed input would close the string literal in the query. The second character (semi-colon) would end the individual statement, but sql server won't stop executing code. The next set of characters make up an additional statement that would drop your table. The final two characters comment out anything that follows, to avoid sql server rejecting or not committing the command because of syntax errors. Yes, Sql Server will run that additional statement, if that is what you put in a textbox.
So, your methods as written are broken, because the only accept completed sql strings as input. Any function that calls into the database MUST also include a mechanism for accepting query parameters. You ultimately want to be running code more like this:
Public Sub CreateReport(ByVal StartDate As DateTime, ByVal EndDate As DateTime)
Dim sql As String = _
"INSERT INTO tbl_report " & _
" (RepStudNo,RepName,RepCourse,RepDept,RepLogTime,RepLogdate) " & _
" SELECT StudID, Name, Course, Dept, LoginTime, LoginDate " & _
" FROM tblStudInfo " & _
" INNER JOIN tbl_studentLog ON tblStudInfo.StudID = tbl_studentLog.StudentNumber " & _
" WHERE tbl_studentLog.LoginDate BETWEEN #StartDate AND #EndDate"
'.Net is designed such in most cases that you really do want a new SqlConnection for each query
'I know it's counter-intuitive, but it is the right way to do this
Using cn As New SqlConnection("Connection string"), _
cmd As New SqlCommand(sql, cn)
'Putting your data into the query using parameters like this is safe from injection attacks
cmd.Parameters.Add("#StartDate", SqlDbType.DateTime).Value = StartDate
cmd.Parameters.Add("#EndDate", SqlDbType.DateTime).Value = EndDate
cn.Open()
cmd.ExecuteNonQuery()
End Using
End Sub
One thing to point out here is that at first glance I don't close the connection. However, the Using block will ensure that the connection is closed promptly... even if an exception is thrown. Your existing code will leave the connection hanging in the case of a exception.
Also note that this neatly side-steps the whole issue of needing to execute a separate query while your reader is opened... but if you ever do really need to do this (it's rare), the answer is simple: use a separate connection.
Instead of:
Dim SQLstatementSave As String = "INSERT INTO tbl_report
(RepStudNo,RepName,RepCourse,RepDept,RepLogTime,RepLogdate)
VALUES ('" & dr("StudID") & "','" & etc.
Try using .ToString on your DR() references.
Dim SQLstatementSave As String = "INSERT INTO tbl_report
(RepStudNo,RepName,RepCourse,RepDept,RepLogTime,RepLogdate)
VALUES ('" & dr("StudID").ToString & "','" & etc.

Standard SQL SELECT * FROM TABLE return syntax error

I keep getting an error saying "there is an error in your sql syntax." when i use this sql statement:
SELECT * FROM gsm_oceanwide_integration
EDIT:
To put this in context heres the code im using this query statement in (VB.net):
Dim con As MySqlConnection = New MySqlConnection("Data Source=" & frmLogin.txtserver.Text & ";Database=stratocast;User ID=" & frmLogin.txtusername.Text & ";Password=" & frmLogin.txtpassword.Text & ";")
Dim sqladmin As MySqlCommand = New MySqlCommand("SELECT * FROM employee", con)
Dim sqlprojects As MySqlCommand = New MySqlCommand("SELECT * FROM projects", con)
Dim sqlpage As MySqlCommand = New MySqlCommand("SELECT * FROM '" & frmMain.ListBox1.SelectedItem & "';", con)
Dim ds5 As DataSet = New DataSet()
Dim DataAdapter5 As MySqlDataAdapter = New MySqlDataAdapter()
Dim Comb As MySqlCommandBuilder
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' retrieving the Project Page.
Try
con.Open()
DataAdapter5.SelectCommand = sqlpage
DataAdapter5.Fill(ds5, "stratocast")
DataGridView3.DataSource = ds5
DataGridView3.DataMember = "stratocast"
con.Close()
Catch myerror As MySqlException
MessageBox.Show("Error Retrieving Project Page: " & myerror.Message)
End Try
End Sub
on my frmMain form i have a listbox with a list of projects (one of them being gsm_oceanwide_integration) and i want to make it so that when i click on that selection it will display another form with a datagridview. this datagridview needs to be filled with data from the table i called gsm_oceanwide_integration. (like the listbox selection)
so my current query statement (including vb.net tags) is:
Dim sqlpage As MySqlCommand = New MySqlCommand("SELECT * FROM '" & frmMain.ListBox1.SelectedItem & "';", con)
It was working earlier today, but i must have changed something in it and forgot...
since then the best i can do is get rid of all the errors but the datagridview still won't display anything on my database. Yes, i've checked all the spelling.
UPDATE 2:
I changed my sqlpage command statement from:
Dim sqlpage As MySqlCommand = New MySqlCommand("SELECT * FROM '" & frmMain.ListBox1.SelectedItem & "';", con)
To:
Dim sqlpage As MySqlCommand = New MySqlCommand("SELECT * FROM [" & Me.ListBox1.SelectedItem.Value & "]", con)
and i got a new error on another form all together but it's linked to the listbox1; the code for which is below:
Private Sub ListBox1_SelectedValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ListBox1.SelectedValueChanged
Form1.indprojectname.Text = ListBox1.SelectedItem
Form1.Show()
End Sub
The error is shown in this screenshot (i thought a screen shot might be the best method for displaying the error details):
the error is: (in case you couldn't read the screenshot)
An error occurred creating the form. See Exception.InnerException for details. The error is: Object variable or With block variable not set.
Also, thanks for the quick replies, sorry i couldn't update my post sooner...
Thanks!
How about the single quote before your double quote around the table name coming in from your listbox? That should not be there. You have:
Dim sqlpage As MySqlCommand = New MySqlCommand("SELECT * FROM '" & frmMain.ListBox1.SelectedItem & "';", con)
It should be:
Dim sqlpage As MySqlCommand = New MySqlCommand("SELECT * FROM " & frmMain.ListBox1.SelectedItem & ";", con)
Steer clear of any adding special characters in your table names or field names. Stick to a convention such as...
myFieldName - known as camel casing or...
my_field_name - just use underscores
As for the sql statement I can't see anything immediately wrong with it. Is the table name correct?
Regarding your query about spaces in table names:
Short Answer - yes but no
However, I would take a look at the MySQL documentation on Schema Object Names
Also as mentioned in the comments, spaces are allowed as a table indentifer using quoted indentifiers but I would not encourage the use of them, mainly for readability reasons.
As for your query, would require more information, such as your list of tables.