Python: 读取 Access 数据库

Python: Reading an Access database

这个 Python 脚本直到今天都运行良好。我最近在 FROM 子句中列出的 table 中添加了一列。但是,它不是错误消息中列出的字段。

我也尝试过将 pyodbc.pooling = False 添加到代码中,但没有任何改变。

我很茫然,如有任何帮助,我们将不胜感激。

# Load the needed packages
import pyodbc
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns

# Define the connection parameters for MS Access
myDataSources = pyodbc.dataSources()
access_driver = myDataSources['MS Access Database']
file = '\Datasets\BookData.accdb'

# Connect to MS Access
cnxn = pyodbc.connect(Driver = access_driver, DBQ = file)

# Create a query which pulls in the correct data from MS Access
query = pd.read_sql_query('''SELECT * FROM table''', cnxn)

# Close the connection to the MS Access database
cnxn.close()

错误信息

DatabaseError: Execution failed on sql 'SELECT * FROM table': ('HY000', "[HY000] [Microsoft][ODBC Microsoft Access Driver] The specified field 'different_table.[field] could refer to more than one table listed in the FROM clause of your SQL statement. (-3007) (SQLExecDirectW)")

如前所述,SQL 查询中的 table 可能不是实际的 table,而是存储的查询或视图(如在其他数据库),它像 table 一样是可查询的。 Access 会引发错误,因为您在查询中的某处引用了一个没有别名 table 的重复字段。例如,CustomersOrders table 可以有一个名为 CustomerID 的字段,而您运行 这种形式:

SELECT CustomerID, ...
FROM Customers c
INNER JOIN Orders o
  ON c.CustomerID = o.CustomerID

甚至 运行 这个查询:

SELECT *
FROM Customers c
INNER JOIN Orders o
  ON c.CustomerID = o.CustomerID

然后在 Python 中调用此表单,由于 CustomerID:

的多个来源而引发错误
SELECT * FROM myStoredQuery

为什么现在而不是以前出现此错误?因为您可能在基础 table 中添加了相同的命名列,然后在顶级查询的 SELECT 子句中使用了 *。因此 any 添加到 any 引用的 table 的新列被拉入最终查询。

要解决这个问题,请考虑为任何潜在的名称冲突设置别名。正如大多数应用程序所建议的那样 运行ning SQL(超过 Python):

  • 始终明确标识 SELECT 子句中的列,不要使用 * 缩写。

  • 当在查询中引用多个 table 时(即 c.CustomerIDo.CustomerID),始终限定 table 列的来源例如连接。

查看调整后的 SQL:

SELECT c.CustomerID AS Customer_CustomerID, 
       o.CustomerID AS Order_CustomerID, 
       ...
FROM Customers c
INNER JOIN Orders o
  ON c.CustomerID = o.CustomerID

虽然写出每一列似乎很乏味,但这样做有助于提高可维护性,因为您可以控制并清楚地看到预期的输出并考虑重组的更改,例如新的、删除的、重复的或特殊命名的列。也许您也不需要 Pandas 中的所有列,因此可以在 SELECT 中省略它们。

最后,请记住 SQL 是一种声明性的专用语言,旨在以用户可读的形式向数据库引擎发送显式命令。引擎使用不同的代码来处理请求。对于 Access' Jet/ACE 引擎是 Window .dll,这可能是 C 或 C++。