-1

I'm doing a windows form using Visual Basic.NET, SQL Server 2016, Visual Studio 2017.

I have been trying to fix this problem and already tried set dateformat mdy in SQL Server Management Studio query, but the dates on the table I have are still in this format: 2022-07-17 00:00:00.000. Does this have anything to do with this error when trying to insert something while running the project?

Everyone says stuff along the line "datetime doesn't work with yy/mm/dd or dd/mm/yy, use mm/dd/yy instead". But nobody says how you actually change/fix it in the database or Visual Studio.

I never found this error while using MySQL when I was studying and doing stuff on other languages, so this datetime thing is really getting desperate. Any insight on how to actually fix this error is greatly appreciated.

Code:

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim someid As Integer = TextCode.Text
            Dim descri As String = TextDescription.Text
            Dim somedate As DateTime = DateTimePickerinsert.Text
            Dim value As String = TextValue.Text
            Dim stock As String = TextStock.Text
            Dim warehouse As String = ComboWarehouse.Text
    
            con.Open()
            Dim command As New SqlCommand("Insert into Item values('" & someid & "','" & descri & "','" & somedate & "','" & value & "','" & stock & "','" & warehouse & "')", con)
            command.ExecuteNonQuery()
            con.Close()
            MessageBox.Show("Inserted succesfully")
            LoadDataInGrid()
        End Sub

I get

System.Data.SqlClient.SqlException: 'The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
The statement has been terminated.' error on the line: command.ExecuteNonQuery()

Dale K
  • 25,246
  • 15
  • 42
  • 71
  • 3
    Please show relevant code. If you are sending values from VB then your issue is almost certainly that you should be using `datetime` parameters, which don't have formats, they are passed as binary values. *"the dates on the table I have are still in this format"* as I said, dates don't have a format, that's just how they are being displayed. – Charlieface Jul 17 '22 at 19:44
  • 1
    You are using a varchar (or string literal) somewhere where you shouldn't. Everything becomes easy and all these datetime format issues magically disappear, if you just *never* store dates as strings and *always* store them using the appropriate types. Somewhere in your code, you (inadvertently) violate this rule and use a string. If you create a [mcve], we can show you where. – Heinzi Jul 17 '22 at 19:46
  • 3
    Well… the answer is don’t do a conversion . Store dates as dates, use the appropriate data types right though out your application and save the headaches of type conversion – Hursey Jul 17 '22 at 19:46
  • @Heinzi I edited the Question with the insert code and the exact line I get the error, hope it helps. When you say I'm using varchar somewhere where I shouldn't you mean on the db or in the code? How exactly do you fix this error? – spiritedHunter Jul 17 '22 at 20:15
  • 1
    If you parametrise this problem will likely disappear. Your code is wide open to injection attacks, and is the cause for the error. There is no excuse to write such code any more; the dangers of SWL Injection are a very well known issue. – Thom A Jul 17 '22 at 20:28
  • @Hursey I don't want to do a conversion lol, I just created the column of the date with the datetime type as I was asked to. Is it a problem on the code itself? I edited my question to add the declaration of variables, if it helps, but I still don't get what is the problem or how to actually fix it. – spiritedHunter Jul 17 '22 at 20:33
  • 1
    You might not want to do a conversion, but you are. Charlieface has given you a fairly solid answer, the only thing I would add to this is turning Option Strict on. If it was on you would of almost certainly been warned about this problem by the complier. – Hursey Jul 17 '22 at 20:45
  • `2022-07-17 00:00:00.000` <-- this format is ambiguous, because some languages will interpret it as `yyyy-dd-MM` (in fact more than half of the languages SQL Server supports). In addition to the other suggestions, I'd ensure your datepicker composes a format that is _NOT_ ambiguous, like `2022-07-17T00:00:00.000` or `20220717 00:00:00.000` or - if no time is involved - `20220717`. I talk about this in multiple links [here](https://sqlblog.org/dates#format). – Aaron Bertrand Jul 17 '22 at 22:06

3 Answers3

5

You should use proper parameterization, keeping your dates as actual DateTime values, rather than strings, likewise for numbers. Otherwise you will get SQL injection problems, this is not just a security issue but also about correctness.

The parameter values should be cast to the correct type before you send them, and the parameter objects should be declared with the correct SqlDbType and precision/length also.

