Согласно Горду Томпсону здесь: Получение предупреждения при использовании объекта соединения pyodbc с пандами
pyodbc не устарел, и я согласен, для баз данных с диалектом SQLAlchemy. Но я использую непонятную базу данных - Providex, на которой основан Sage 100 ERP. Я могу использовать pyodbc, как в cnxn = pyodbc.connect("DSN=SOTAMAS16",autocommit=True)
, для доступа/чтения данных с помощью read_sql() в 1.4.47 или ниже с предупреждениями. Я не могу и не хочу записывать данные в базу с интерфейсом ODBC. Я также не хочу, чтобы меня принуждали использовать старые версии Pandas. Я не против SQLAlchemy. Есть ли способ использовать мой ODBC DSN, возможно, создав свой собственный диалект SQLAlchemy с помощью драйвера ODBC PVXODBC?
Я могу приблизиться к тому, чтобы использовать SQLAlchemy с
sql3 = "SELECT ItemCode FROM CI_Item"
engine = create_engine("mssql+pyodbc://user:pwd@SOTAMAS16?autocommit=True")
items= pd.read_sql_query(sql=text(sql3), con=engine.connect())
на что я получаю эту ошибку: «pyodbc.Error: ('37000', '[37000] [ProvideX] [Драйвер ODBC] Ожидаемый лексический элемент не найден: FROM (1015) (SQLExecDirectW)')" что имеет смысл, поскольку база данных не является сервером Microsoft Sequel. Это самый близкий диалект, который я нашел.
Почему бы не использовать pyodbc
для выполнения запроса и загрузки результатов с помощью pd.DataFrame.from_records
. Что-то вроде:
import pandas as pd
import pyodbc
cnxn = pyodbc.connect('DSN=SOTAMAS16', autocommit=True)
cursor = cnxn.cursor()
cursor.execute('SELECT ItemCode FROM CI_Item')
cols = [c[0] for c in cursor.description]
df = pd.DataFrame.from_records(cursor.fetchall(), columns=cols)
Спасибо @Corralien, это работает. Я добавил одну небольшую вариацию: pd.DataFrame.from_records(cursor.fetchall(), columns=[col[0] for col in cursor.description]) Это дает мне имена столбцов. Просто жаль, что если я хочу перейти на Pandas 2.0, мне придется изменить весь мой существующий код, чтобы он не использовал read_sql.
Спасибо и за этот трюк :-) Я обновил свой ответ, связанный с вашими комментариями.
Я добавил одну дополнительную строку в свой код df = df.apply(pd.to_numeric, errors = "ignore")
Моя база данных содержит некоторые столбцы как десятичные, и панды с трудом выполняли с ними математические операции, пока я не изменил тип на плавающий. Эта строка кода меняет для меня числовые столбцы.
Который из? Это решает вашу проблему?