使用df.to_sql将pandas数据帧写入sqlite数据库表时如何设置主键

yos*_*rry 11 python sqlite primary-key pandas

我使用pandas df.to_sql创建了一个sqlite数据库,但访问它似乎比只读取500mb csv文件慢得多.

我需要:

  1. 使用df.to_sql方法为每个表设置主键
  2. 告诉sqlite数据库3.dataframe中每个列的数据类型是什么? - 我可以传递像[整数,整数,文本,文本]这样的列表

代码....(格式代码按钮不起作用)

if ext == ".csv": 
df = pd.read_csv("/Users/data/" +filename) 
columns = df.columns columns = [i.replace(' ', '_') for i in columns]

df.columns = columns
df.to_sql(name,con,flavor='sqlite',schema=None,if_exists='replace',index=True,index_label=None, chunksize=None, dtype=None)
Run Code Online (Sandbox Code Playgroud)

Chr*_*ino 12

不幸的是,现在没有办法在pandas df.to_sql()方法中设置主键.另外,为了让事情变得更加困难,在创建表之后,无法在sqlite中的列上设置主键.

但是,目前的解决方法是使用pandas df.to_sql()方法在sqlite中创建表.然后,您可以创建一个重复的表并设置主键,然后复制数据.然后放下旧桌子进行清理.

这将是一个类似的事情.

import pandas as pd
import sqlite3

df = pd.read_csv("/Users/data/" +filename) 
columns = df.columns columns = [i.replace(' ', '_') for i in columns]

#write the pandas dataframe to a sqlite table
df.columns = columns
df.to_sql(name,con,flavor='sqlite',schema=None,if_exists='replace',index=True,index_label=None, chunksize=None, dtype=None)

#connect to the database
conn = sqlite3.connect('database')
c = conn.curser()

c.executescript('''
    PRAGMA foreign_keys=off;

    BEGIN TRANSACTION;
    ALTER TABLE table RENAME TO old_table;

    /*create a new table with the same column names and types while
    defining a primary key for the desired column*/
    CREATE TABLE new_table (col_1 TEXT PRIMARY KEY NOT NULL,
                            col_2 TEXT);

    INSERT INTO new_table SELECT * FROM old_table;

    DROP TABLE old_table;
    COMMIT TRANSACTION;

    PRAGMA foreign_keys=on;''')

#close out the connection
c.close()
conn.close()
Run Code Online (Sandbox Code Playgroud)

在过去,我已经完成了这个,因为我遇到了这个问题.把整个东西包装成一个功能,使它更方便......

在我对sqlite的有限经验中,我发现在创建表后无法添加主键,无法执行Update Inserts或UPSERTS,UPDATE JOIN引起了很多挫折和一些非传统的解决方法.

最后,在pandas df.to_sql()方法中,有一个dtype关键字参数,可以获取列名称的字典:types.IE:dtype = {col_1:TEXT}


yel*_*hin 7

在 pandas 0.15 版本中,to_sql()有一个 argument dtype,可用于设置所有列的 dtype 和主键属性:

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',
                                    'Data': 'FLOAT'})
Run Code Online (Sandbox Code Playgroud)


Rob*_*inL 5

基于Chris Guarino的回答,这里提供了一些更通用的解决方案.请参阅底部的示例以了解如何使用它们.

import re

def get_create_table_string(tablename, connection):
    sql = """
    select * from sqlite_master where name = "{}" and type = "table"
    """.format(tablename) 
    result = connection.execute(sql)

    create_table_string = result.fetchmany()[0][4]
    return create_table_string

def add_pk_to_create_table_string(create_table_string, colname):
    regex = "(\n.+{}[^,]+)(,)".format(colname)
    return re.sub(regex, "\\1 PRIMARY KEY,",  create_table_string, count=1)

def add_pk_to_sqlite_table(tablename, index_column, connection):
    cts = get_create_table_string(tablename, connection)
    cts = add_pk_to_create_table_string(cts, index_column)
    template = """
    BEGIN TRANSACTION;
        ALTER TABLE {tablename} RENAME TO {tablename}_old_;

        {cts};

        INSERT INTO {tablename} SELECT * FROM {tablename}_old_;

        DROP TABLE {tablename}_old_;

    COMMIT TRANSACTION;
    """

    create_and_drop_sql = template.format(tablename = tablename, cts = cts)
    connection.executescript(create_and_drop_sql)

# Example:

# import pandas as pd 
# import sqlite3

# df = pd.DataFrame({"a": [1,2,3], "b": [2,3,4]})
# con = sqlite3.connect("deleteme.db")
# df.to_sql("df", con, if_exists="replace")

# add_pk_to_sqlite_table("df", "index", con)
# r = con.execute("select sql from sqlite_master where name = 'df' and type = 'table'")
# print(r.fetchone()[0])
Run Code Online (Sandbox Code Playgroud)

有了这个代码的要点在这里