从Pandas Dataframe生成SQL语句

时间:2015-06-26 11:22:17

标签: python sql pandas

我正在将来自各种来源(csv,xls,json等...)的数据加载到Pandas数据帧中,我想生成使用此数据创建和填充SQL数据库的语句。有谁知道这样做的方法?

我知道pandas有to_sql函数,但只能在数据库连接上运行,它不能生成字符串。

实施例

我想要的是采用这样的数据框架:

import pandas as pd
import numpy as np

dates = pd.date_range('20130101',periods=6)
df = pd.DataFrame(np.random.randn(6,4),index=dates,columns=list('ABCD'))

一个会生成这个的函数(这个例子是PostgreSQL,但任何都可以):

CREATE TABLE data
(
  index timestamp with time zone,
  "A" double precision,
  "B" double precision,
  "C" double precision,
  "D" double precision
)

6 个答案:

答案 0 :(得分:15)

如果你只想要创建表' sql代码(而不是数据的插入),你可以使用pandas.io.sql模块的get_schema函数:

In [10]: print pd.io.sql.get_schema(df.reset_index(), 'data')
CREATE TABLE "data" (
  "index" TIMESTAMP,
  "A" REAL,
  "B" REAL,
  "C" REAL,
  "D" REAL
)

一些注意事项:

  • 我必须使用reset_index因为它不包含索引
  • 如果您提供某种数据库风格的sqlalchemy引擎,结果将调整为该风格(例如数据类型名称)。

答案 1 :(得分:2)

如果您想自己编写文件,您还可以检索列名和dtypes并构建字典以将pandas数据类型转换为sql数据类型。

举个例子:

import pandas as pd
import numpy as np

dates = pd.date_range('20130101',periods=6)
df = pd.DataFrame(np.random.randn(6,4),index=dates,columns=list('ABCD'))

tableName = 'table'
columnNames = df.columns.values.tolist()
columnTypes =  map(lambda x: x.name, df.dtypes.values)

# Storing column names and dtypes in a dataframe

tableDef = pd.DataFrame(index = range(len(df.columns) + 1), columns=['cols', 'dtypes'])

tableDef.iloc[0]           = ['index', df.index.dtype.name]
tableDef.loc[1:, 'cols']   = columnNames
tableDef.loc[1:, 'dtypes'] = columnTypes

# Defining a dictionnary to convert dtypes

conversion = {'datetime64[ns]':'timestamp with time zone', 'float64':'double precision'}

# Writing sql in a file

f = open('yourdir\%s.sql' % tableName, 'w')

f.write('CREATE TABLE %s\n' % tableName)
f.write('(\n')

for i, row in tableDef.iterrows():
    sep = ",\n" if i < tableDef.index[-1] else "\n"
    f.write('\t\"%s\" %s%s' % (row['cols'], conversion[row['dtypes']], sep))

f.write(')')

f.close()

您可以使用INSERT INTO以相同的方式填充表格。

答案 2 :(得分:1)

插入语句解决方案

不确定这是否是最好的方法,但这比使用 next(gen) 更有效,因为它非常慢。此外,这会在正则表达式的帮助下处理 df.iterrows() 值。

nan

答案 3 :(得分:0)

从DATAFRAME生成SQL创建声明

SOURCE = df
TARGET = data

从DATAFRAME生成SQL创建声明

def SQL_CREATE_STATEMENT_FROM_DATAFRAME(SOURCE, TARGET):

# SQL_CREATE_STATEMENT_FROM_DATAFRAME(SOURCE, TARGET)
# SOURCE: source dataframe
# TARGET: target table to be created in database

    import pandas as pd
    sql_text = pd.io.sql.get_schema(SOURCE.reset_index(), TARGET)   
    return sql_text

检查SQL CREATE TABLE语句字符串

print('\n\n'.join(sql_text))

从DATAFRAME生成SQL插入声明

def SQL_INSERT_STATEMENT_FROM_DATAFRAME(SOURCE, TARGET):
    sql_texts = []
    for index, row in SOURCE.iterrows():       
        sql_texts.append('INSERT INTO '+TARGET+' ('+ str(', '.join(SOURCE.columns))+ ') VALUES '+ str(tuple(row.values)))        
    return sql_texts

检查SQL INSERT INTO语句字符串

print('\n\n'.join(sql_texts))

答案 4 :(得分:0)

以用户@Jaris的帖子获取CREATE,我进一步扩展了它以适用于任何CSV

import sqlite3
import pandas as pd

db = './database.db'
csv = './data.csv'
table_name = 'data'

# create db and setup schema
df = pd.read_csv(csv)
create_table_sql = pd.io.sql.get_schema(df.reset_index(), table_name)
conn = sqlite3.connect(db)
c = conn.cursor()
c.execute(create_table_sql)
conn.commit()


# now we can insert data
def insert_data(row, c):
    values = str(row.name)+','+','.join([str('"'+str(v)+'"') for v in row])
    sql_insert=f"INSERT INTO {table_name} VALUES ({values})"

    try:
        c.execute(sql_insert)
    except Exception as e:
        print(f"SQL:{sql_insert} \n failed with Error:{e}")



# use apply to loop over dataframe and call insert_data on each row
df.apply(lambda row: insert_data(row, c), axis=1)

# finally commit all those inserts into the database
conn.commit()

希望这比替代答案更简单,而且更Python化!

答案 5 :(得分:0)

我没有找到满足我需求的上述答案。我想为每一行作为值的数据框创建一个插入语句。这可以通过以下方式实现:

import re 
import pandas as pd 

table = 'your_table_name_here'

# You can read from CSV file here... just using read_sql_query as an example

df = pd.read_sql_query(f'select * from {table}', con=db_connection)


cols = ', '.join(df.columns.to_list()) 
vals = []

for index, r in df.iterrows():
    row = []
    for x in r:
        row.append(f"'{str(x)}'")

    row_str = ', '.join(row)
    vals.append(row_str)

f_values = [] 
for v in vals:
    f_values.append(f'({v})')

# Handle inputting NULL values
f_values = ', '.join(f_values) 
f_values = re.sub(r"('None')", "NULL", f_values)

sql = f"insert into {table} ({cols}) values {f_values};" 

print(sql)

db.dispose()