【问题标题】:MS access SELECT INTO in vbaMS 在 vba 中访问 SELECT INTO
【发布时间】:2012-07-05 17:11:50
【问题描述】:

我的应用程序的某些功能存在一些问题。有一个特定的实例,我在表单上有一个“待定类”的实例供管理员查看。表单中填充了与此待定课程相关联的学生。在他们的成绩完成后,我在页脚有一个按钮,可以从我的“待定”表中删除该课程并将成绩添加到所有学生。这行得通。 但是,我想在从待处理中删除之前将这个待处理的课程(它只有课程名称、日期和教师)复制到已完成的课程表中。由于除了主键(类号)之外没有关于该类的数据在整个表单中保留,因此我无法将该行的其他字段(类名、日期)填充到我已完成的类表中。

我正在尝试在 VBA 中执行“SELECT INTO”操作来获取这些值。事情是这样的:

   dim cname as String
   dim classdate as Date
   dim pid as integer
   dim teacher as String
   dim qry as String

    pid = [Forms]![frmClasses]![txtID]

   qry = "Select className INTO cname FROM tblPending WHERE tblPending.id = " & " ' " & pid & " ' " & ";"

   db.execute qry
   debug.print qry
   debug.print cname   

从这里开始,我对其他变量执行相同的操作,构建我的 INSERT 查询并执行它。问题是——我的选择不起作用。 Debug.print 显示局部变量从未从 SELECT INTO 语句初始化。有什么想法吗?

【问题讨论】:

  • 这是一个生成表查询,我想你想要一个追加查询。我真的不认为你的身份证是文字。如果 pid 为空(空),那么 [Forms]![frmClasses]![txtID] 似乎很可能是空的。尝试使用 Me 关键字,看看它提供了哪些控件名称——Me。会调出智能感知。
  • 在这种情况下我不能使用 Me 关键字。我没有使用参数打开表单,而是使用前一个表单中的字段。带有 txtID 的字段(带有相关类 ID 的文本框)位于前一个表单中。此外,这部分正在按预期工作。打印出来的查询是“Select ClassName INTO cName FROM tblPending WHERe tblPending.id = '17';”我还尝试删除 id 条件周围的单引号,因为它是一个整数,但它没有任何区别。
  • 根据我从上一个表单中所做的选择,我得到了正确的对应类 ID
  • SELECT INTO 创建一个表,你想要的是 INSERT INTO,它附加到一个表中。另外,添加db.execute qry, dbFailOnerror - 如果表存在,您的查询将失败,否则您不会收到警告。
  • 在 MS Access 中,您可以使用 DLookup() 来“选择变量office.microsoft.com/en-us/access-help/… 您可能会发现其他有用的“域函数”:DMin();最大(); DAvg();等

标签: sql ms-access vba


【解决方案1】:

首先,将所有类放在一个表中并设置“NotPending”或“Completed”列会更好。
拥有两个相同的类表并将值从一个表移到另一个表以指示状态更改是糟糕的数据库设计。


如果您真的需要通过使用两个表并复制行来执行此操作,那么您需要 an INSERT INTO query(和 not SELECT INTO),正如 Remou 在 cmets 中已经提到的那样,因为 @987654327 @ 创建一个新表(或覆盖现有的同名表,如果已经存在的话)。

INSERT INTO 的语法如下所示:

INSERT INTO CompletedClassTable (ClassName, Teacher)
SELECT ClassName, Teacher FROM tblPending WHERE id = 123

最后,你在评论中问了这个问题:

所以 SELECT INTO 在 Access 中与 Oracle 完全不同?在 Oracle 和 PL/SQL 中,您可以在变量或表中选择一行。 Access中不能选择变量吗?

要将行加载到变量中,您需要使用Recordset

将查询加载到 Recordset 并输出 ClassName 字段的示例代码:

Dim RS As DAO.Recordset

Set RS = CurrentDb.OpenRecordset("SELECT * FROM tblPending WHERE id = 123")
If Not RS.EOF Then
    Debug.Print RS("classname")
End If
RS.Close
Set RS = Nothing

【讨论】:

  • 我觉得我对 'select into' 的预期用途被误解了。我的意图是 SELECT INTO 从行中获取一个值,并将它从我知道的表中分配给 VBA 中的一个变量PK,就像在 PL/SQL 中一样。正如您提到的,通过 RS 进行迭代似乎是 Access 的比较解决方案。就数据库设计而言,待处理表和已完成表并不完全相同。我已完成的表具有待定表的所有字段,并添加了几个字段。在这种情况下,我将一个已完成的课程和一个正在进行(待定)的课程视为不同的实体
  • 我不确定我的问题是否模棱两可或我的意图不清楚,但我会继续并将其标记为“已回答”——不可能在VBA 将行中的值分配给变量。为此,我需要打开必要查询的记录集。您认为这是一个适当的总结吗?
  • 我不了解 Oracle 和 PL/SQL,所以除了你所说的之外,我不知道它是如何工作的。要将行中的值分配给变量,您需要Recordset,或者,如果您只需要一个值,则需要you can use DLookup。但是,如果您只想将一行复制到另一个表中,我会使用 INSERT INTO 查询。 IMO 这是最简单的方法。
  • 听起来不错,感谢您的意见。我会继续接受这个并认为它已回答
【解决方案2】:

您似乎想从tblPending 中检索一个文本值className,其中tblPending.id 与您的文本框中的值txtID 匹配,并将该文本值存储在一个名为cname 的字符串变量中.

如果该解释是正确的,您就不必为查询和记录集而烦恼。只需使用 DLookup Function 检索值,类似于此未经测试的代码示例。

Dim cname As String
Dim pid As Integer
Dim strCriteria As String
pid = [Forms]![frmClasses]![txtID]
strCriteria = "id = " & pid
cname = Nz(DLookup("className", "tblPending", strCriteria), vbNullString)
Debug.Print "cname: '" & cname & "'"

注意事项:

  1. 我假设tblPendingid 字段的数据类型是数字。如果实际上是文本数据类型,将strCriteria改成这样:

    strCriteria = "id = '" & pid & "'"

  2. DLookup() 如果未找到匹配项,则返回 Null。由于我们将函数的返回值分配给字符串变量,因此我使用Nz() 将 Null 转换为空字符串。或者,您可以将 cname 声明为 Variant(以便它可以接受 Null 值)并去掉 Nz()

【讨论】:

  • 这也有效。在您对我的问题发表评论后,我使用 dLookup 实现了我的表单^ 并且它有效(我的代码类似于您提供的此答案的代码)。以前,我在以前的表单上使用隐藏控件来存储变量——这是一个丑陋的解决方法,因为我不知道 DLookup()。感谢您让我意识到这一点,我相信我将来会经常使用它,因为我更喜欢在 VBA 中编写插入、更新和删除的代码,而不是使用向导提供的默认操作。
  • 当我意识到您真的想选择 一个变量 时,DLookup() 成为了简单的解决方案。当我第一次阅读您的问题时,我将目标误解为将 SELECTed 值存储在表中(新的或现有的)。
  • 我想雷穆和克里斯蒂安也是这么想的。我习惯于使用 SELECT INTO 将表中的值获取到 PL/SQL 中的局部变量中。这就是混乱的根源。我不想“SELECT INTO”,我想知道该操作的 Access 等效项是什么。 DLookup 是我们一直在寻找的答案。
猜你喜欢
  • 2013-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-12
  • 2019-04-03
相关资源
最近更新 更多