【问题标题】:Query will not update SQL Server查询不会更新 SQL Server
【发布时间】:2016-04-25 10:11:00
【问题描述】:

在下面的代码中,我的第二个查询不会插入 SQL 数据库,但第一个会更新。我可以复制查询(从我为测试添加的 msgbox 中)并将其粘贴到 SQL Server Management Studio 中,它会执行得很好。我也没有从 SQL 收到任何错误消息,尽管我不确定该代码是否正确(它是从另一个来源复制 + 粘贴的)。另外,我可以简化代码以同时传递两个查询吗?

Dim Conn As New System.Data.SqlClient.SqlConnection         'sql server datastream connection
Dim Cmd As New System.Data.SqlClient.SqlCommand             'sql command vars
Dim SqlQuery As String                                      'string var used to hold various SQL queries
Dim data As System.Data.SqlClient.SqlDataReader             'datareader object variable
Dim MVDataset As New DataSet
Dim MVDatatable As DataTable
Dim MVDatarow As DataRow

Private Sub MVUpdateButton_Click(sender As Object, e As EventArgs) Handles MVUpdateButton.Click

  vbyn = MsgBox("Are you sure you want to update Tally Sheet Master Variables?" & vbCrLf & vbCrLf & "Changes to these variables will change the functionality of the Tally Sheet!", vbYesNo, )
  Try
    Select Case vbyn
      Case vbNo
        GoTo MVTableUpdateBypass
      Case vbYes
        'get new data from textboxes
        Vers = TextBox1.Text
        If TextBox2.Text = True Then
          Testing = 1
        Else
          Testing = 0
        End If
        FlatFeeCharge = TextBox3.Text
        PrepricingCharge = TextBox4.Text
        SendMailAcct = TextBox5.Text
        SendMailPW = TextBox6.Text
        TestingEmail = TextBox7.Text
        PrePricingEmail = TextBox8.Text
        ImperataEmail = TextBox9.Text

        'update existing active row to mark inactive
        SqlQuery = "Update MasterVars set Active = 0 where PKEY = " & PKEY & ";"
        MsgBox(SqlQuery)
        If Conn.State = ConnectionState.Closed Then
          Conn.ConnectionString = "Data Source=SQL01;Initial Catalog=TallySheet;Integrated Security=SSPI;"
        End If
        Conn.Open()
        Dim MVDataAdapter As New SqlDataAdapter(SqlQuery, Conn)
        Dim MVUpdateCommand As SqlCommand
        MVUpdateCommand = New SqlCommand(SqlQuery)
        MVDataAdapter.UpdateCommand = MVUpdateCommand

        'insert new active row
        SqlQuery = "Insert into MasterVars (Vers, Testing, FlatFeeCharge, PrePricingCharge, SendMailAcct, SendMailPW, TestingEmail, PrePricingEmail, ImperataEmail, DTS, UserName, Active) Values (" & "'" & Vers & "', " & Testing & ", '" & FlatFeeCharge & "'" & ", '" & PrepricingCharge & "'" & ", '" & SendMailAcct & "'" & ", '" & SendMailPW & "'" & ", '" & TestingEmail & "'" & ", '" & PrePricingEmail & "'" & ", '" & ImperataEmail & "'" & ", '" & Date.Now & "'," & "'QGDOMAIN\" & Environment.UserName & "'," & 1 & ");"
        MsgBox(SqlQuery)
        Dim MVInsertCommand As SqlCommand
        MVInsertCommand = New SqlCommand(SqlQuery)
        MVDataAdapter.InsertCommand = MVInsertCommand
        MVDataAdapter.Fill(MVDataset, "MasterVars")
      End Select
    Catch ex As SqlException
      Dim i As Integer
      Dim errormessages As String
      errormessages = ""
      For i = 0 To ex.Errors.Count - 1
        errormessages = errormessages & " " & ("Index #" & i.ToString() & ControlChars.NewLine _
                & "Message: " & ex.Errors(i).Message & ControlChars.NewLine _
                & "LineNumber: " & ex.Errors(i).LineNumber & ControlChars.NewLine _
                & "Source: " & ex.Errors(i).Source & ControlChars.NewLine _
                & "Procedure: " & ex.Errors(i).Procedure & ControlChars.NewLine)
      Next i
    Console.WriteLine(errorMessages.ToString())
  End Try

  'reload form with updated variables
  Conn.Close()
  Conn.Dispose()
MVTableUpdateBypass:
End Sub

【问题讨论】:

  • 不要使用 GoTo,使用 SQL 参数,不要使用全局 DB 提供程序对象。我不确定可以使用更新命令来填充数据表
  • 您能否提供更多信息?我在 SQL Server 和 VBA 方面非常熟练……但现在我得到了我应该使用 VB.NET 的指令……更新查询有效,但插入无效。如果我不应该使用 GoTo 和全局 DB 对象,那么我应该使用什么?
  • 这里有很多很多很多的帖子 (like this one) 展示了如何使用参数、处理对象等等。
  • 在这种简单的情况下,您应该只使用“return”而不是 GOTO。而且你真的需要使用参数化查询,甚至更好的存储过程,而不是像这样构建一个字符串并执行它。
  • 谁执行这些查询? Adapter.Fill 运行 SelectCommand,正如我上面所说的。

标签: sql-server vb.net winforms


【解决方案1】:

SqlDataAdapter 的 Fill 方法执行 SelectCommand 而不是 UpdateCommandInsertCommand。在任何情况下,当您调用适配器的Update 方法时,都会执行这两个命令(以及DeleteCommand)。
此外,Update 方法运行命令以查找 SelectCommand 检索的 DataTable/DataSet 中更改/添加/删除的行,并且仅适用于这些行。

但您不需要 SqlDataAdapter 来执行您的两个查询。您应该简单地构造一个用分号分隔的两个文本的 SqlCommand 并调用 ExecuteNonQuery

SqlQuery = "Update MasterVars set Active = 0 where PKEY = @key;" & _
           "Insert into MasterVars (Vers, Testing, .....) VALUES (@p1, @o2, ....)"
Using Conn = New SqlConnection("Data Source=SQL01;......")
Using cmd = New SqlCommand(SqlQuery, Conn)
    Conn.Open()
    cmd.Parameters.Add("@key", SqlDbType.Int).Value = PKEY 
    cmd.Parameters.Add("@p1", SqlDbType.NVarChar).Value = vers 
    cmd.Parameters.Add("@p2", SqlDbType.Int).Value = testing
    ... and so on with other parameters .... 
    cmd.ExecuteNonQuery()
End Using
End Using

在这个不完整的例子中(太多的参数要写下来)我将两个 sql 文本连接在一个字符串中,并用参数占位符准备了它。然后我使用您的表所需的确切数据类型构建参数集合,最后调用ExecuteNonQuery 在数据库端运行所有内容。

注意不需要保留全局对象,如连接或命令。最好创建一个局部变量,完成后使用和销毁它。特别是像连接和命令这样的一次性对象应该总是在 Using 块中创建

【讨论】:

  • 谢谢....整个数据适配器的事情让我很困惑。我同时得到了很多新信息。我很欣赏清晰、简洁的答案。
  • 很高兴能提供帮助。作为新用户,我建议您也阅读How does accepting an answer works
猜你喜欢
  • 1970-01-01
  • 2020-11-21
  • 1970-01-01
  • 1970-01-01
  • 2015-09-05
  • 1970-01-01
  • 2019-07-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多