there is always an error...don't know why - vb.net

i think my Insert into/ syntax is correct, but when i run the project there is always an error...
in this code i'm trying to add data to my database ms access 2013 using vb2012
here the code...
Private Sub btnadd_Click(sender As Object, e As EventArgs) Handles btnadd.Click
provider = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="
dataFile = "C:\Users\hp-2\Documents\Visual Studio 2012\Projects\Delta\Delta.mdb"
connString = provider & dataFile
cnn.ConnectionString = connString
cnn.Open()
cmd.Connection = cnn
addstring = "insert into Transaction (Customer_Name, Job, Trans_date, Amount ) values (" & C_name.Text & ",'" & C_job.Text.Length & "','" & t_date.Text & "','" & t_amount.Text & "');"
cmd = New OleDbCommand(addstring, cnn)
cmd.ExecuteNonQuery()
cnn.Close()
End Sub
this is the error...
An unhandled exception of type 'System.Data.OleDb.OleDbException' occurred in System.Data.dll
Additional information: Syntax error in INSERT INTO statement.

I think if the problem were due to incorrect quoting in the VALUES clause, you would get a different error, either "data type mismatch in criteria expression", or a message that the db engine expected a parameter value but you supplied none.
My guess is the syntax error is due to the fact that Transaction is a reserved word. See whether it works when you enclose the table name in square brackets.
insert into [Transaction] (Customer_Name, Job, ...
If that change eliminates the error, I don't think you should stop there. Switch to a parameter query, as others suggested, instead of building values into a string and executing the string. In addition to protection against SQL injection errors, a parameter query would avoid complications with quotes in the VALUES clause. And if you follow that advice, you should still bracket [Transaction]. Better still, change the table name to a non-reserved word if possible.

while it's essential to put single quote to the Name ('" & C_name.Text & "'), guess your amount is not a varchar column, so probably you could take the single quote away for that field.
the best way to debug this is watch the insert command (string value) generated and check whether there is any syntax error compared to your table design.

The customer_name is not in quote. You are also passing .Length, which I don't think it what you want to do.
Most importantly, you should put everything in parameters.
addstring = "insert into Transaction (Customer_Name, Job, Trans_date, Amount ) values (#Customer_Name, #Job, #Trans_date, #Amount);"
cmd = New OleDbCommand(addstring, cnn)
cmd.Parameters.AddWithValue("#Customer_Name", C_name.Text)
cmd.Parameters.AddWithValue("#Job", C_job.Text)
cmd.Parameters.AddWithValue("#Trans_date", Convert.ToDateTime(t_date.Text))
cmd.Parameters.AddWithValue("#Amount", Convert.ToInt32(t_amount.Text))

Related

What have I missed out with regards to the syntax of the SQL statement?

I am writing code to insert a username and password into a database called Users.
When I try to run the code it says there is an error in the INSERT statement's syntax but I cannot for the life of me find it.
I am running the SQL statement using another function called RunSQL that I can submit if need be but its worked fine with every other SQL statement I have run with it.
The Users table has the following columns with their data type
User_ID - Auto Number (Primary Key)
Username - Short Text
Password - Short Text
I have tried adding ' ' around the values I am going to insert into the table as well as removing the & and making it one continuous string. I have tried adding / removing the ; but nothing has worked.
Dim sql As String = "INSERT INTO Users (Username, Password) " &
"VALUES (" & username_Textbox.Text & " , " & password_Textbox.Text & ");"
RunSQL(sql)
MessageBox.Show("User Added")
Private Sub RunSQL(ByVal sql As String)
Dim conn As OleDbConnection = New
OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Paper_Gen_Database.accdb;")
conn.Open()
Dim cmd As New OleDbCommand(sql, conn)
cmd.ExecuteNonQuery()
System.Threading.Thread.Sleep(500)
End Sub
The code should take the values from the username and password textboxes and insert them into the Users table but so far it has only thrown back an SQL error.
This is what the SQL statement looks when with "bh106" being the Username and "ZLTga" being the Password
This is one way to use parameters. It is very important to use parameters because otherwise you risk SQL injection which can ruin your database. It is actually much easier to write the SQL statement this way because you don't have to worry about if you have all your quotes in the string correctly.
The Using...End Using blocks ensure that your database objects are closed and disposed even if there is an error. This is important because it releases any unmanaged resources being used.
In a real application you would never save passwords as plain text but that is a subject for another day.
Private Sub InsertUser()
Dim sql As String = "INSERT INTO Users (Username, [Password]) VALUES (#username, #password);"
Using conn As OleDbConnection = New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Paper_Gen_Database.accdb;")
Using cmd As New OleDbCommand(sql, conn)
cmd.Parameters.Add("#username", OleDbType.VarChar).Value = username_Textbox.Text
cmd.Parameters.Add("#password", OleDbType.VarChar).Value = password_Textbox.Text
conn.Open()
cmd.ExecuteNonQuery()
End Using
End Using
MessageBox.Show("User Added")
End Sub
In Access the order that the parameters are added must match the order that they appear in the SQL statement.
Try this (its probably because of lack of quotes, and also because password is protected word):
Dim sql As String = "INSERT INTO Users (Username, [Password]) " &
"VALUES ('" & username_Textbox.Text & "' , '" & password_Textbox.Text & "');"
RunSQL(sql)
MessageBox.Show("User Added")
Also be aware of sql injection problem.
If a user will put a quote inside a textbox, insert will still fail.
You should try converting your code into parametrized query, example:
https://learn.microsoft.com/pl-pl/dotnet/api/system.data.oledb.oledbcommand.parameters?view=netframework-4.7.2

Having an issue inserting data into Postgresql using Npgsql and VB.net

Can someone please look at my code and possibly point me to why it is not allowing me to insert data into my Postgres database? I'm creating a Comic Book database for my collection.
Everytime I click my submit button to submit the data entered, the debugger throws an exception:
'An unhandled exception of type 'Npgsql.PostgresException' occurred in Npgsql.dll'
Which happens on the execution of myCommand.ExecuteNonQuery() function.
I've spent my day trying to figure this out, I am a complete noob at this. Any guidance would be awesome!
Dim myConnection As NpgsqlConnection = New NpgsqlConnection()
Dim myCommand As NpgsqlCommand
Dim mySQLString As String
myConnection.ConnectionString = "Server=localhost;Port=5432;Database=ComicsDatabase;User Id=postgres;Password=xxxxxxxx;"
mySQLString = "INSERT INTO Comics (IssueName,IssueNumber,PublicationDate,Publisher,IsVariant) VALUES (" & comicName & "," & issueNumber & "," & publicationDate & "," & publisher & "," & isVariant & ");"
myCommand = New NpgsqlCommand(mySQLString, myConnection)
myConnection.Open()
myCommand.ExecuteNonQuery()
myConnection.Close()
When you concatenate strings as above to form your sql command it is very easy to fall in common errors. In your code, for example, a string value should be enclosed between single quotes.
So, supposing that IssueName is a string type field, you should express the value in this way
.... VALUES ('" & comicName & "'," & ....
But this is a remedy worse than the illness. First you will have another problem if your comicName variable contains a single quote, second the concatenation of strings is the main way that leads to Sql Injection (a very dangerous code vulnerability)
The only correct way to pass a value to a database engine (...any database engine of this world) is through a parameterized query
You write the query putting parameter placeholders instead of directly the values
(No string concatenation, no weird & and single quotes....)
mySQLString = "INSERT INTO Comics
(IssueName,IssueNumber,PublicationDate,Publisher,IsVariant)
VALUES (:comicName,:issueNumber,:publicationDate,:publisher,:isVariant);"
And then you pass the value using a parameter added to the command parameters collection
myCommand = New NpgsqlCommand(mySQLString, myConnection)
myCommand.Parameters.Add(":comicName", NpgsqlDbType.Varchar).Value = comicName
Of course you need to add all the other parameters required by the placeholders, the important thing to keep in mind is to use the correct NpgsqlDbType for the specific column that you are trying to update.

Update button error

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

Date in SQL string from DateTimePicker

I am trying to insert a date from a DateTimePicker in a Windows Form in VB.Net into an SQL string in such a way as it recognises it as a datetime (the field itself is set as datetime in SQL Server).
I have tried a few methods (Convert at SQL level, Format at VB.Net level) and am now using a variable stored as DateTime, however I still cannot get it to work. A snippet of my code is below:
Using sqlConn = New SqlConnection(My.Settings.sqlString)
sqlConn.Open()
Dim dte As DateTime = Convert.ToDateTime(Me.dateMain.Text)
Dim cmd As SqlCommand
cmd = sqlConn.CreateCommand
cmd.CommandText = "Update Table1 " &
"SET Person='" & Me.person.Text & "'," &
"Date='" & dte & "' " &
"WHERE (Code = '" & PCode & "')"
cmd.ExecuteNonQuery()
cmd = Nothing
End Using
EDIT:
The following error (or slight variation of) is what I have got with almost every attempt I have tried. This error was received after the Parameterization answer submitted below
An unhandled exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll
Additional information: The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value.
So it seems that even still, it is not recognising it as a datetime in SQL. I imagine I will need to try again with Convert in the SQL string, but my knowledge of the function is limited. Anyone know how I can use it to get this to work (if that is the solution)?
Sounds like a job for parameterization!
Using sqlConn = New SqlConnection(My.Settings.sqlString)
sqlConn.Open()
Dim cmd As SqlCommand
cmd = sqlConn.CreateCommand
cmd.CommandText = "Update Table1 " &
"SET Person = #person, " &
"Date = #dte " &
"WHERE (Code = #code)"
cmd.Parameters.AddWithValue("#person", Me.person.Text)
cmd.Parameters.AddWithValue("#dte", Me.dateMain.Value)
cmd.Parameters.AddWithValue("#code", PCode)
cmd.ExecuteNonQuery()
cmd = Nothing
End Using
And while you're at it, I don't want to change too much because I've never written a line of VB in my life (so this also may or may not be right, let me know if it doesn't compile or something, but this is the gist), but SqlCommand does implement IDisposable, so you should probably wrap that in a Using as well.
Parameterizing your queries will eliminate bugs like you've come across, promote code reuse, and arguably most importantly, stop SQL Injection attacks. Please always use parameters, for all our sakes.
You can use the ISO 8601 format (YYYY-MM-DDThh:mm:ss[.mmm] or YYYYMMDD hh:mm:ss[.mmm]) or use the unseparated format(YYYYMMDD hh:mm:ss[.mmm]). Both should work fine.
Parameterized query is still better though.

Problems with MS Access update statement

This is my code i'm trying to update table via VB forms , I don't know what the wrong with it please help me.
This is the table:
Dim con As New OleDbConnection("provider=microsoft.ace.oledb.12.0; data source = |datadirectory|\Studen.accdb;")
con.Open()
Dim sql As String = "Update tend set StudentName='" & TextBox9.Text & "', LessonDate='" & TextBox13.Text & "', LessonTime=" & TextBox10.Text & ", Payment=" & TextBox11.Text & ", Note='" & TextBox12.Text & "' where ID=" & TextBox8.Text
Dim cmd As New OleDbCommand(sql, con)
cmd.ExecuteNonQuery()
con.Close()
The first problem is the field named NOTE. This is a reserved keyword in MS-Access and, if you want to use it, you need to encapsulate the word with square brackets
Dim sql As String = "Update tend set StudentName=...., [Note]=..."
but this is not the only problem here. A much bigger one is the string concatenation used to build the sql command. This approach leads to possible sql injections and problems in propertly quoting the values used to prepare the statement. Strings need to be examined to duplicate single quotes, decimals need to be passed with the proper decimal point, dates need to be encapsulated in the # symbol and so on....
A better way is using a parameterized query
Dim sql As String = "Update tend set StudentName=?, LessonDate=?, LessonTime=?, " & _
"Payment=?, [Note]=? where ID=?"
Using con = New OleDbConnection(...........)
Using cmd = New OleDbCommand(sql, con)
con.Open()
cmd.Parameters.AddWithValue("#p1", TextBox9.Text)
cmd.Parameters.AddWithValue("#p2", Convert.ToDate(TextBox13.Text))
cmd.Parameters.AddWithValue("#p3", Convert.ToInt32(TextBox10.Text))
cmd.Parameters.AddWithValue("#p4", Convert.ToDecimal(TextBox11.Text))
cmd.Parameters.AddWithValue("#p5", TextBox12.Text)
cmd.Parameters.AddWithValue("#p6", Convert.ToInt32(TextBox8.Text))
cmd.ExecuteNonQuery()
End Using
End Using
In a parameterized query, like the one above, you put placeholders (?) in the query text and supply the values with the Parameters collection of the command. In this way, the work to properly quote every single value is passed to the framework and db engine. They know better than you and me how to properly quote the parameters.
Note how the AddWithValue method infers the correct datatype to use for the parameter looking at the datatype of value passed. If your LessonDate field is a field with DateTime type then you need to convert the textbox text (a string) to a date. This could cause an exception if you don't check before trying the conversion. (Here I assume that you have something in place to ensure valid inputs). The same reasoning should be applied to the other NON text fields. (ID, LessonTime, Payment)