【问题标题】:How to use VB and SQL to add Records to a Relational Database in AccessAccess中如何使用VB和SQL向关系数据库添加记录
【发布时间】:2020-07-09 19:18:29
【问题描述】:

我正在使用 Visual Basic 创建表单应用程序,作为大学项目的一部分。我使用 SQL 语句从 access 数据库中读取数据,但在写入时遇到了一些麻烦。我想冒险猜测这是由于数据库在表之间存在关系。

这是我第一次尝试制作实质性的东西,vb 不是我选择的语言。期望代码充其量是糟糕的。如果有人有我可以用来改进的资源的链接,我将不胜感激。

例外:

抛出异常:'System.Data.OleDb.OleDbException:'没有为一个或多个必需参数提供值。'

异常位置:'commAddToStaff.ExecuteNonQuery()'

两个 try 语句在运行时都会捕获异常。我尝试在参数中提供数据,而不是使用文本框中的数据,但这并没有解决问题。

代码:

Private Sub btnAddStaffMember_Click(sender As Object, e As EventArgs) Handles btnAddStaffMember.Click

    'Dimension tblStaff Parameters 
    Dim AddEmployeeIDParam As New OleDb.OleDbParameter("@AddEmployeeID", txtAddEmployeeID.Text)
    Dim AddForenameParam As New OleDb.OleDbParameter("@AddForename", txtAddForename.Text)
    Dim AddSurnameParam As New OleDb.OleDbParameter("@AddSurname", txtAddSurname.Text)
    Dim AddDOBParam As New OleDb.OleDbParameter("@AddDOB", txtAddDOB.Text)
    Dim AddUserTierParam As New OleDb.OleDbParameter("@AddUserTier", txtAddUserTier.Text)

    'Dimension tblContacts Parameters
    Dim conContact As New OleDb.OleDbConnection("Provider=Microsoft.......")
    Dim commContactCount As New OleDb.OleDbCommand("Select Count(*) FROM tblContacts", conContact)
    commContactCount.Connection.Open()                 
    Dim ContactID = commContactCount.ExecuteScalar + 1     'Calculate the contactID of the new record
    commContactCount.Connection.Close()                  'Close the connection
    Dim AddContactIDParam As New OleDb.OleDbParameter("@AddContactID", ContactID)
    Dim AddAddressParam As New OleDb.OleDbParameter("@AddAddress", txtAddAddress.Text)
    Dim AddPostcodeParam As New OleDb.OleDbParameter("@AddPostcode", txtAddPostcode.Text)
    Dim AddEmailParam As New OleDb.OleDbParameter("@AddEmail", txtAddEmail.Text)
    Dim AddMobileNoParam As New OleDb.OleDbParameter("@AddMobileNo", txtAddMobileNumber.Text)

    Dim conAddToStaff As New OleDb.OleDbConnection("Provider=Microsoft....")
    Dim commAddToStaff As New OleDb.OleDbCommand("Insert Into tblStaff (EmployeeID, Forename, Surname, DOB, User_Tier, ContactID) Values (@AddEmployeeID, @AddForename, @AddSurname, @AddDOB, @AddUserTier, @AddContactID)", conAddToStaff)
    commAddToStaff.Parameters.Add(AddEmployeeIDParam)
    commAddToStaff.Parameters.Add(AddForenameParam)
    commAddToStaff.Parameters.Add(AddSurnameParam)
    commAddToStaff.Parameters.Add(AddDOBParam)
    commAddToStaff.Parameters.Add(AddUserTierParam)

    Dim commAddToContact As New OleDb.OleDbCommand("Insert Into tblContacts (ContactID, Address, Postcode, Email, Mobile_Number) Values (@AddContactID, @AddAddress, @AddPostcode, @AddEmail, @AddMobileNo)", conContact)
    commAddToContact.Parameters.Add(AddContactIDParam)
    commAddToContact.Parameters.Add(AddAddressParam)
    commAddToContact.Parameters.Add(AddPostcodeParam)
    commAddToContact.Parameters.Add(AddEmailParam)
    commAddToContact.Parameters.Add(AddMobileNoParam)

    Try
        commAddToStaff.Connection.Open()                 'Open a connection to the database
        commAddToStaff.ExecuteNonQuery()                 'Execute the command
        commAddToStaff.Connection.Dispose()              'Remove unmanaged resources
        commAddToStaff.Connection.Close()                'Close the connection
    Catch ex As Exception
        MessageBox.Show("Error with staff")
    End Try

    Try
        commAddToContact.Connection.Open()                 'Open a connection to the database
        commAddToContact.ExecuteNonQuery()                 'Execute the command
        commAddToContact.Connection.Dispose()              'Remove unmanaged resources
        commAddToContact.Connection.Close()                'Close the connection
    Catch ex As Exception
        MessageBox.Show("Error with contacts")
    End Try

    MessageBox.Show("Reached")

    Me.Hide()       'Close the Current screen
    StaffDB_Add_Staff_Security_Question.Show()  'Open the Add Security Question Screen
