SQLAlchemy — Ошибка программирования на Python «Преобразование десятичной дроби теряет точность», «HY000»

#python #pandas #sqlalchemy

Вопрос:

Я использую механизм SQL Alchemy вместе с пандами и пытаюсь реализовать fast_executemany=True , но я получаю эту ошибку, когда пытаюсь вставить строки df-фреймов в базу данных SQL SERVER.

Мой код выглядит примерно так

 engine = create_engine('mssql pyodbc://@SERVER/DATABASE?driver=ODBC Driver 17 for SQL Server',
                       encoding="utf-8", fast_executemany=True)
conn = engine.connect()
 

Затем я разделяю фрейм данных на фрагменты и применяю pd.to_sql к каждому фрагменту

 chunksize = int(len(df) / 10) # 10%
with tqdm(total=len(df)) as pbar:
    for i, cdf in enumerate(chunker(df, chunksize)):
        replace_var = "replace" if i == 0 else "append"
        cdf.to_sql(output_table_name, con=engine, schema=output_schema, if_exists=replace_var, index=False)
        pbar.update(chunksize)
 

После попытки запустить первый фрагмент у меня возникла следующая ошибка

 Traceback (most recent call last):
  File "X:avelazquezretailparquet_import_to_sqlparquet_import.py", line 97, in <module>
    insert_with_progress(df, engine, table_output, schema)
  File "X:avelazquezretailparquet_import_to_sqlparquet_import.py", line 25, in insert_with_progress
    cdf.to_sql(output_table_name, con=engine, schema=output_schema, if_exists=replace_var, index=False)
  File "X:avelazquezretailvenvlibsite-packagespandascoregeneric.py", line 2872, in to_sql
    sql.to_sql(
  File "X:avelazquezretailvenvlibsite-packagespandasiosql.py", line 717, in to_sql
    pandas_sql.to_sql(
  File "X:avelazquezretailvenvlibsite-packagespandasiosql.py", line 1761, in to_sql
    sql_engine.insert_records(
  File "X:avelazquezretailvenvlibsite-packagespandasiosql.py", line 1350, in insert_records
    raise err
  File "X:avelazquezretailvenvlibsite-packagespandasiosql.py", line 1340, in insert_records
    table.insert(chunksize=chunksize, method=method)
  File "X:avelazquezretailvenvlibsite-packagespandasiosql.py", line 967, in insert
    exec_insert(conn, keys, chunk_iter)
  File "X:avelazquezretailvenvlibsite-packagespandasiosql.py", line 882, in _execute_insert
    conn.execute(self.table.insert(), data)
  File "X:avelazquezretailvenvlibsite-packagessqlalchemyenginebase.py", line 1286, in execute
    return meth(self, multiparams, params, _EMPTY_EXECUTION_OPTS)
  File "X:avelazquezretailvenvlibsite-packagessqlalchemysqlelements.py", line 323, in _execute_on_connection
    return connection._execute_clauseelement(
  File "X:avelazquezretailvenvlibsite-packagessqlalchemyenginebase.py", line 1478, in _execute_clauseelement
    ret = self._execute_context(
  File "X:avelazquezretailvenvlibsite-packagessqlalchemyenginebase.py", line 1842, in _execute_context
    self._handle_dbapi_exception(
  File "X:avelazquezretailvenvlibsite-packagessqlalchemyenginebase.py", line 2023, in _handle_dbapi_exception
    util.raise_(
  File "X:avelazquezretailvenvlibsite-packagessqlalchemyutilcompat.py", line 207, in raise_
    raise exception
  File "X:avelazquezretailvenvlibsite-packagessqlalchemyenginebase.py", line 1779, in _execute_context
    self.dialect.do_executemany(
  File "X:avelazquezretailvenvlibsite-packagessqlalchemydialectsmssqlpyodbc.py", line 550, in do_executemany
    super(MSDialect_pyodbc, self).do_executemany(
  File "X:avelazquezretailvenvlibsite-packagessqlalchemyenginedefault.py", line 714, in do_executemany
    cursor.executemany(statement, parameters)
sqlalchemy.exc.ProgrammingError: (pyodbc.ProgrammingError) ('Converting decimal loses precision', 'HY000')
 

Просто для завершения истории у меня была ошибка памяти до этого, но я обновил SQLAlchemy до последней версии и поместил ее в качестве драйвера ODBC Драйвер 17 для SQL Server, но теперь у меня эта проблема.

Я не нашел многого в Интернете, некоторые люди говорят, что используют dtype для изменения точности столбца, в котором у меня есть ошибка, но у меня есть 70 столбцов, и большинство из них-цифры 😛

Комментарии:

1. Проверьте таблицу, созданную первоначальным .to_sql() вызовом. Являются ли предположительно числовые столбцы созданными как varchar(max) ?

2. Привет, Горд, это работает! Я ищу числовые столбцы, которые панды идентифицировали как «объект», и я менял один за другим в панд. Спасибо! Как вы думаете, как я могу решить эту проблему более систематическим образом?

Ответ №1:

Горд был прав, там были числовые столбцы, созданные как varchar(max). Мне пришлось отлить их вручную при создании фрейма данных

Комментарии:

1. Рад, что исправление сработало! Не могли бы вы поделиться фрагментом кода, в котором показано внесенное вами изменение, которое его исправило? Это помогло бы другим, у кого такая же проблема!