Sql 使用循环从表中选择多条记录,以填充MS Access中未绑定的文本框

Sql 使用循环从表中选择多条记录,以填充MS Access中未绑定的文本框,sql,ms-access,vba,Sql,Ms Access,Vba,我有一个包含以下字段的表: StudentID ClassID TestID TestScore 对于每个学生和班级的独特组合,最多可能有10个测试ID和相应的测试分数。我有一个表单,其中有10个未绑定的文本框,对应于10个测试ID的测试分数。我正在尝试使用表单编辑数据并将数据添加到我的表(StudentScores)。由于学生可能缺课,每个学生班级组合表中不一定有10条记录 我希望能够在事件过程中使用循环,根据选定的学生和班级ID从表中检索测试分数,并将其输入到文本框中。文本框命名为tex

我有一个包含以下字段的表:

StudentID
ClassID
TestID 
TestScore
对于每个学生和班级的独特组合,最多可能有10个测试ID和相应的测试分数。我有一个表单,其中有10个未绑定的文本框,对应于10个测试ID的测试分数。我正在尝试使用表单编辑数据并将数据添加到我的表(StudentScores)。由于学生可能缺课,每个学生班级组合表中不一定有10条记录

我希望能够在事件过程中使用循环,根据选定的学生和班级ID从表中检索测试分数,并将其输入到文本框中。文本框命名为textbox1到textbox10,对应于10个测试

通过在类似这样的论坛上进行搜索,我能够找到以下代码,从10个未绑定的文本框中提取数据,将其作为新记录添加到表中:

Dim i As Integer
Dim rst As DAO.Recordset
Set rst = CurrentDb.OpenRecordset("StudentScores", dbOpenTable)
For i = 1 To 10
rst.AddNew
rst![StudentID] = Me.StudentCombo1
rst![ClassID] = Me.ClassCombo1
rst![TestID] = i
If Not IsNull(Controls("Textbox" & i)) Then
   rst![TestScore] = CLng(Controls("Textbox" & i))
End If
rst.Update
Next 
好的,下面的代码似乎至少在一开始是有效的。我最初的问题是由于打字错误。但是,当我更改组合框的值并重新运行例程时,我得到一个错误,即记录集为空

Dim rst As DAO.Recordset
mmySQL = "SELECT * from StudentScores where ClassID =" & Me.ClassCombo1 & "AND StudentID =" & Me.StudentCombo1
Set rst = CurrentDb.OpenRecordset(mmySQL)
rst.MoveFirst
Do Until rst.EOF
    Controls("Textbox" & rst![TestID]) = rst![TestScore]
    rst.MoveNext
Loop
rst.Close
Set rst = Nothing

在讨论问题的实质之前,请注意以下几点:

  • 当前您允许StudentScores表中的
    Null
    测试分数。尽管您知道自己的数据,但我可能会拒绝它们(即,将字段的必需属性设置为
    True
    )。也就是说,下面的代码假设不允许使用null

  • 即使在小表单中,我也会避免使用默认控件名,如
    TextBox1
    ——一种常见的访问约定是使用三个字母的前缀(例如
    txtTestScore1
    )。还有,如果每个都只有一个,为什么要
    ClassCombo1
    StudentCombo1
    ?不过,为了清楚起见,我会坚持你现在的名字

  • 您的描述是指添加或编辑,但记录代码的文本框仅包括前者。。。虽然我知道你自己也说过了

  • 对于这种情况,您可以使用纯DAO或一些内联SQL。在数据量达到一定规模之前(10个测试分数远未达到这一水平),选择哪种方法并不重要,但我会选择第二种方法

  • 如果还没有,您可能希望在
    TestID
    字段中放置一个验证规则,以强制执行1到10之间的值

  • 因此,首先是几个常量-在表单模块的顶部声明它们:

    Const MaxTextScoreCount = 10 
    Const TestScoreTextBoxPrefix = "TextBox" 
    
    接下来,一个清除表单上现有值的方法:

    Sub ClearTestScoreTextBoxes()
      Dim I As Integer
      For I = 1 To MaxTextScoreCount
        Me.Controls(TestScoreTextBoxPrefix & I).Value = Null
      Next I
    End Sub
    
    第三,一个帮助函数,用于从组合框构建WHERE子句:

    Function BuildWhereClause() As String
      BuildWhereClause = " WHERE StudentID = " & StudentCombo1.Value & _
        " AND ClassID = " & ClassCombo1.Value 
    End Function
    
    第四,使用选择填充文本框的方法:

    Sub UpdateTestScoreTextBoxes()
      Dim RS AS DAO.Recordset, SQL As String
      SQL = "SELECT TestID, TestScore FROM StudentScores" + BuildWhereClause
      Set RS = CurrentDb.OpenRecordset(SQL, dbForwardOnly)
      ClearTestScoreTextBoxes
      While Not RS.EOF
        Me.Controls(TestScoreTextBoxPrefix & RS!TestID).Value = RS!TestScore
        RS.MoveNext
      Wend
    End Sub
    
    第五,从文本框更新数据库的方法:

    Sub UpdateDatabase()
      Dim DB AS DAO.Database, I As Integer, Score As Variant, WhereClause as String, SQL As String
      Set DB = CurrentDb
      For I = 1 To MaxTextScoreCount
        Score = Me.Controls(TestScoreTextBoxPrefix & I).Value
        WhereClause = BuildWhereClause + " AND TestID = " & I
        If IsNull(Score) Then
          SQL = "DELETE FROM StudentScores" + WhereClause
        ElseIf DB.OpenRecordset("SELECT 1 FROM StudentScores" + WhereClause).EOF Then
          SQL = "INSERT INTO StudentScores(StudentID, ClassID, TestID, TestScore) " + _
                "VALUES (" & StudentCombo1.Value & "," & ClassCombo1.Value & "," & _
                 I & "," & Score & ")"
        Else
          SQL = "UPDATE StudentScores SET TestScore = " & Score & WhereClause
        End If
        DB.Execute SQL
      Next I
    End Sub
    

    应该这样做…

    去掉字段名中的空格,以后你会感谢自己的。查看交叉表查询向导。回到你被困的地方。好的,我已经编辑了我的问题。希望这能增加清晰度。ClassID和StudentID都是数字,还是有文本的数据类型?您的记录集应该检索StudentID/ClassID的10条(或更少)记录,然后逐个循环遍历记录,并基于TestID写入相应的文本框。使用rst.movefirst,Do直到rst.eof,moveNext应该执行您想要的操作。您似乎非常接近。1)您的
    mmySQL
    作业中有一个错误-在和之前需要有一个空格,即
    Me.ClassCombo1&”和StudentID=“
    ;2) 不要调用
    MoveFirst
    ,因为记录光标无论如何都将位于第一条记录(如果有);3) 如果你正处于子程序的末尾,不要麻烦调用
    Close
    ,或者显式地将对象引用设置为
    Nothing
    ——如果Access没有自动执行此操作,那么这将是一个严重的错误,会引起是否可以信任其中任何一个的问题。Chris,非常感谢你的回答。我能够修改我找到的一些其他代码,并且能够继续前进。尽管如此,您的解决方案似乎非常优雅,我打算在有更多时间时尝试一下。再次感谢你。