Как изменить тип данных при создании SQL таблицы из DataFrame?

Хочу из DataFrame создать таблицу в SQL кодом ниже.

Таблица создаётся, но типы данных у этой таблицы не такие как мне хотелось бы. Столбцы у меня создаются под типом данных: bigint, text, а нужны int, varchar. Пробую методом dtype={} указать нужные мне типы данных, но таблица создаётся со всё теми же данными biging, text.

with ftp_client.open("/home/20211027165128-41.zip","r", bufsize=32768) as f:
    archive = zipfile.ZipFile(f, 'r')
    df = pd.read_csv(io.BytesIO(archive.read('GExternalGsmCell.csv')))
    df.to_sql('ZTE_GExternalGsmCell', con=connSQLBD_vf_work, schema='art',
         if_exists='replace', 
         dtype={'datefld': sqlalchemy.DateTime(),
                'intfld':  sqlalchemy.types.INTEGER(),
                'strfld': sqlalchemy.types.VARCHAR(length=255),
                'floatfld': sqlalchemy.types.Float(precision=3, asdecimal=True),
                'bigint': sqlalchemy.types.INT(),
                'text': sqlalchemy.types.VARCHAR(length=255),
                'booleanfld': sqlalchemy.types.Boolean})

Ответы (2 шт):

Автор решения: MaxU

Скорее всего проблема в несоответствии имен столбцов фрейма и ключей словаря, который вы передаете в параметр dtype. Например если у вас столбцы в upper case или mixed case, то и в параметре dtype они должны точно соответствовать именам столбцов фрейма.

Для простоты можно явно преобразовать все имена столбцов в DataFrame'е в lower case:

df.columns = df.columns.str.lower()

В параметр dtype при вызове DataFrame.to_sql(..., dtype={...}) нужно передавать словарь с точными именами столбцов DataFrame в виде ключей:

dtype = {
  "df_column_1_exact_name": sqlalchemy.types.INTEGER(),
  "df_column_3_exact_name": sqlalchemy.types.INTEGER(),
  "df_column_N_exact_name": sqlalchemy.types.VARCHAR(length=255),
}
df.to_sql("table_name", con=db_conn, dtype=dtype)

PS в dtype не обязательно передавать все имена столбцов - достаточно только тех, которые мы хотим задать явно.

→ Ссылка
Автор решения: ralph_lauren

Нашёл способ на сайте https://russianblogs.com/article/91571572655/ )

В нём создается функция def mapping_df_types(df) которая проходиться по первой строке каждого столбца и создаёт словарь для замены типа данных функцией dtype. Если строка относиться к типу данных object - она заменяет её на тип данных VARCHAR, если у строки тип данных int,float - заменяет на Float, Integer

def mapping_df_types(df):
    dtypedict = {}
    for i, j in zip(df.columns, df.dtypes):
        if "object" in str(j):
            dtypedict.update({i: sqlalchemy.types.NVARCHAR(length=255)})
        if "float" in str(j):
            dtypedict.update({i: sqlalchemy.types.Float(precision=2, asdecimal=True)})
        if "int" in str(j):
            dtypedict.update({i: sqlalchemy.types.Integer()})
    return dtypedict



with ftp_client.open("/home/20211027165128-41.zip","r", bufsize=32768) as f:
    archive = zipfile.ZipFile(f, 'r')
    df = pd.read_csv(io.BytesIO(archive.read('GExternalGsmCell.csv')))
    dtypedict = mapping_df_types(df)
    df.to_sql('ZTE_GExternalGsmCell', con=connSQLBD_vf_work, schema='art', if_exists='replace',dtype=dtypedict)
→ Ссылка