Delphi 使用DAO执行查询
我想使用DAO对Access数据库执行一系列查询。“Database.Execute()”方法似乎适合这种情况,并指出它只能执行“操作查询”,即不返回结果集()的查询。对于返回记录的查询,可以使用“Database.OpenRecordset()”。如果传递了错误类型的查询,这两种方法都会引发异常Delphi 使用DAO执行查询,delphi,ms-access,dao,Delphi,Ms Access,Dao,我想使用DAO对Access数据库执行一系列查询。“Database.Execute()”方法似乎适合这种情况,并指出它只能执行“操作查询”,即不返回结果集()的查询。对于返回记录的查询,可以使用“Database.OpenRecordset()”。如果传递了错误类型的查询,这两种方法都会引发异常 在列表中既有操作查询又有选择查询,如何预先决定哪些将返回记录,哪些不返回记录?此信息适用于查询类型。因此: 执行SELECT命令的所有查询。。。从…起是选择查询 所有插入、更新和删除都是操作查询
在列表中既有操作查询又有选择查询,如何预先决定哪些将返回记录,哪些不返回记录?此信息适用于查询类型。因此:
- 执行SELECT命令的所有查询。。。从…起是选择查询
- 所有插入、更新和删除都是操作查询
您只需检查查询sql命令文本,查看它是否以上述任何关键字开头,并相应地执行操作。请注意,无论查询是否返回结果集,都可以使用ADO Execute方法 但是你真的想执行所有的“查询”吗?如果它们包含SQLDDL呢?考虑使用这个SQL DDL代码创建<代码>过程<代码>:< /p>
CREATE PROCEDURE qryDropMe AS DROP PROCEDURE qryDropMe;
)() Access维护一个名为MSysObjects的隐藏系统表,其中包含一个字段(标志),该字段存储一个指示查询类型的值。您可以使用列表中的每个查询名称尝试以下函数,并使用返回值确定是使用Database.Execute()还是Database.OpenRecordset() 该函数要求MSysObjects具有读取权限。我听说一些Access 2007用户被拒绝读取MSysObjects的报告。但是,我在Access 2007中没有遇到这个问题 我测试了几种查询类型以确定标志值。如果您的查询之一是我没有测试的类型,则函数将返回无法识别的标志值。您可以修改该函数以包含该标志类型 我测试的唯一DDL查询是DROP TABLE(Flags=96) 另外,请注意,并非所有“选择…从…”查询都是出于您的目的而进行的选择查询(返回记录集)。诸如“从旧表中将字段选择为新表”之类的查询不会返回记录,Access UI将其分类为生成表查询
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连接比ADO连接稍微聪明一些,其中连接保存一个“错误”集合并返回一些其他数据,如受影响的记录数?受@HansUp回答的启发,我进一步研究了DAO接口提供的QueryDef结构。该结构有一个“Type”属性,我可以使用它来区分不同的查询类型()。我最终实现了以下功能:
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;
函数TAccessDatabase.SQLExec(AName,AQuery:String):整数;
变量
I:整数;
QDef:QueryDef;
qdef存在:布尔;
开始
结果:=0;
//在数据库中查找querydef
QDefExists:=False;
对于I:=0到DB.querydfs.Count-1 do
开始
QDef:=DB.querydfs[I];
如果QDef.Name=AName,则
开始
QDefExists:=真;
中断;//-->
结束;
结束;
//如果查询定义不存在,则创建查询定义
如果不存在,那么
开始
QDef:=DB.CreateQueryDef(AName,AQuery);
//需要刷新才能获得正确的QDef.Type_
DB.querydfs.Refresh;
结束;
//仅当查询不是SELECT时才执行该查询
如果QDef.Type uqselect,则
开始
db.Execute(AQuery,dbunconsistent);
结果:=DB.RecordsAffected;
结束;
结束;
谢谢所有有用的答案和备注。
“执行SELECT……的所有查询都是SELECT查询”——但它们不返回结果集,例如考虑“查询”是否包含SQLDDL“创建视图MyView为客户选择客户机ID”;这不是选择查询,而是创建查询,不会给出任何结果。。。这一个属于“操作查询”类别,与所有DDL查询一样。那么回到原始问题:“我如何预先决定哪些将返回记录,哪些将不返回记录?”换句话说,您如何判断包含SELECT关键字的查询是否将返回结果集?插入到..选择。。是另一个示例构造。这个构造也不会返回任何结果集,因为它基本上是一个插入。引用我的回答:“…检查查询sql命令文本,看看它是否以上述任何关键字开头…”根据需要,可以随意向这两个组添加一些其他关键字(如DDL语句CREATE、DROP…)嗯,那么以PARAMETERS关键字开头,后跟SELECT关键字的查询呢?一个以SELECT关键字开头,然后使用到[NewTableName]中,因此不返回结果集的如何?谢谢你的提议,但我觉得我无法编辑你的答案来改进它;相反,它从根本上是有缺陷的,解析SQL无论如何都不是小事。我认为你这里没有一个可行的系统。从逻辑上讲,更新就是删除和插入。以上内容表明,对于Access数据库引擎,更新是删除和交叉表!有一天。不更新记录中所有字段的更新怎么会是逻辑删除和插入?@oneday-我想你在没有的地方读到了更具意义的内容-标志列表就是一个flags@DJ:根据我的经验,名为“flags”的枚举建议使用位掩码,更不用说值(16、32、64…)@Tony Toews:因为它使用未提及的列的现有值,并且一次发生。您是否在更新触发器上使用过SQL Server?您将有两个名为“inserted”和“deleted”的逻辑表,而不是一个名为“updated”的逻辑表。为什么您甚至要执行仅选择的查询,除非您