7

我一直在使用 VBA 检查我的 Access 2000 数据库中的所有查询、表单和模块,但它可能非常乏味和缓慢。最近,我决定仔细研究一下 Access 中的系统表,特别是 MSysQueries 和 MSysObjects。我可以使用这些表更快地检查数据库中的对象吗?当然,这些表是只读的,所以我不能通过它们对数据库进行任何修改而不返回VBA。MSysQueries 中的属性是什么意思?

4

4 回答 4

15

好吧,我在 Google 群组上看到了这篇文章。我对自己的表格进行了进一步调查,并希望分享一张我在已完成工作的启发下创建的信息表格。

每个查询可以占用表中的多行。

属性为 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 上,但这些属性并不总是空字符串。

于 2013-06-26T19:52:26.797 回答
4

感谢@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 视图中创建一个查询并粘贴上面的代码。

于 2014-04-24T14:56:54.773 回答
3

除了 Bobort 和 iDevlop 的回答:

属性为 1 的行表示查询的类型。

  • 标志值 7 = DDL 查询(例如CREATE TABLE...
  • 标志值 9 = 通过查询

具有属性 3 的行表示谓词。

  • 标志值 1 = 所有值,或 UNION ALL(如果是 UNION 查询)
  • 标志值 4 = WITH OWNERACCESS OPTION
  • 标志值 16 = TOP N
  • 标志值 48 = TOP N PERCENT

具有属性 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
于 2016-07-08T05:08:05.720 回答
3

属性 3 出现累积值。因此其他项目包括:

  • 标志 12 SELECT DISTINCT.... 带有 OWNERACCESS 选项
  • 标志 18 SELECT DISTINCT TOP(即 2+16)
  • 标志 24 SELECT DISTINCTROW TOP(即 8+16)
  • 标志 50 SELECT DISTINCT TOP PERCENT(即 2+48)
  • 标志 56 SELECT DISTINCTROW TOP PERCENT(即 8+48)

我写了一篇关于 MSysQueries 表工作原理的扩展文章。请参阅Access 如何存储查询

于 2019-02-02T15:57:41.463 回答