You should also create and dispose your connection object, rather than keeping a global connection open, which is wasteful. Automatic connection pooling will ensure efficient usage of available connections.

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim query As String = "
INSERT INTO Item (someid, descri, somedate, value, stock, warehouse)
VALUES (@id, @description, @date, @value, @stock, @warehouse)
"
    Dim someid As Integer = Integer.Parse(TextCode.Text)
    Dim somedate As DateTime = DateTimePickerinsert.Value
    Dim value As Decimal = Decimal.Parse(TextValue.Text)
    Dim stock As Integer = Integer.Parse(TextStock.Text)
    
    Using con As new SqlConnection("YourConnectionString"),
        command As New SqlCommand(query, con)
        command.Parameters.Add("@id", SqlDbType.Int).Value = someid
        command.Parameters.Add("@description", SqlDbType.VarChar, 100).Value = If(TextDescription.Text, DBNull.Value)
        command.Parameters.Add("@date", SqlDbType.DateTime).Value = somedate
        command.Parameters.Add("@value", SqlDbType.Decimal).Value = value
        command.Parameters.Add("@stock", SqlDbType.Int).Value = stock
        command.Parameters.Add("@warehouse", SqlDbType.VarChar, 50).Value = If(ComboWarehouse.Text, DBNull.Value)
        con.Open()
        command.ExecuteNonQuery()
    End Using
    MessageBox.Show("Inserted succesfully")
    LoadDataInGrid()
End Sub

As far as viewing the results in SSMS: datetime values don't have an inherent format. SSMS will have a default way of displaying them, but you can show them any way you like by converting them using CONVERT, or in VB using ToString

Charlieface
  • 52,284
  • 6
  • 19
  • 43
  • Thanks for your answer. I'm trying to change it in my code but it seems you only declared 4 of the original 6 variables, Am I right? Other than that, you say it's better to put the main connectionString (Using con As new SqlConnection("YourConnectionString").........) for every "Button" ? Like on insert, update, search and delete rather than what I had (my SqlConnection string in the beginning just under the "Public Class Form1" line? I noticed you also didn't close the connection as I had it. – spiritedHunter Jul 17 '22 at 22:10
  • 1
    Yes I didn't bother with the ones that were anyway `String` I just did those inline. You could do the whole `Integer.Parse` inline also, but maybe easier this way so you can do other checks. Yes, a new connection on each function, do not cache the connection object, see also https://stackoverflow.com/questions/17552829/c-sharp-data-connections-best-practice. You don't need to call `.Close` because you have `Using` which sorts that out, see also https://stackoverflow.com/a/18588084/14868997, *always always* have a `Using` otherwise you may leak the connection if there is an exception. – Charlieface Jul 17 '22 at 22:14
  • "I just did those inline. " meaning you put them? – spiritedHunter Jul 17 '22 at 23:18
  • For example `command.Parameters.Add("@description", SqlDbType.VarChar, 100).Value = TextDescription.Text` I didn't bother with an intermediate variable – Charlieface Jul 17 '22 at 23:31
  • Thanks for everything but your code messed my variables so bad when I only wanted to fix the date one. I can't "accept" the answer. Bye. – spiritedHunter Jul 18 '22 at 03:34
  • 2
    *"I only wanted to fix the date one"*. That is the wrong approach. You should ALWAYS use parameters. This answer demonstrates how to do that. Learn from the example, understand the principle and then apply it to ALL the values. If you do things by halves then you'll be back later asking the same question that has already been answered here. Just do it properly and it well work. If you're trying to implement this and having issues then update your question and show us what you tried and we can then help you fix what you did wrong. – John Jul 18 '22 at 06:29
  • 1
    @spiritedHunter The only way you could have gotten that error is if you did not actually pass the `@description` parameter (or if it was `null`, then instead you need to pass `DBNull.Value`). I didn't "mess" your variables, I showed you how to pass them in as parameters, instead of concatenating them and causing SQL injection. See also https://stackoverflow.com/questions/7505808/why-do-we-always-prefer-using-parameters-in-sql-statements – Charlieface Jul 18 '22 at 08:11
  • 1
    @spiritedHunter: "*I only wanted to fix the date one*" Please reconsider. The problem is that your strings are broken as well: Your SQL will fail if you try to enter a description that contains `'`. I work with VB.NET on a daily basis since the very first version in 2002, and, trust me, parameters are the only correct way to do this. Here's another related question explaining how to use parameterized SQLs: https://stackoverflow.com/q/35163361/87698 – Heinzi Jul 18 '22 at 10:36
0

You are seriously entertaining SQL Injection using that Code. You don't directly insert data to SQL database from your Windows Controls.

Use SQL Connection Parameters to house the values. That way, any text in the incoming data will not be evaluated as a SQL Script but a text literal.

Hackers could assign SQL Script to your TextDescription.Text like "Exec 'Delete From XXX '" and it will be executed.

Dim descri As String = TextDescription.Text

Use SQL Connection Parameters to house the values.

-3

You may run into many issues while using strings as dates. If you are connecting to a stored procedure or just executing SQL via SqlClient or ODBC, one way to fix this error is to use Cast in your SQL string to convert the date string to something that the server will understand. ex:

Insert Into MyTable (MyID, MyDate) Values (@MyID, Cast(@MyDate as datetime));

or,

Insert Into MyTable (MyID, MyDate) Values (123, Cast('2022-03-14 14:12:00' as datetime));

It will be more forgiving on different formats that you might use.

S. MacKenzie
  • 210
  • 2
  • 5