基本上,我正在使用python比较2个访问数据库。
我无权手动打开任何访问文件,必须完全在python中完成!
我需要检索完整列表
我将不知道查询的名称是什么。
我已经尝试了许多已经[[接近起作用的解决方案,我在下面列出了三个解决方案。
部分解决方案1
] >>我几乎使用win32com
和CurrentDb.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
] >>第一个解决方案失败后,我尝试在MSysQueries上编写查询并强制执行排序。但是,pyodbc没有对该表的读取权限!部分解决方案2
看来您无法授予来自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
] >>[我试图做的另一件事是让python将部分解决方案3
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中完成!我需要检索查询的完整列表...
我需要与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