End Sub

【问题讨论】:

  • 实际的错误信息是什么?这将告诉您和我们要寻找什么。您似乎不知道它是什么的事实表明您实际上还没有尝试解决问题。如果你不知道问题出在哪里,你怎么能?
  • 对不起,我以为我把它包括在内了。我不确定这是否是您正在寻找的东西,我对此真的很陌生。我已经添加了我认为是上面的错误消息。
  • 我已经在上面更新了,它发生在我尝试 ExecuteNonQuery() 的两次。

标签: sql vb.net ms-access relational-database


【解决方案1】:

您在此处将六个值插入六列:

Dim commAddToStaff As New OleDb.OleDbCommand("Insert Into tblStaff (EmployeeID, Forename, Surname, DOB, User_Tier, ContactID) Values (@AddEmployeeID, @AddForename, @AddSurname, @AddDOB, @AddUserTier, @AddContactID)", conAddToStaff)

但是你这里只给命令添加五个参数:

commAddToStaff.Parameters.Add(AddEmployeeIDParam)
commAddToStaff.Parameters.Add(AddForenameParam)
commAddToStaff.Parameters.Add(AddSurnameParam)
commAddToStaff.Parameters.Add(AddDOBParam)
commAddToStaff.Parameters.Add(AddUserTierParam)

SQL 代码中@AddContactID 占位符的参数在哪里?

编辑:

为了记录,以下是我倾向于为此类任务编写代码的方式,忽略您生成 ContactID 值的可怕方式:

Using connection As New OleDbConnection("connection string here")
    connection.Open()

    Dim contactCount As Integer

    Using contactCountCommand As New OleDbCommand("SELECT COUNT(*) FROM tblContacts", connection)
        contactCount = CInt(contactCountCommand.ExecuteScalar())
    End Using

    Dim contactId = contactCount + 1

    Using staffCommand As New OleDbCommand("INSERT INTO tblStaff (EmployeeID, Forename, Surname, DOB, User_Tier, ContactID) Values (@EmployeeID, @Forename, @Surname, @DOB, @User_Tier, @ContactID)", connection)
        With staffCommand.Parameters
            .Add("@EmployeeID", OleDbType.VarChar, 50).Value = txtAddEmployeeID.Text
            .Add("@Forename", OleDbType.VarChar, 50).Value = txtAddForename.Text
            .Add("@Surname", OleDbType.VarChar, 50).Value = txtAddSurname.Text
            .Add("@DOB", OleDbType.Date).Value = CDate(txtAddDOB.Text) 'Why isn't this coming from a DateTimePicker?
            .Add("@User_Tier", OleDbType.VarChar, 50).Value = txtAddUserTier.Text
            .Add("@ContactID", OleDbType.Integer).Value = contactId
        End With

        staffCommand.ExecuteNonQuery()
    End Using

    Using contactCommand As New OleDbCommand("INSERT INTO tblContacts (ContactID, Address, Postcode, Email, Mobile_Number) Values (@ContactID, @Address, @Postcode, @Email, @Mobile_Number)", connection)
        With contactCommand.Parameters
            .Add("@ContactID", OleDbType.Integer).Value = contactId
            .Add("@Address", OleDbType.VarChar, 50).Value = txtAddAddress.Text
            .Add("@Postcode", OleDbType.VarChar, 50).Value = txtAddPostcode.Text
            .Add("@Email", OleDbType.VarChar, 50).Value = txtAddEmail.Text
            .Add("@Mobile_Number", OleDbType.VarChar, 50).Value = txtAddMobileNumber.Text
        End With

        contactCommand.ExecuteNonQuery()
    End Using
End Using

【讨论】:

  • 我稍微往下添加了一点,我通过计算联系人表中的记录数然后加 1 来计算 ContactID 应该是多少。
  • 不。阅读我发布的内容。该代码显示您创建参数对象。您在哪里将该参数添加到该命令?你不是。您将它添加到另一个命令,但不是我在我的答案中写的单词中指定的那个。部分问题在于您的代码过于冗长以至于难以阅读,因此很难看出何时出错。
  • 你可能想看看我关于如何编写更简洁、可读和可维护的代码的建议。
  • 我一定会看看的。除了一些非常基本的python之外,我对编码完全陌生,所以我严重超出了我的深度。我现在所写的内容更接近于一系列博奇,而不是任何类似雄辩的东西。再次感谢您的帮助。
  • @Ian 您可能喜欢一种稍微不同的创建 SQL 参数的方法,如我现在冗余的答案中所示。此外,请确保使用数据库中的日期作为 DOB,而不是字符串。
