【问题标题】:Unable to INSERT even if the record still does not exist in the database即使该记录在数据库中仍然不存在,也无法插入
【发布时间】:2012-01-11 20:08:30
【问题描述】:

我想在数据库中插入记录,但是在插入之前,它必须先检查数据库中插入的值是否已经存在。现在我的问题是,即使该值仍然不存在,我也无法插入到数据库中。

这是我的代码:

Dim check As New SqlCommand
    Dim sqlcheck As String = "SELECT SerialNumber FROM EquipmentDetail WHERE SerialNumber = '" & TextBox1.Text & "'"


    connection.Open()
    check.Connection = connection
    check.CommandText = sqlcheck

    Dim read As SqlDataReader = check.ExecuteReader()

    If read.HasRows Then

        While read.Read()

            If read("SerialNumber").ToString() = TextBox1.Text Then

                MessageBox.Show(read("SerialNumber").ToString() & " was already added")

            Else

                cmd.Connection = connection
                cmd.CommandText = "INSERT INTO EquipmentDetail (SerialNumber, BoxNumber, FATTNumber, FaultTicketNumber, Description, ProductCode)" &
                "VALUES('" & TextBox1.Text & "',  '" & TextBox2.Text & "',  '" & TextBox3.Text & "',  '" & TextBox4.Text & "', '" & TextBox6.Text & "',  '" & ComboBox1.Text & "')"
                cmd.ExecuteNonQuery()

                MessageBox.Show("Equipment successfully added.", "Equipment", MessageBoxButtons.OK)
                TextBox1.Text = ""
                TextBox2.Text = ""
                TextBox3.Text = ""
                TextBox4.Text = ""
                TextBox6.Text = ""
                TextBox1.Focus()
                connection.Close()

            End If
        End While
    End If
    read.Close()

【问题讨论】:

  • 当您尝试执行 INSERT 语句时,您返回了什么错误?可能错误与数据库中已经存在的序列号无关。
  • read.HasRows 为假时怎么办?您最好使用 "SELECT Count(*) FROM FROM EquipmentDetail WHERE SerialNumber = '" & TextBox1.Text & "'" *** 但使用 TextBox1.Text 的参数以避免注入攻击。如果您希望我提供代码示例,请告诉我。

标签: sql vb.net visual-studio-2010


【解决方案1】:

您的代码存在许多问题。

首先,您有一个可以使用参数解决的 sql 注入漏洞。

其次,您正在一个开放的数据阅读器中执行数据库活动,这可能会导致许多问题。

第三,您执行了太多工作来确定序列号是否存在。您可以使用 SQL Server Exists 语句和 SqlCommand 的 ExecuteScalar 方法来返回和测试单个值,这使得代码更快更容易理解。

最后,您需要确保一次性物品被丢弃,最简单/最好的方法是使用 Using blocks。

这些都可以用下面的代码解决:

    Using connection As New SqlConnection(connStr)
        Dim sqlcheck As String = "IF EXISTS(select 1 FROM EquipmentDetail WHERE SerialNumber=@SerialNumber) SELECT 1 ELSE SELECT 0"
        Using cmd As New SqlCommand(sqlcheck, connection)
            cmd.Parameters.AddWithValue("@SerialNumber", TextBox1.Text)
            connection.Open()

            If CBool(cmd.ExecuteScalar) Then
                MessageBox.Show(TextBox1.Text & " was already added")
            Else
                Using insertCmd As New SqlCommand
                    insertCmd.Connection = connection

                    insertCmd.CommandText = "INSERT INTO EquipmentDetail (SerialNumber, BoxNumber, FATTNumber, FaultTicketNumber, Description, ProductCode)" &
                    "VALUES(@SerialNumber, @BoxNumber, @FATTNumber, @FaultTicketNumber, @Description, @ProductCode)"
                    insertCmd.Parameters.AddWithValue("@SerialNumber", TextBox1.Text)
                    insertCmd.Parameters.AddWithValue("@BoxNumber", TextBox2.Text)
                    insertCmd.Parameters.AddWithValue("@FATTNumber", TextBox3.Text)
                    insertCmd.Parameters.AddWithValue("@FaultTicketNumber", TextBox4.Text)
                    insertCmd.Parameters.AddWithValue("@Description", TextBox6.Text)
                    insertCmd.Parameters.AddWithValue("@ProductCode", ComboBox1.Text)

                    insertCmd.ExecuteNonQuery()

                    MessageBox.Show("Equipment successfully added.", "Equipment", MessageBoxButtons.OK)
                    TextBox1.Text = ""
                    TextBox2.Text = ""
                    TextBox3.Text = ""
                    TextBox4.Text = ""
                    TextBox6.Text = ""
                    TextBox1.Focus()
                End Using

            End If
        End Using
        connection.Close()
    End Using

【讨论】:

  • HI .. .thank you all for your reply ... nweiz 我上面的代码有一个错误“错误:'read'未声明。由于它的保护,它可能无法访问等级。”这是我第一次听说“使用”语句和参数(新手)......仍然无法完全掌握他们的概念,但我会尝试适应......
  • 很抱歉;消息框行应该是:MessageBox.Show(TextBox1.Text & " was already added")。我已经更新了答案。
  • 第一次:别担心,这些是开发安全、性能良好的代码的最佳实践,因此您从一开始就正确学习是一件好事 :)。
  • 非常感谢。现在它的工作。我将尝试使用参数方法转换我的所有代码。 ...现在,我为我的代码感到羞耻 .. LOL .. 再次感谢您。
  • 你的 Insert 语句现在不是有 Sql Injection 漏洞吗?
【解决方案2】:

如果数据库中不存在 SerialNumber 值,则不会返回任何内容 - 因此永远不会到达包含您的插入的块。

【讨论】:

    【解决方案3】:

    首先,您要连接字符串以创建 SQL 语句。非常危险,请阅读 SQL 注入和参数化。

    问题似乎是因为您仅在 SerialNumber 检查的结果有行时才执行 INSERT。但如果 SerialNumber 不存在,它不会做任何事情。您可能应该尝试像这样修改 If 语句:

    If read.HasRows Then
    
        MessageBox.Show(read("SerialNumber").ToString() & " was already added")
    
    Else
    
        cmd.Connection = connection
        cmd.CommandText = "INSERT INTO EquipmentDetail (SerialNumber, BoxNumber, FATTNumber, FaultTicketNumber, Description, ProductCode)" &
          "VALUES('" & TextBox1.Text & "',  '" & TextBox2.Text & "',  '" & TextBox3.Text & "',  '" & TextBox4.Text & "', '" & TextBox6.Text & "',  '" & ComboBox1.Text & "')"
        cmd.ExecuteNonQuery()
    
        MessageBox.Show("Equipment successfully added.", "Equipment", MessageBoxButtons.OK)
                TextBox1.Text = ""
                TextBox2.Text = ""
                TextBox3.Text = ""
                TextBox4.Text = ""
                TextBox6.Text = ""
                TextBox1.Focus()
                connection.Close()
    
    End If
    read.Close()
    

    【讨论】:

      猜你喜欢
      • 2018-08-14
      • 1970-01-01
      • 2023-03-21
      • 1970-01-01
      • 2012-07-12
      • 1970-01-01
      • 1970-01-01
      • 2019-09-20
      • 2015-01-26
      相关资源
      最近更新 更多