我想使用 DAO 对 Access 数据库执行查询列表。“Database.Execute()”方法似乎适合于此,并指出它只能执行“操作查询”,即不返回结果集的查询(MSDN 参考)。对于返回记录的查询,可以使用“Database.OpenRecordset()”。如果传递了错误类型的查询,这两种方法都会引发异常。

列表中同时存在操作查询和选择查询,我如何预先决定哪些将返回记录,哪些不会?

有帮助吗?

解决方案 3

受@ HansUp的回答启发,我研究了DAO接口提供的QueryDef结构。该结构具有“类型”。我可以用来区分不同查询类型的属性( MSDN ) 。我最终得到了以下实现:

function TAccessDatabase.SQLExec(AName, AQuery: String): Integer;
var
  I: Integer;
  QDef: QueryDef;
  QDefExists: Boolean;
begin
  Result := 0;

  // Lookup querydef in the database
  QDefExists := False;
  for I := 0 to DB.QueryDefs.Count - 1 do
  begin
    QDef := DB.QueryDefs[I];
    if QDef.Name = AName then
    begin
      QDefExists := True;
      break; //-->
    end;
  end;

  // Create query def if it doesn't exists
  if not QDefExists then
  begin
    QDef := DB.CreateQueryDef(AName, AQuery);
    // Refresh is required to get the correct QDef.Type_
    DB.QueryDefs.Refresh;
  end;

  // Execute the query only if it is not a SELECT
  if QDef.Type_ <> dbQSelect then
  begin
    db.Execute(AQuery, dbInconsistent);
    Result := DB.RecordsAffected;
  end;
end;

谢谢大家的有用答案和评论。

其他提示

请注意,无论查询是否返回结果集,都可以使用ADO Execute方法。

但你真的想要执行所有'查询'吗?如果它们包含SQL DDL怎么办?考虑使用此SQL DDL代码创建 PROCEDURE

CREATE PROCEDURE qryDropMe AS DROP PROCEDURE qryDropMe;

Access维护一个名为MSysObjects的隐藏系统表,其中包含一个字段(Flags),用于存储指示查询类型的值。您可以使用列表中的每个查询名称尝试以下函数,并使用返回值来确定是否使用Database.Execute()或Database.OpenRecordset()

该函数需要MSysObjects的读取权限。我听说过一些Access 2007用户被拒绝阅读MSysObjects的权限。但是,我没有遇到Access 2007的问题。

我测试了几种查询类型来确定Flags值。如果您的某个查询是我未测试的类型,该函数将返回Flags值为无法识别。您可以修改该函数以包含Flags类型。

我测试的唯一DDL查询是DROP TABLE(Flags = 96)。

另外,请注意并非所有“SELECT ... FROM ...”查询是为您的目的选择查询(返回记录集)。一个查询,例如“SELECT fields INTO newtable FROM oldtable;&quot;不返回记录,Access UI将其归类为Make Table查询。

Public Function QueryType(ByVal pQueryName As String) As String
    Dim lngFlags As Long
    Dim strType As String
    Dim strCriteria As String

    strCriteria = "[Name] = """ & pQueryName & """ And [Type] = 5"
    lngFlags = DLookup("Flags", "MSysObjects", strCriteria)

    Select Case lngFlags
    Case 0
        strType = "Select"
    Case 16
        strType = "Crosstab"
    Case 32
        strType = "Delete"
    Case 48
        strType = "Update"
    Case 64
        strType = "Append"
    Case 80
        strType = "Make Table"
    Case 96
        strType = "Drop Table"
    Case 128
        strType = "Union"
    Case Else
        strType = "Flags " & CStr(lngFlags) & " unrecognized"
    End Select

    QueryType = strType
End Function

为什么不抓住抛出的异常并进行分析呢?

你有没有办法使用beginTrans / Rollback指令?然后,您可以发送SQL命令,收集错误,然后回滚事务,保持数据库不变。

使用ADO连接怎么样,比ADO连接更聪明,连接保持'错误'集合并返回一些其他数据,如受影响的记录数?

此信息适用于查询的类型。所以:

  • 所有执行 a 的查询 选择 ...从 ...选择查询
  • 全部 插入, 更新, 删除动作查询

您只需检查查询 sql 命令文本以查看它是否以上述任何关键字开头并采取相应的操作。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top