【解决方案2】:

通过将代码重新排列成更小的部分,相关项彼此靠近,可以更容易地查看添加的参数不足的位置。比如:

Imports System.Data.OleDb

Public Class Form1

    Dim connStr As String = "Provider=Microsoft......."

    Sub AddStaffMemberToDatabase(contactId As Integer)
        Dim sql = "INSERT INTO tblStaff (EmployeeID, Forename, Surname, DOB, UserTier, ContactID) VALUES (@AddEmployeeID, @AddForename, @AddSurname, @AddDOB, @AddUserTier, @AddContactID)"

        Using conn As New OleDbConnection(connStr),
                cmd As New OleDbCommand(sql, conn)

            Dim dob = DateTime.Parse(txtAddDOB.Text)

            cmd.Parameters.Add(New OleDbParameter With {.ParameterName = "@AddEmployeeID", .OleDbType = OleDbType.VarChar, .Size = 20, .Value = txtAddEmployeeID.Text})
            cmd.Parameters.Add(New OleDbParameter With {.ParameterName = "@AddForename", .OleDbType = OleDbType.VarWChar, .Size = 255, .Value = txtAddForename.Text})
            cmd.Parameters.Add(New OleDbParameter With {.ParameterName = "@AddSurname", .OleDbType = OleDbType.VarWChar, .Size = 255, .Value = txtAddSurname.Text})
            cmd.Parameters.Add(New OleDbParameter With {.ParameterName = "@AddDOB", .OleDbType = OleDbType.Date, .Value = dob})
            cmd.Parameters.Add(New OleDbParameter With {.ParameterName = "@AddUserTier", .OleDbType = OleDbType.VarChar, .Size = 20, .Value = txtAddUserTier.Text})
            cmd.Parameters.Add(New OleDbParameter With {.ParameterName = "@AddContactID", .OleDbType = OleDbType.Integer, .Value = contactId})

            conn.Open()
            cmd.ExecuteNonQuery()

        End Using

    End Sub

    Sub AddContactToDatabase(contactId As Integer)
        Dim sql = "INSERT INTO tblContacts (ContactID, Address, Postcode, Email, Mobile_Number) VALUES (@AddContactID, @AddAddress, @AddPostcode, @AddEmail, @AddMobileNo)"

        Using conn As New OleDbConnection(connStr),
                cmd As New OleDbCommand(sql, conn)

            cmd.Parameters.Add(New OleDbParameter With {.ParameterName = "@AddContactID", .OleDbType = OleDbType.Integer, .Value = contactId})
            cmd.Parameters.Add(New OleDbParameter With {.ParameterName = "@AddAddress", .OleDbType = OleDbType.VarWChar, .Size = 255, .Value = txtAddAddress.Text})
            cmd.Parameters.Add(New OleDbParameter With {.ParameterName = "@txtAddPostcode", .OleDbType = OleDbType.VarChar, .Size = 20, .Value = txtAddPostcode.Text})
            cmd.Parameters.Add(New OleDbParameter With {.ParameterName = "@AddEmail", .OleDbType = OleDbType.VarWChar, .Size = 255, .Value = txtAddEmail.Text})
            cmd.Parameters.Add(New OleDbParameter With {.ParameterName = "@AddMobileNo", .OleDbType = OleDbType.VarChar, .Size = 20, .Value = txtAddMobileNumber.Text})

            conn.Open()
            cmd.ExecuteNonQuery()

        End Using

    End Sub

    Sub AddStaffMember()
        Dim sql = "SELECT COUNT(*) FROM tblContacts"
        Dim contactID As Integer

        Using conn As New OleDbConnection(connStr),
                cmd As New OleDbCommand(sql, conn)
            conn.Open()
            contactID = Convert.ToInt32(cmd.ExecuteScalar()) + 1
        End Using

        AddStaffMemberToDatabase(contactID)
        AddContactToDatabase(contactID)

    End Sub

    Private Sub btnAddStaffMember_Click(sender As Object, e As EventArgs) Handles btnAddStaffMember.Click
        AddStaffMember()
        Me.Hide()
        StaffDB_Add_Staff_Security_Question.Show()  'Open the Add Security Question Screen

    End Sub

End Class

Using 语句确保“非托管资源”在代码完成后被释放。

请注意,您需要提供一种更具体、更可靠的 DOB 文本解析方式(例如 DateTime.TryParseExact)。此外,需要编辑数据库类型和大小以匹配数据库中的声明。

【讨论】:

  • 谢谢 Andrew,我不知道您可以像这样指定数据类型和大小。我想我将从头开始重写代码,借用这两个答案。到目前为止,我所拥有的一切都是由我在网上收集并拼凑起来的块组成的,绝对需要改进。再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-11
  • 2013-04-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多