yos*_*rry 11 python sqlite primary-key pandas
我使用pandas df.to_sql创建了一个sqlite数据库,但访问它似乎比只读取500mb csv文件慢得多.
我需要:
代码....(格式代码按钮不起作用)
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}
在 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)
基于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)
有了这个代码的要点在这里