pandas DataFrame.to_sql()用法小結(jié)
to_sql()
的語法如下:
# https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_sql.html DataFrame.to_sql(name, con, schema=None, if_exists='fail', index=True, index_label=None, chunksize=None, dtype=None, method=None)
我們從一個(gè)簡(jiǎn)單的例子開始。在 mysql 數(shù)據(jù)庫(kù)中有一個(gè) emp_data
表,假設(shè)我們使用 pandas DataFrame ,將數(shù)據(jù)拷貝到另外一個(gè)新表 emp_backup
。
import pandas as pd from sqlalchemy import create_engine import sqlalchemy engine = create_engine('mysql+pymysql://user:password@localhost/stonetest?charset=utf8') df = pd.read_sql('emp_master', engine) df.to_sql('emp_backup', engine)
使用 mysql 的 describe
命令比較 emp_master
表和 emp_backup
表結(jié)構(gòu):
mysql> describe emp_master; +----------------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------------+-------------+------+-----+---------+-------+ | EMP_ID | int(11) | NO | PRI | NULL | | | GENDER | varchar(10) | YES | | NULL | | | AGE | int(11) | YES | | NULL | | | EMAIL | varchar(50) | YES | | NULL | | | PHONE_NR | varchar(20) | YES | | NULL | | | EDUCATION | varchar(20) | YES | | NULL | | | MARITAL_STAT | varchar(20) | YES | | NULL | | | NR_OF_CHILDREN | int(11) | YES | | NULL | | +----------------+-------------+------+-----+---------+-------+ 8 rows in set (0.00 sec)
emp_backup 表結(jié)構(gòu):
mysql> describe emp_backup; +----------------+------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------------+------------+------+-----+---------+-------+ | index | bigint(20) | YES | MUL | NULL | | | EMP_ID | bigint(20) | YES | | NULL | | | GENDER | text | YES | | NULL | | | AGE | bigint(20) | YES | | NULL | | | EMAIL | text | YES | | NULL | | | PHONE_NR | text | YES | | NULL | | | EDUCATION | text | YES | | NULL | | | MARITAL_STAT | text | YES | | NULL | | | NR_OF_CHILDREN | bigint(20) | YES | | NULL | | +----------------+------------+------+-----+---------+-------+ 9 rows in set (0.00 sec)
我們發(fā)現(xiàn),to_sql()
并沒有考慮將 emp_master
表字段的數(shù)據(jù)類型同步到目標(biāo)表,而是簡(jiǎn)單的區(qū)分?jǐn)?shù)字型和字符型,這是第一個(gè)問題,第二個(gè)問題呢,目標(biāo)表沒有 primary key。因?yàn)?pandas 定位是數(shù)據(jù)分析工具,數(shù)據(jù)源可以來自 CSV 這種文本型文件,本身是沒有嚴(yán)格數(shù)據(jù)類型的。而且,pandas 數(shù)據(jù) to_excel()
或者to_sql()
只是方便數(shù)據(jù)存放到不同的目的地,本身也不是一個(gè)數(shù)據(jù)庫(kù)升遷工具。
但如果我們需要嚴(yán)格保留原表字段的數(shù)據(jù)類型,以及同步 primary key,該怎么做呢?
使用 SQL 語句來創(chuàng)建表結(jié)構(gòu)
如果數(shù)據(jù)源本身是來自數(shù)據(jù)庫(kù),通過腳本操作是比較方便的。如果數(shù)據(jù)源是來自 CSV 之類的文本文件,可以手寫 SQL 語句或者利用 pandas get_schema()
方法,如下例:
import sqlalchemy print(pd.io.sql.get_schema(df, 'emp_backup', keys='EMP_ID', dtype={'EMP_ID': sqlalchemy.types.BigInteger(), 'GENDER': sqlalchemy.types.String(length=20), 'AGE': sqlalchemy.types.BigInteger(), 'EMAIL': sqlalchemy.types.String(length=50), 'PHONE_NR': sqlalchemy.types.String(length=50), 'EDUCATION': sqlalchemy.types.String(length=50), 'MARITAL_STAT': sqlalchemy.types.String(length=50), 'NR_OF_CHILDREN': sqlalchemy.types.BigInteger() }, con=engine))
get_schema()
并不是一個(gè)公開的方法,沒有文檔可以查看。生成的 SQL 語句如下:
CREATE TABLE emp_backup ( `EMP_ID` BIGINT NOT NULL AUTO_INCREMENT, `GENDER` VARCHAR(20), `AGE` BIGINT, `EMAIL` VARCHAR(50), `PHONE_NR` VARCHAR(50), `EDUCATION` VARCHAR(50), `MARITAL_STAT` VARCHAR(50), `NR_OF_CHILDREN` BIGINT, CONSTRAINT emp_pk PRIMARY KEY (`EMP_ID`) )
to_sql() 方法使用 append 方式插入數(shù)據(jù)
to_sql()
方法的 if_exists
參數(shù)用于當(dāng)目標(biāo)表已經(jīng)存在時(shí)的處理方式,默認(rèn)是 fail
,即目標(biāo)表存在就失敗,另外兩個(gè)選項(xiàng)是 replace
表示替代原表,即刪除再創(chuàng)建,append
選項(xiàng)僅添加數(shù)據(jù)。使用 append
可以達(dá)到目的。
import pandas as pd from sqlalchemy import create_engine import sqlalchemy engine = create_engine('mysql+pymysql://user:password@localhost/stonetest?charset=utf8') df = pd.read_sql('emp_master', engine) # make sure emp_master_backup table has been created # so the table schema is what we want df.to_sql('emp_backup', engine, index=False, if_exists='append')
也可以在 to_sql()
方法中,通過 dtype
參數(shù)指定字段的類型,然后在 mysql 中 通過 alter table
命令將字段 EMP_ID
變成 primary key。
df.to_sql('emp_backup', engine, if_exists='replace', index=False, dtype={'EMP_ID': sqlalchemy.types.BigInteger(), 'GENDER': sqlalchemy.types.String(length=20), 'AGE': sqlalchemy.types.BigInteger(), 'EMAIL': sqlalchemy.types.String(length=50), 'PHONE_NR': sqlalchemy.types.String(length=50), 'EDUCATION': sqlalchemy.types.String(length=50), 'MARITAL_STAT': sqlalchemy.types.String(length=50), 'NR_OF_CHILDREN': sqlalchemy.types.BigInteger() }) with engine.connect() as con: con.execute('ALTER TABLE emp_backup ADD PRIMARY KEY (`EMP_ID`);')
當(dāng)然,如果數(shù)據(jù)源本身就是 mysql,當(dāng)然不用大費(fèi)周章來創(chuàng)建數(shù)據(jù)表的結(jié)構(gòu),直接使用 create table like xxx
就行。以下代碼展示了這種用法:
import pandas as pd from sqlalchemy import create_engine engine = create_engine('mysql+pymysql://user:password@localhost/stonetest?charset=utf8') df = pd.read_sql('emp_master', engine) # Copy table structure with engine.connect() as con: con.execute('DROP TABLE if exists emp_backup') con.execute('CREATE TABLE emp_backup LIKE emp_master;') df.to_sql('emp_backup', engine, index=False, if_exists='append')
到此這篇關(guān)于pandas DataFrame.to_sql()用法小結(jié)的文章就介紹到這了,更多相關(guān)pandas DataFrame.to_sql() 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
UI自動(dòng)化定位常用實(shí)現(xiàn)方法代碼示例
這篇文章主要介紹了UI自動(dòng)化定位常用實(shí)現(xiàn)方法代碼示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10Python中使用第三方庫(kù)xlutils來追加寫入Excel文件示例
這篇文章主要介紹了Python中使用第三方庫(kù)xlutils來追加寫入Excel文件示例,本文直接給出追加寫入示例和追加效果,需要的朋友可以參考下2015-04-04Python判斷對(duì)象是否相等及eq函數(shù)的講解
今天小編就為大家分享一篇關(guān)于Python判斷對(duì)象是否相等及eq函數(shù)的講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-02-02JupyterNotebook 如何調(diào)整輸出窗口的顯示效果
這篇文章主要介紹了JupyterNotebook 輸出窗口的顯示效果調(diào)整實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09