我想使用DAO对Access数据库执行查询列表。 “Database.Execute()”方法似乎适用于此,并注释它只能执行“操作查询”,即不返回结果集(MSDN reference)的查询。对于返回记录的查询,可以使用“Database.OpenRecordset()”。如果传递了错误类型的查询,则两种方法都会抛出异常。
在列表中同时进行操作查询和选择查询如何预先确定哪些将返回记录,哪些不会?
答案 0 :(得分:1)
请注意,无论查询是否返回结果集,都可以使用ADO Execute方法。
但你真的想要执行所有'查询'吗?如果它们包含SQL DDL怎么办?考虑使用此SQL DDL代码创建PROCEDURE
:
CREATE PROCEDURE qryDropMe AS DROP PROCEDURE qryDropMe;
)
答案 1 :(得分:1)
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;”不返回记录,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
答案 2 :(得分:1)
受@ 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;
谢谢大家的有用答案和评论。
答案 3 :(得分:0)
为什么不抓住抛出的异常并进行分析呢?
你有没有办法使用beginTrans / Rollback指令?然后,您可以发送SQL命令,收集错误,然后回滚事务,保持数据库不变。
使用ADO连接怎么样,比ADO连接更聪明,连接保持'错误'集合并返回一些其他数据,如受影响的记录数?
答案 4 :(得分:-1)
此信息适用于查询的类型。所以:
您只需检查查询sql命令文本,看它是否以上述任何关键字开头,并采取相应的行动。