将日期保存到SQL Server表

时间:2016-01-09 09:05:16

标签: sql-server vb.net

我使用以下命令为变量设置日期值:

    Dim someDate As DateTime = Date.Today.AddDays(1) 

    nextMonday = someDate
    While nextMonday.DayOfWeek <> DayOfWeek.Monday
        nextMonday = nextMonday.AddDays(1)
    End While

然后我使用以下内容将日期插入SQL Server表:

   Private Sub CButton1_ClickButtonArea(Sender As Object, e As MouseEventArgs) Handles CButton1.ClickButtonArea
    Dim doenditstring As String = "INSERT INTO Parsversoeke (ma_datum,di_datum)  " & _
                                     "VALUES (" & _
                                       "'" & nextMonday & "'," & _
                                     "'" & nextTuesday & "')" 

    cnn.Open()
    Dim aksie As New SqlClient.SqlCommand(doenditstring, cnn)

    aksie.ExecuteNonQuery()

    cnn.Close()

它有效,但我只能在两个日期之前完成。之后我收到以下错误:

  

从字符串

转换日期和/或时间时转换失败

有没有人知道我为什么会收到错误?

1 个答案:

答案 0 :(得分:6)

不,这种连接字符串的方法从一开始就注定要失败 您会收到语法错误,转换错误以及可能Sql Injection Attacks

  • 语法错误:严格来说不是这种情况,但如果用作字符串 一个值包含单引号,然后是整个连接字符串 语法无效
  • 转换错误:您不必担心如何准备数据 可以接受作为数据库的输入。十进制怎么样? 分离?你应该使用一个点还是一个逗号?这取决于区域设置 数据库的设置,如果它是在不同的文化上你的 代码很快会变得一团糟,无用的替换或者 的ToString
  • Sql Injection:同样,这里没有严格的参与,而是采取任何措施 您的用户键入并直接将其用作查询的一部分 真的是一个很大的错误,可能会给您的客户带来很多损失。见 上面的链接

只有一种方法可以解决这个问题。 Parameterized queries

Private Sub CButton1_ClickButtonArea(Sender As Object, e As MouseEventArgs) Handles CButton1.ClickButtonArea
    Dim doenditstring As String = "INSERT INTO Parsversoeke " & _
                                  "(ma_datum,di_datum)  " & _
                                  "VALUES (@m, @t)"

    cnn.Open()
    Dim aksie As New SqlClient.SqlCommand(doenditstring, cnn)
    aksie.Parameters.Add("@m", SqlDbType.Date).Value = nextMonday     
    aksie.Parameters.Add("@t", SqlDbType.Date).Value = nextTuesday 
    aksie.ExecuteNonQuery()
    cnn.Close()
End Sub

在您的代码中,您要求编译器将DateTime变量转换为字符串并执行请求的任务,但它不知道此字符串将执行sql命令。当然,您可以使用ToString和格式给它一个强烈的提示,但是您打算在数据库本身上根据其转换规则将该字符串转换回数据时间。最后,为什么要允许所有这些转换?参数可以减轻你的代码。

注意,现在,您的命令文本如何更清晰,正确传递值的工作是由ADO.NET引擎本身(及其SqlClient类)完成的,他们更了解如何为数据库准备DateTime变量。

我还应该解决您的代码中清晰可见的另一个问题。有一个全局连接对象可以在需要时重用。这是一种不好的做法,因为您永远不能确定此对象的正确状态。如果在某个地方,在此代码之前,你发现了异常,结果你的连接仍然是开放的?你再次打开它,你会得到一个新的例外。同样,您的程序将很快突然结束。此外,这些对象包含非托管资源,如果没有释放,将导致程序中的每个位置出现问题。我建议每次需要时创建一个新的SqlConnection,并确保在代码末尾将其销毁,并将其包含在Using Statement中