【问题标题】:Python: Reading an Access databasePython:读取 Access 数据库
【发布时间】:2020-02-13 21:20:49
【问题描述】:

这个 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: sql 'SELECT * FROM table' 执行失败: ('HY000', "[HY000] [Microsoft][ODBC Microsoft Access Driver] 指定字段 'different_table.[field] 可以引用多个 SQL 语句的 FROM 子句中列出的表。 (-3007) (SQLExecDirectW)")

【问题讨论】:

  • 你添加的数据字段类型是什么?是多值字段、附件类型等吗?
  • Parfait,这只是 MS Access 查询中的一个简单 iif 语句,如果满足某个要求,它将 qty 乘以 2。此后我删除了该字段,但尝试在 Python 中加载时仍然遇到相同的错误。
  • 尝试使用MSAccess.exe Compact & Repair数据库
  • Parfait,我按照你的建议完成了压缩和修复。不幸的是,我在运行 python 脚本时仍然收到相同的错误消息。
  • FROM 中的 table 实际上是表还是存储查询?尝试显式指定列,不要在SELECT 中使用*

标签: python pandas ms-access pyodbc


【解决方案1】:

如前所述,SQL 查询中的 table 可能不是实际的表,而是存储的查询或视图(如在其他数据库中使用的那样),可像表一样查询。 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 子句中使用了*。因此,添加到 any 引用表的 any 新列被拉入最终查询。

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

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

  • 当查询中引用了多个表(即c.CustomerIDo.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++。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-14
    • 2021-09-20
    • 2020-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多