【问题标题】:Multi user support for Access dbAccess db 的多用户支持
【发布时间】:2020-07-13 21:21:30
【问题描述】:

我有一个数据库,记录客户和供应商及其 使用 Access 的 3 个表中的地址,tblCustomers、tblSuppliers 和 tblAddresses。

如:

[tblCustomers] <== [tblAddresses] ==> [tblSuppliers]

例如,当我输入客户的详细信息时,在检查了所有必填字段后 我将在[tblAddresses] 中插入一条新记录,然后在[tblCustomers] 中插入客户详细信息 其中[tblCustomers].AddressFK = [tblAddresses.AddressPK]。

问题是我通过选择最新记录得到tblAddresses.AddressPK,但这并没有 处理多用户。当 2 人或更多人同时创建新客户或供应商时 它链接到错误的地址。例如

  1. 创建新客户
  2. 创建供应商

当(1)和(2)同时保存记录时,它们都在 tblAddresses 也不知道属于哪个。

最初,我以为客户和供应商共享相同的地址字段 我可以将他们的地址放在同一张表中,但现在这听起来是个坏主意。

有人知道如何解决这个问题吗?

我对任何事情都持开放态度,更糟糕的是我会重新设计数据库。

PS:我忘了提到我使用的是内置于 VBA 而不是 .NET 的 Access。

更新:感谢大家的投入,我已经找到了一种不同的方法来管理这个问题。 @@ 身份听起来是个好主意,但我没有使用它(我已经更改了数据输入
程序代替)所以我不确定是否应该将其标记为答案。不过谢谢,
我学到了一些新东西。 ^^

【问题讨论】:

标签: ms-access vba


【解决方案1】:

@LocTrang:实际上,一位客户可能拥有多个地址(账单、送货、替代送货)。关系看起来像

  1. [Customer]-1:1----0:m[Address] > 如果没有相应的客户详细信息,客户地址就不能存在。

供应商也是如此。供应商可能有多个地址(帐单、仓库) 供应商和地址表之间的关系看起来就像客户与地址之间的关系。

通常客户和供应商都有自己的地址表,但如果您想将两个地址保存在一个表中,您可以像这样设计地址表

  1. Address_ID > Primary1
  2. Owner_ID > Primary2 (*)
  3. Address_type >(可以是address_type表的主键)
  4. 地址_line1
  5. 地址_line2
  6. 城市
  7. ...其余列

这种设计将防止数据库中的数据不一致。 (*) 但是: 要实现这一点,owner_id 在整个数据库中或至少在客户和供应商表之间必须是唯一的。由于客户和供应商表中的自动编号字段将从 1 开始,因此您不能将其用作 owner_id,因为它在这两个表之间不是唯一的。最好在表中使用“GUID/uuid”作为 unique_id或构建自定义唯一字段,如供应商 ID 以“S_”开头,客户 ID 以 C_ 开头

您可以选择创建另一个名为 Address_type 的表:

  1. Address_type_id > 主键,自动编号
  2. 地址类型
  3. 说明

并将其粘贴到地址表中。

现在回答您的问题: 如果您使用 Access 表单来输入您的客户详细信息,您可以为地址创建一个子表单,并通过 LinkMasterField 和 LinkChildField 链接主表单和子表单。这样,您首先创建客户记录,然后当您移动到地址子表单时,新创建的 customer_Id 会为您预先填充。 喜欢她:(C_ID 是唯一的客户/所有者 ID)

使用插入后事件自动更新您的客户唯一 ID

Private Sub Form_AfterInsert()
    Me.txt_c_id.value = "C_" & Me.txt_Customer_id.value
End Sub

如果您使用 VBA 输入客户详细信息,请尝试通过事务封装您的数据执行。这样,无论有多少其他用户正在创建记录,您始终是安全的:

vba 代码:

Private Sub btn_add_new_Click()
    Dim MyDB As DAO.Database
    Dim MyRs As DAO.Recordset

    Set MyDB = CurrentDb

    Dim Last_ID As Long

    Dim SQL_GET As String
    Dim SQL_SET As String

    DBEngine.BeginTrans
        On Error GoTo ERROR_TRANS:
        SQL_SET = "INSERT INTO TBL_Customer(C_name,C_contact) VALUES('Second Customer','Second Contact')"
        MyDB.Execute SQL_SET, dbFailOnError

        SQL_GET = "SELECT MAX(Customer_id) AS LAST_ID FROM TBl_Customer"
        Set MyRs = MyDB.OpenRecordset(SQL_GET)
        Last_ID = Nz(MyRs("LAST_ID"), 0)

        'Since access does not provide triggers we update the customer unique id manually
        If Not Last_ID = 0 Then
            SQL_SET = "UPDATE TBL_Customer SET C_ID = 'C_" & Last_ID & "' WHERE TBL_Customer.Customer_id = " & Last_ID
            MyDB.Execute SQL_SET, dbFailOnError
        End If

        'Now add the address record via vba
        SQL_SET = "INSERT INTO TBL_Address(Owner_ID, type, Address_line1, Address_line2, city) VALUES('C_" & Last_ID & "','Billing','01 Main Street','Flat 2','London');"
        MyDB.Execute SQL_SET, dbFailOnError
    DBEngine.CommitTrans

    MsgBox "Customer inserted. New customer ID = C_" & Last_ID, vbInformation, "Success"
EXIT_ROUTINE:
    On Error Resume Next
    Set MyDB = Nothing
    Set MyRs = Nothing
    Exit Sub
ERROR_TRANS:
    On Error Resume Next
    DBEngine.Rollback
    MsgBox "Sorry there was a problem while creating new customer record", vbExclamation, "Unable to insert"
    Err.Clear
    GoTo EXIT_ROUTINE
End Sub

我希望你已经理解并更好地利用这个答案。

【讨论】:

猜你喜欢
  • 2016-05-07
  • 1970-01-01
  • 1970-01-01
  • 2010-12-12
  • 1970-01-01
  • 1970-01-01
  • 2016-12-04
  • 1970-01-01
  • 2015-05-02
相关资源
最近更新 更多