如何使用python从MS Access数据库中检索所有保存的查询?

问题描述 投票:0回答:1

基本上,我正在使用python比较2个访问数据库。

我无权手动打开任何访问文件,必须完全在python中完成!

我需要检索完整列表

  • 查询名称
  • 相关查询代码

我将不知道查询的名称是什么。

我已经尝试了许多已经[[接近起作用的解决方案,我在下面列出了三个解决方案。


部分解决方案1

] >>我几乎使用win32comCurrentDb.QueryDefs方法来检索每个查询的代码。

但是,连接的顺序似乎没有确定性地存储在2个数据库之间。(它似乎取决于MSysQueries中条目的顺序)

即在一个数据库中,联接的文本可以是

on Table1.ColumnA = Table2.ColumnA & Table1.ColumnB = Table2.ColumnB

和另一个

on Table1.ColumnB = Table2.ColumnB & Table1.ColumnA = Table2.ColumnA

显然,这些将导致相同类型的联接,但不会导致完全相同的查询文本。

如果我直接比较文字,则它们不匹配。比较之前处理文本似乎是一个坏主意,有很多极端情况。

样本代码

objAccess = Dispatch("Access.Application") objAccess.Visible = False counter = 0 query_dicts = {} for database_path in (new_database_path, old_database_path): # Open New DB and pull stored queries into dict objAccess.OpenCurrentDatabase(database_path) objDB = objAccess.CurrentDb() db_query_dict = {} for stored_query in objDB.QueryDefs: db_query_dict[stored_query.name] = stored_query.sql query_dicts[("New" if counter == 0 else 'Old')] = db_query_dict objAccess.CloseCurrentDatabase() counter += 1


部分解决方案2

] >>第一个解决方案失败后,我尝试在MSysQueries上编写查询并强制执行排序。但是,pyodbc没有对该表的读取权限!

看来您无法授予来自python本身的读取访问权限,这是一个问题,在这里可能是错误的。

查询:

SELECT MSysObjects.Name , MSysQueries.Attribute , MSysQueries.Expression , MSysQueries.Flag , MSysQueries.Name1 , MSysQueries.Name2 FROM MSysObjects INNER JOIN MSysQueries ON MSysObjects.Id = MSysQueries.ObjectId order by MSysObjects.Name , MSysQueries.Attribute , MSysQueries.Expression , MSysQueries.Flag , MSysQueries.Name1 , MSysQueries.Name2

部分解决方案3

] >>[我试图做的另一件事是让python将VBA模块存储到数据库中,这会将元信息写入表,然后通过pyodbc读出该表。

i可以添加模块,但是访问数据库不断提示输入模块名称。我找不到有关如何使用方法调用命名模块的文档

示例代码:

import win32com.client as win32 import comtypes, comtypes.client import win32api, time from win32com.client import Dispatch strDbName = r'C:\Users\Username\SampleDatabase.mdb' objAccess = Dispatch("Access.Application") # objAccess.Visible = False objAccess.OpenCurrentDatabase(strDbName) objDB = objAccess.CurrentDb() xlmodule = objAccess.VBE.VbProjects(1).VBComponents.Add(1) # vbext_ct_StdModule xlmodule.CodeModule.AddFromString(Constants.ACCESS_QUERY_META_INFO_MACRO) objAccess.Run("CreateQueryMetaInfoTable") objAccess.CloseCurrentDatabase() objAccess.Quit()

我尝试添加的宏。

Sub CreateQueryMetaInfoTable() Dim sql_string As String # Create empty table CurrentDb.Execute ("Create Table QueryMetaInfoTable (QueryName text, SqlCode text)") Dim qd As QueryDef For Each qd In CurrentDb.QueryDefs # insert values sql_string = "Insert into QueryMetaInfoTable (QueryName, SqlCode) values ('" & qd.Name & "', '" & qd.SQL & "')" CurrentDb.Execute sql_string Next End Sub

[基本上,我正在使用python比较2个访问数据库。我无权手动打开任何访问文件,必须完全在python中完成!我需要检索查询的完整列表...

在@Gord Thompson的帮助下,我现在有了一个可行的解决方案。

我需要与OLEDB连接以授予读取访问权限1,使用所需的信息生成一个非系统表,然后通过熊猫通过ODBC读回该表。

CONNECTION_STRING_OLEDB = "PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE={};Jet OLEDB:System Database={};" ACCESS_QUERY_META_INFO_CREATE = """SELECT MSysObjects.Name , MSysQueries.Attribute , MSysQueries.Expression , MSysQueries.Flag , MSysQueries.Name1 , MSysQueries.Name2 INTO QueryMetaInfo FROM MSysObjects INNER JOIN MSysQueries ON MSysObjects.Id = MSysQueries.ObjectId order by MSysObjects.Name , MSysQueries.Attribute , MSysQueries.Expression , MSysQueries.Flag , MSysQueries.Name1 , MSysQueries.Name2""" ACCESS_QUERY_META_INFO_READ = """select * from QueryMetaInfo order by Name , Attribute , Expression , Flag , Name1 , Name2;""" ACCESS_QUERY_META_INFO_DROP = "DROP TABLE QueryMetaInfo" connection = win32com.client.Dispatch(r'ADODB.Connection') DSN = CONNECTION_STRING_OLEDB.format(database_path, r"C:\Users\C218\AppData\Roaming\Microsoft\Access\System.mdw") connection.Open(DSN) cmd = win32com.client.Dispatch(r'ADODB.Command') cmd.ActiveConnection = connection cmd.CommandText = "GRANT SELECT ON MSysObjects TO Admin;" cmd.Execute() connection.Execute(ACCESS_QUERY_META_INFO_CREATE) connection.Close() # connect with odbc to read the query meta info into pandas connection_string = Constants.CONNECTION_STRING_ACCESS.format(database_path) access_con = pyodbc.connect(connection_string) access_cursor = access_con.cursor() df = pd.read_sql(ACCESS_QUERY_META_INFO_READ, access_con) # drop table after read access_cursor.execute(ACCESS_QUERY_META_INFO_DROP) access_cursor.commit

python ms-access pyodbc
1个回答
1
投票
在@Gord Thompson的帮助下,我现在有了一个可行的解决方案。
© www.soinside.com 2019 - 2024. All rights reserved.