我一直在使用VBA检查Access 2000数据库中的所有查询、表单和模块,但这可能非常乏味和缓慢。最近,我决定仔细查看Access中的系统表,特别是MSysQueries和MSysObjects。我可以使用这些表更快地检查数据库中的对象吗?当然,这些表是只读的,所以在不返回VBA的情况下,我无法通过它们对数据库进行任何修改。MSysQueries中的属性是什么意思?
嗯,我在谷歌群组上看到了这篇文章。我对自己的表格做了进一步的调查,并想分享一张我受已经完成的工作启发创建的信息表格。
每个查询可以占用表中的多行。
具有属性0的行是查询的开头。
属性为1的行表示查询的类型。
- 标志值1=SELECT查询
- 标志值2=SELECT。。。INTO查询或生成表查询。Name1将具有所创建的表的名称
- 标志值3=INSERT查询;Name1将具有要插入的表的名称
- 标志值4=UPDATE查询
- 标志值5=DELETE查询
- 标志值6=交叉表查询(TRANSFORM)
- 标志值9=UNION查询
属性为2的行(可能有多个)是查询的每个形式参数。Flag列表示数据类型(即dbText的"10"),Name1列表示参数的名称。如果没有属性为2的行,那么查询就没有正式参数。
属性为3的行表示UNION或DISTINCT关键字的存在。
- 标志值0=无特殊情况
- 标志值1=UNION ALL
- 标志值2=SELECT DISTINCT
- 标志值3=UNION
- 标志值8=SELECT DISTINCTROW
- 标志值9=查询主字段和子字段
属性为4的行表示查询是否来自外部数据库。如果属性4存在,则Name1将包含源。
属性为5的行(可能有多个)指示在查询中找到的每个表。如果查询是UNION查询,则Expression字段在UNION关键字上具有拆分,Name2字段具有系统生成的表别名。对于查询中的所有其他表,Name1是表的名称,Name2是别名(如果有)。
属性为6的行(可能有多个)表示查询中的每个字段或表达式。如果查询没有属性6,则假定行为是包括所有字段。Expression字段包含每个字段表达式或名称,Name1包含字段别名(如果有)。
- 标志值0=字段或表达式的值
- 标志值1=字段是交叉表查询中的列标题
- 标志值2=字段是交叉表查询中的行标题
属性为7的行(可能有多个)表示每个单独的联接"ON"表达式。Expression字段包含实际的联接表达式。Name1包含联接中的第一个表。Name2包含联接中的第二个表。
- 标志值1=内部联接
- 标志值2=左联接
- 标志值3=右联接
属性为8的行包含Expression字段中的整个WHERE子句。如果没有where子句,则从查询中省略属性8。
属性为9的行(可能有多个)表示查询的Group By子句中的每个Group By表达式。"表达式"字段按表达式包含每组。
- 标志值0=字段或表达式的值
- 标志值1=字段是交叉表查询中的列标题
- 标志值2=字段是交叉表查询中的行标题
属性为11的行(可能有多个)指示查询的Order By子句中的每个Order By表达式。"表达式"字段按表达式包含每个顺序。Name1有"D"或"D"表示按降序排序。
属性为255的行是查询的末尾。
我不太确定Order字段的作用,但我确实发现它不是Null,尽管它有时有一个空字符串的值,但它并不总是有这个值。空字符串出现在属性5、6、7和9上,但这些属性并不总是空字符串。
感谢@Bobort的出色解释,我能够创建一个查询,列出当前数据库中的所有查询,以及它们的输入表/查询、查询类型和目标表(用于操作查询)
我想我可以在这里分享。
SELECT MSysObjects.Name AS queryName,
Mid("SelectMakTblAppendUpdateDeleteXtab 777777PassThUnion ",([msysqueries]![Flag]-1)*6+1,6) AS queryType,
src.Name1 AS [Input],
MSysQueries.Name1 AS Target
FROM (MSysQueries INNER JOIN MSysObjects ON MSysQueries.ObjectId = MSysObjects.Id)
LEFT JOIN (select * from MSysQueries WHERE Attribute = 5 ) AS src
ON MSysQueries.ObjectId = src.ObjectId
WHERE (((MSysObjects.Name)>"~z") AND ((MSysQueries.Attribute) =1))
ORDER BY MSysObjects.Name, src.Name1;
要使用,只需在SQL视图中创建一个查询并粘贴上面的代码。
关于Bobort和iDevlop的回答:
属性为1的行表示查询的类型。
- 标志值7=DDL查询(例如
CREATE TABLE...
) - 标志值9=传递查询
属性为3的行表示谓词。
- 标志值1=所有值,或UNION All(如果是UNION查询)
- 标志值4=WITH OWNERACCCESS OPTION
- 标志值16=顶部N
- 标志值48=前N百分比
属性为5的行(可能有多个)表示在查询中找到的每个FROM表/查询
- 表达式包含FROM源,如果是UNION查询则包含SELECT语句
属性为10的行在Expression字段中包含整个HAVING子句。如果没有HAVING子句,则查询中将省略属性10。
Order
字段是一个包含4字节数组的BIG-ENDIAN二进制值(二进制字段可以使用VBA添加,但不能使用UI添加,除非您从系统表中的二进制字段复制和粘贴。)然而,在大多数数据库中,在MSysQueries
表中,您不太可能遇到大于255的二进制值,因此,您可以通过检查索引3处的字节来缩短到字节的转换。例如:
Sub EnumOrder()
Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset( _
" SELECT * FROM MSysQueries " & _
" WHERE Attribute = 6 " & _
"ORDER BY ObjectId Asc, [Order] Asc")
With rst
Do While Not .EOF
Debug.Print .Fields("ObjectId"), .Fields("Order")(3)
.MoveNext
Loop
.Close
End With
End Sub
属性3会出现累积值。因此,附加项目包括:
- 标志12 SELECT DISTINCT。。。。具有OWNERACCESS选项
- 标志18选择DISTINCT TOP(即2+16)
- 标志24选择DISTINCTROW顶部(即8+16)
- 标志50选择差异最高百分比(即2+48)
- 标志56选择差异最高百分比(即8+48)
我写了一篇关于MSysQueries表工作原理的扩展文章。请参阅Access如何存储查询。