Python Pandas to_sql,如何用主键创建表?

pat*_*_ai 23 python mysql primary-key pandas pandasql

我想用Pandas的to_sql函数创建一个MySQL表,它有一个主键(在mysql表中有一个主键通常很好),如下所示:

group_export.to_sql(con = db, name = config.table_group_export, if_exists = 'replace', flavor = 'mysql', index = False)
Run Code Online (Sandbox Code Playgroud)

但这会创建一个没有任何主键的表(甚至没有任何索引).

文档提到参数'index_label'与'index'参数结合使用可用于创建索引但不提及主键的任何选项.

文档

tom*_*omp 36

只需在使用pandas上传表后添加主键即可.

group_export.to_sql(con=engine, name=example_table, if_exists='replace', 
                    flavor='mysql', index=False)

with engine.connect() as con:
    con.execute('ALTER TABLE `example_table` ADD PRIMARY KEY (`ID_column`);')
Run Code Online (Sandbox Code Playgroud)

  • SQLite 不支持这一点。 (5认同)

yel*_*hin 18

从 pandas 0.15 开始,至少对于某些风格,您可以使用参数dtype来定义主键列。您甚至可以通过AUTOINCREMENT这种方式激活。对于 sqlite3,这看起来像这样:

import sqlite3
import pandas as pd

df = pd.DataFrame({'MyID': [1, 2, 3], 'Data': [3, 2, 6]})
with sqlite3.connect('foo.db') as con:
    df.to_sql('df', con=con, dtype={'MyID': 'INTEGER PRIMARY KEY AUTOINCREMENT'})
Run Code Online (Sandbox Code Playgroud)

  • 这对我不起作用 - 我收到错误:“ValueError:col 的类型不是 SQLAlchemy 类型”。 (9认同)
  • @DanSteingart OP 询问 MySQL,但 dtype 的字符串值仅支持 SQLite。一般来说,dtype 值需要是 SQLAlchemy 类型(例如 `Integer()`),所以我认为对于 SQLite 来说,传递字符串并可用于设置主键只是一个意外。在其他 SQL 后端中,这通常不起作用。 (4认同)

krv*_*kir 15

免责声明:这个答案更具实验性和实用性,但也许值得一提.

我发现该类pandas.io.sql.SQLTable已命名参数key,如果您为其指定了该字段的名称,则该字段将成为主键:

不幸的是,你不能只从DataFrame.to_sql()函数中转移这个参数.要使用它你应该:

  1. 创建pandas.io.SQLDatabase实例

    engine = sa.create_engine('postgresql:///somedb')
    pandas_sql = pd.io.sql.pandasSQL_builder(engine, schema=None, flavor=None)
    
    Run Code Online (Sandbox Code Playgroud)
  2. 定义函数类似于pandas.io.SQLDatabase.to_sql()但使用附加*kwargs参数传递给pandas.io.SQLTable在其中创建的对象(我刚刚复制了原始to_sql()方法并添加*kwargs):

    def to_sql_k(self, frame, name, if_exists='fail', index=True,
               index_label=None, schema=None, chunksize=None, dtype=None, **kwargs):
        if dtype is not None:
            from sqlalchemy.types import to_instance, TypeEngine
            for col, my_type in dtype.items():
                if not isinstance(to_instance(my_type), TypeEngine):
                    raise ValueError('The type of %s is not a SQLAlchemy '
                                     'type ' % col)
    
        table = pd.io.sql.SQLTable(name, self, frame=frame, index=index,
                         if_exists=if_exists, index_label=index_label,
                         schema=schema, dtype=dtype, **kwargs)
        table.create()
        table.insert(chunksize)
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用您SQLDatabase要保存的实例和数据框调用此函数

    to_sql_k(pandas_sql, df2save, 'tmp',
            index=True, index_label='id', keys='id', if_exists='replace')
    
    Run Code Online (Sandbox Code Playgroud)

我们得到类似的东西

CREATE TABLE public.tmp
(
  id bigint NOT NULL DEFAULT nextval('tmp_id_seq'::regclass),
...
)
Run Code Online (Sandbox Code Playgroud)

在数据库中.

PS你当然可以使用猴子补丁DataFrame,io.SQLDatabase并且io.to_sql()可以方便地使用这种解决方法.

  • 尼斯.谢谢.最后,我发现之前制作桌子并附加到桌面更简单. (2认同)