Python: чтение базы данных Access - PullRequest
0 голосов
/ 14 февраля 2020

Этот 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] [ODB C Драйвер Microsoft Access] Указанное поле 'Different_table. [field] может ссылаться на несколько таблиц, перечисленных в предложении FROM вашего оператора SQL. (-3007) (SQLExecDirectW) ")

1 Ответ

1 голос
/ 15 февраля 2020

Как уже говорилось, вероятная таблица в SQL запросе - это не фактическая таблица, а хранимый запрос или представление (как используется в других базах данных), к которому можно обращаться, как к таблице. При доступе возникает ошибка, потому что где-то в запросе вы ссылаетесь на дублирующееся поле без таблицы псевдонимов. Например, Customers и Orders таблиц могут иметь поле с именем 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 - это декларативный язык специального назначения, предназначенный для отправки явных команд ядру базы данных в удобочитаемой форме для пользователя. Движок использует другой код для обработки запросов. Для Access / Jet / ACE Engine, являющегося Windows .dll, это может быть C или C ++.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...