我想用Pandas'创建一个MySQL表。 to_sql函数有一个主键(在mysql表中有一个主键通常很好),如下所示:
group_export.to_sql(con = db, name = config.table_group_export, if_exists = 'replace', flavor = 'mysql', index = False)
但这会创建一个没有任何主键的表(或者甚至没有任何索引)。
文档中提到参数' index_label'结合了'指数'参数可用于创建索引但不提及主键的任何选项。
答案 0 :(得分:31)
只需在使用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`);')
答案 1 :(得分:14)
免责声明:这个答案更具实验性和实用性,但也许值得一提。
我发现类pandas.io.sql.SQLTable
已命名参数key
,如果为其指定字段名称,则此字段将成为主键:
不幸的是,你不能只从DataFrame.to_sql()
函数转移这个参数。要使用它,你应该:
创建pandas.io.SQLDatabase
实例
engine = sa.create_engine('postgresql:///somedb')
pandas_sql = pd.io.sql.pandasSQL_builder(engine, schema=None, flavor=None)
定义与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)
使用您的SQLDatabase
实例和要保存的数据框
to_sql_k(pandas_sql, df2save, 'tmp',
index=True, index_label='id', keys='id', if_exists='replace')
我们得到像
这样的东西CREATE TABLE public.tmp
(
id bigint NOT NULL DEFAULT nextval('tmp_id_seq'::regclass),
...
)
在数据库中。
PS您当然可以使用DataFrame
,io.SQLDatabase
和io.to_sql()
函数进行修补,以方便使用此变通方法。
答案 2 :(得分:0)
automap_base
的 sqlalchemy.ext.automap
(tableNamesDict是仅包含Pandas表的dict):
metadata = MetaData()
metadata.reflect(db.engine, only=tableNamesDict.values())
Base = automap_base(metadata=metadata)
Base.prepare()
除了一个问题之外,哪个会完美运行, automap要求表具有主键。好的,没问题,我确定Pandas to_sql
有办法表明主键......不。这是一个有点hacky的地方:
for df in dfs.keys():
cols = dfs[df].columns
cols = [str(col) for col in cols if 'id' in col.lower()]
schema = pd.io.sql.get_schema(dfs[df],df, con=db.engine, keys=cols)
db.engine.execute('DROP TABLE ' + df + ';')
db.engine.execute(schema)
dfs[df].to_sql(df,con=db.engine, index=False, if_exists='append')
我通过dict
的{{1}}进行迭代,获取用于主键的列的列表(即包含DataFrames
的列),使用id
创建然后空表将get_schema
附加到表格。
现在您已拥有模型,您可以使用DataFrame
显式命名和使用它们(例如User = Base.classes.user
),或使用以下内容创建所有类的dict:
session.query
查询:
alchemyClassDict = {}
for t in Base.classes.keys():
alchemyClassDict[t] = Base.classes[t]
答案 3 :(得分:0)
with engine.connect() as con:
con.execute('ALTER TABLE for_import_ml ADD PRIMARY KEY ("ID");')
for_import_ml
是数据库中的表名。
对 tomp 的回答稍作改动(我会发表评论,但没有足够的声望点)。
我正在使用 PGAdmin 和 Postgres(在 Heroku 上)来检查它是否有效。