Create a temporary table in MySQL using Pandas

时间:2015-12-10 02:01:41

标签: python mysql pandas temp-tables

Pandas has a great feature, where you can write your dataframe to a table in SQL.

df.to_sql(con=cnx, name='some_table_name', if_exists='replace', flavor='mysql', index=False)

Is there a way to make a temporary table this way?

There is nothing in the documentation as far as I can tell.

3 个答案:

答案 0 :(得分:10)

DataFrame.to_sql()使用内置的pandas pandas.io.sql package,它本身依赖于SQLAlchemy作为数据库抽象层。为了创造一个临时的" SQLAlchemy ORM中的表,you need to supply a prefix

t = Table(
    't', metadata,
    Column('id', Integer, primary_key=True),
    # ...
    prefixes=['TEMPORARY'],
)

从我看到的内容,pandas.io.sql does not allow you to specify the prefixes或轻松更改表格的创建方式。

解决此问题的一种方法是事先创建临时表并使用to_sql() if_exists="append"(所有使用相同的数据库连接)。

以下是我尝试过的操作:覆盖pandas.io.sql.SQLTable的{​​{1}}方法并将_create_table_setup()传递给prefixes构造函数。出于某种原因,该表仍然是非临时的。不确定它是否会有所帮助,但这里是我使用的代码:gist。这有点像hacky,但我希望它至少可以作为一个示例代码来帮助您开始这种方法。

答案 1 :(得分:1)

简单的解决方法,无需花哨的魔法

这对我来说是一种快速简便的解决方法。

只需将 RegEx 应用到生成的 SQL 中即可添加您想要的任何语句。

import io
import pandas as pd

# Get the SQL that would be generated by the create table statement
create_table_sql = pd.io.sql.get_schema(df, tmp_table_name)

# Replace the `CREATE TABLE` part of the generated statement with 
# whatever you need.
create_tmp_table_sql = re.sub(
    "^(CREATE TABLE)?",
    "CREATE TEMP TABLE",
    create_table_sql
)

# Write to the database in a transaction (psychopg2)
with conn.cursor() as cur:
    cur.execute(create_tmp_table_sql)
    output = io.StringIO()
    df.to_csv(output, sep="\t", header=False, index=False, na_rep="NULL")
    output.seek(0)
    cur.copy_from(output, tmp_table_name, null="NULL")

感谢 Aseem 写入 Postgres 的方式。

答案 2 :(得分:0)

这可能有点hacky并且它在技术上没有创建一个临时表,它就像一个,但你可以创建使用@contextmanager decorator from contextlib来打开上下文创建表并删除它在收盘时可能看起来像:

from contextlib import contextmanager

import numpy as np
import sqlalchemy as sqla
import pandas as pd


@contextmanager
def temp_table(frame, tbl, eng, *args, **kwargs):
    frame.to_sql(tbl, eng, *args, **kwargs)
    yield
    eng.execute('DROP TABLE {}'.format(tbl))

df = pd.DataFrame(np.random.randint(21, size=(10, 10)))
cnx = sqla.create_engine(conn_string)

with temp_table(df, 'some_table_name', cnx, if_exists='replace', flavor='mysql', index=False):
    # do stuff with "some_table_name"

我使用Teradata进行测试,效果很好。我没有安装MySQL,我可以对其进行测试,但只要DROP语句在MySQL中有效,它就应该按预期工作。