首页 > 解决方案 > Python:读取 Access 数据库

问题描述

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

我也尝试添加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] 指定的字段 'different_table.[field] 可以引用多个表SQL 语句的 FROM 子句。(-3007) (SQLExecDirectW)")

标签: pythonpandasms-accesspyodbc

解决方案


如前所述,SQL 查询中的可能不是实际表,而是存储的查询或视图(如在其他数据库中使用的),它可以像表一样查询。Access 引发错误,因为在查询中的某处您引用了没有别名表的重复字段。例如,CustomersOrders表可以有一个名为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

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

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

  • 始终明确标识子句中的列,SELECT并且不要缩写*.

  • c.CustomerID当查询(即,或)中引用了多个表(o.CustomerID例如使用连接)时,始终用句号限定列的表源。

查看调整后的 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 是一种声明性的专用语言,旨在以用户可读的形式向数据库引擎发送显式命令。引擎使用不同的代码来处理请求。对于作为 Window .dll 的 Access 的 Jet/ACE 引擎,这可能是 C 或 C++。


推荐阅读