【问题标题】:MS Access SQL: Left Join for Selection List with CheckboxesMS Access SQL:带有复选框的选择列表的左连接
【发布时间】:2021-12-04 21:26:48
【问题描述】:

我正在尝试按照此处提供的示例 (https://www.databasedevelopment.co.uk/examples.htm) 获取带有复选框的 MS Access 子表单以供选择。

tbl_Employee_Selected

ID EmployeeID Name
1 1234 John Smith
2 1235 Jane Smith

tbl_Simple_selected

selectedID EmployeeID Selected
1 Yes/No
2 Yes/No
SELECT tbl_Employee_Selected.ID, tbl_Employee_Selected.EmployeeID, tbl_Employee_Selected.FirstName, tbl_Employee_Selected.LastName, tbl_Simple_selected.Selected
FROM tbl_Employee_Selected 
LEFT JOIN tbl_Simple_selected ON tbl_Employee_Selected.ID = tbl_Simple_selected.EmployeeID;

问题在于,使用上面的 SQL,我在创建的表中获得了“SelectedID”,而不是实际的员工 ID。如果我尝试任何其他联接条件,我将无法更新记录集,因为我没有使用主键。

【问题讨论】:

  • 我正在查看示例数据库。我没有看到那些表也没有查询。你到底想完成什么?
  • 我从他们的例子中重命名。我相信原来是“Categories”和“SimpleSelect”。

标签: sql ms-access


【解决方案1】:

您关心还是需要临时表?

您可以从“网格”(连续形式)中选择行,而无需复选框列。

因此,我们构建了一个“集合”来跟踪所选行的表单代码。

代码如下所示:

  Option Compare Database
  Option Explicit
  
  Public CheckItems As New Collection
  
  Public Function MySel(vID As Variant) As Boolean
  
     If IsNull(vID) Then
        MySel = False
        Exit Function
     End If
     ' check if id exists in colleciton.
     On Error Resume Next
     Dim mydummy As Variant
     mydummy = CheckItems(CStr(vID))
     If Err.Number = 0 Then
        ' found it, return true!!
        MySel = True
        Exit Function
     End If
     
     MySel = False
  
  End Function
  
  
  Private Sub cmdCheck_Click()
  
     ' check in our list
     If MySel(Me!ID) Then
        ' already in list - remove
        CheckItems.Remove CStr(Me!ID)
     Else
        ' not in the list - add it
        CheckItems.Add Me!ID.Value, CStr(Me!ID)
     End If
     
     Me.ckSel.Requery
  
  End Sub

所以,这里的“技巧”是我们将复选框绑定到 MySel 函数。因为复选框现在绑定到那个函数,所以我们不能点击那个复选框。

所以,复选框现在是这样绑定的:

因此,SelChk 函数将传递给定行的 PK。

现在,要选中/取消选中,我们在复选框的顶部放置一个按钮(不可见)。

像这样:

不要忘记将此按钮放在前面 - 我们确保它位于复选框的顶部。

因此:

所以,将以上所有内容放在一起,我们就有了:

当然,我们现在需要一个最终按钮来进行选择,我们可以运行报告,甚至处理记录。代码可以是这样的:

Dim strWhere      As String
Dim v             As Variant

For Each v In CheckItems
  If strWhere <> "" Then strWhere = strWhere & ","
  strWhere = strWhere & v
Next

' 根据选择打开报告

DoCmd.OpenReport "rptHotelsInvoice", acViewPreview, , "ID IN (" & strWhere & ")"

或者,我们可以在代码中处理记录,这样说:

  Dim strWhere      As String
  Dim v             As Variant
  
  For Each v In CheckItems
     If strWhere <> "" Then strWhere = strWhere & ","
     strWhere = strWhere & v
  Next
  
  Dim strSQL As String
  
  strSQL = "SELECT * from tblHotels where ID IN (" & strWhere & ")"
  Debug.Print strSQL
  
  Dim rst     As DAO.Recordset
  Set rst = CurrentDb.OpenRecordset(strSQL)

  Do While rst.EOF = False
  
      ' process reocrds
      rst.Edit
      rst("FirstName") = rst("FirstName") & "z"
      
      rst.Edit
      rst("FirstName") = rst("FirstName") & "z"
      
      rst.Update
      rst.MoveNext
  Loop
  rst.Close

现在,我们假设 PK 有一个“ID”,但如果您的 pk id 不同,则更改此:

MySql([ID])  to whatever your PK row ID is. the rest of the code should work as is.

上面创建 WHERE 子句的最后一段代码也将被更改。

所以,总而言之?

您确实不需要临时表,使用上述自定义集合和驱动复选框的函数意味着您不需要额外的表。

上面的美景?

您可以将其用于链接的 Excel 工作表、SharePoint 表、SQL 服务器表 - 没关系,因为我们不会弄乱或处理额外的表。

【讨论】:

  • 谢谢,这很有帮助!当您选择一个时,有没有办法防止基础表单中的所有其他选择框“闪烁”?当我单击透明按钮时,所有其他框都会显示一个填充的黑框(无论它们的状态如何),然后再更新为它们最后选择/未选择的状态。
  • 没有解决方案,我注意到这是一个问题。记录越少,条件格式越少,数据源越干净越好,但它会闪烁。不要用 dlookup() 说任何行,并尝试使用条件格式等保持 sql 和行格式“受限”。表单越干净,闪烁越少 - 但你必须忍受它。这还不算太糟糕 - 但这里的合法烦恼永远不会少。我有一个较新的版本,其中我不使用复选框,但只有一个文本框(出现 X - 它有点好,不是很多)
【解决方案2】:

加入EmployeeID怎么样:

SELECT 
    tbl_Employee_Selected.ID, 
    tbl_Employee_Selected.EmployeeID, 
    tbl_Employee_Selected.FirstName, 
    tbl_Employee_Selected.LastName, 
    tbl_Simple_selected.Selected
FROM 
    tbl_Employee_Selected 
LEFT JOIN 
    tbl_Simple_selected 
    ON tbl_Employee_Selected.EmployeeID = tbl_Simple_selected.EmployeeID;

【讨论】:

  • 我不能,因为那时记录集不可更新。我相信这是因为 EmployeeID 不是主键。
  • @user2059972 对于更新查询,您需要 DLOOKUP()、DSUM()、DMIN()、DMAX() 等域聚合函数。
  • 但是如果联接在主键上而不使用这些关键字,则原始查询有效。问题是我希望查询更新但报告的字段与主键字段不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-31
  • 1970-01-01
  • 1970-01-01
  • 2021-05-20
  • 1970-01-01
相关资源
最近更新 更多