Date in SQL string from DateTimePicker - sql

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.

Related

What can be written in exchange of Oledb.parameters.AddwithValue() to add a Parameter to a Command?

I am been told that cmd.Parameters.AddWithValue is not good and we should write cmd.Parameters.Add instead.
Some of the link referred to me are :
Link 1 and Link 2.
I referred the link but the link gave examples with SQL Connection. I am using Oledb Connection everywhere. And .Add don't work properly with Oledb Connection.
On digging on stack overflow and other sites I found that almost everyone using .AddWithValue. Some used .Add and I tried their method and got error like "Must declare a scalar variable.". Again searching the error gives result to use .AddWithValue
I am currently using parameters like this
cmd = New OleDbCommand("INSERT INTO TABLE (Col1,Col2,Col3)
VALUES('" & ColVal1 & "','" & ColVal2 & "',?)", con1)
'With cmd.Parameters
' .Add(New OleDbParameter("#Trans_Date", TransDate))
' '.Add(New OleDbParameter("#Password", txtPassword.Text))
'End With
cmd.Parameters.AddWithValue("#Col3", OleDbType.Date).Value = TransDate
And it works fine for me.
So what should I use and How?
That code is wrong. When you call AddWithValue, the second argument is the value and the data type is inferred from that. If you were going to call AddWithValue then it would look like this:
cmd.Parameters.AddWithValue("#Col3", TransDate)
The reason that you should call Add instead is that it may occur that the inferred data type does not match what the database actually needs and that can cause problems on some occasions. Your code is the right pattern but should be calling Add rather than AddWithValue:
cmd.Parameters.Add("#Col3", OleDbType.Date).Value = TransDate
As it is, you are creating a parameter with a value of OleDbType.Date and a data type inferred from that, then you explicitly set the Value to TransDate. That's wrong.
Also, the whole point of using parameters is to avoid the issues that can arise form string concatenation and you're using string concatenation anyway. Don't! Use parameter EVERY time:
cmd = New OleDbCommand("INSERT INTO MyTable (Col1, Col2, Col3) VALUES (#Col1, #Col2, #Col3)", con1)
With cmd.Parameters
.Parameters.Add("#Col1", OleDbType.VarChar).Value = ColVal1
.Parameters.Add("#Col2", OleDbType.VarChar).Value = ColVal2
.Parameters.Add("#Col3", OleDbType.Date).Value = TransDate
End With

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.

VB Access DB Update statement

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.

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)

ado in excel, inserting records into access database

First time asker, usually I can find the answer by searching, but my google-fu seems weak today.
I have an excel workbook connecting to an access 2003 database to insert usage records
The code i'm using is:
sdbpath = ThisWorkbook.Path & "\Data.mdb"
sCommand = "INSERT INTO Usage VALUES('" & Environ("Username") & "',#" & Now() & "#)"
Dim dbCon As New ADODB.Connection
Dim dbCommand As New ADODB.Command
dbCon.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & sdbpath & "; Jet OLEDB:Database Password=TestPass;"
dbCommand.ActiveConnection = dbCon
dbCommand.CommandText = sCommand
dbCommand.Execute
dbCon.Close
The code fails on the line dbCommand.Execute with run-time error '-2147217900 (80040e14)' : Automation error.
The database its trying to insert the record into contains one table, usage, with two columns - UserID and AccessDate, formatted as text and DateTime respectively.
The odd part is the connection string seems OK, since it fails after the connection is already open, yet if I take the sCommand value before the execute is run, then paste it into a query in access and execute that - it runs fine!
In case it was access struggling with the datetime format i've tried switching it to text (and the hashtags in the code) but that still fails. I've also tried specifying the column names too.
Can anyone shed some light on what i'm doing wrong? I've never had so much trouble with a very simple bit of SQL.
Thanks in advance!
In Access we need to specify the field-names. Even so, I found that I needed to wrap the table-name in square brackets before it would insert:
sCommand = "INSERT INTO [Usage] (UName, SomeDate) VALUES ('" & Environ("Username") _
& "',#" & Now() & "#)"