pandas.read_sql 使用參數進行數據查詢

pandas.read_sql 可以在數據庫中執行指定的SQL語句查詢或對指定的整張表進行查詢,以DataFrame 的類型返回查詢結果,這是在跟數據庫進行交互操作時很重要的一步——既讀取數據,還返回DataFrame方便處理。

要解決的問題: 編寫過的SQL語句需要重複使用,這就涉及到參數,使用參數來替換條件,然後根據需要替換參數。

一、之前的處理方法

在沒有使用參數之前,我一直使用的是正則法,也就是利用 re.sub 這個方法將需要的SQL內容替換掉,這樣的好處就是可以替換任意內容,缺點就是必須每次使用的時候 import re.sub

    from re import sub
    import sqlalchemy
    import pandas as pd
    # 創建數據庫連接,這裏使用的是pymysql
    engine = sqlalchemy.create_engine("mysql+pymysql://username:password@ip:port/store_name")
    sql = "select * from test where id = 'pid'"
    # 使用 sub 進行數據替換
    data = pd.read_sql(sub("pid", '1', sql), engine)

在這裏使用的時候 pid 是爲了統一處理才用的標識名,這樣在以後不管什麼時候都只需要對 pid 進行替換即可。

有一點需要注意的是 sub 替換後的傳入是字符串,但是傳入到 替換到SQL中是不會變的。比如

sql = "select * from test where id = pid" data =
pd.read_sql(sub("pid", '1', sql), engine) 

進行 sub("pid", '1',> sql) 操作後 SQL 變成了
sql select * from test where id = 1
如果 id 字段是 int 類型那就沒問題,但是如果 id 字段是 char 或 varchar 等其他類型就會出現字段類型是字符串但給的是數字(mysql 很寬容,不一定會報錯,但是從數據類型上來說肯定是錯了)

二、使用 read_sql 中的 params 傳入參數

1.文檔說明

 pandas.read_sql(sql, con, index_col=None, coerce_float=True, params=None, parse_dates=None, columns=None, chunksize=None)[source]

read_sql 方法中已經有了 params 這個參數,這個就是可以進行參數的傳遞,具體的描述如下

params : list, tuple or dict, optional, default: None
List of parameters to pass to execute method. The syntax used to pass parameters is database driver dependent. Check your database driver documentation for which of the five syntax styles, described in PEP 249’s paramstyle, is supported. Eg. for psycopg2, uses %(name)s so use params={‘name’ : ‘value’}

意思就是可以使用功能 list, tuple or dict 傳遞參數,但是如何怎麼設置參數和傳遞參數需要依據使用的數據庫引擎。PEP 249’s paramstyle 如下表

paramstyle Meaning
qmark Question mark style, e.g. …WHERE name=?
numeric Numeric, positional style, e.g. …WHERE name=:1
named Named style, e.g. …WHERE name=:name
format ANSI C printf format codes, e.g. …WHERE name=%s
pyformat Python extended format codes, e.g. …WHERE name=%(name)s

總結下就是在SQL語句中使用?, :1, :name, %s, %設置參數,然後在params 使用 list, tuple or dict 進行參數的傳遞

2.具體的使用

    from re import sub
    import sqlalchemy
    import pandas as pd
    # 創建數據庫連接
    engine = sqlalchemy.create_engine("mysql+pymysql://username:password@ip:port/store_name")
    sql = "select * from test where id = %(pid)s"
    # 使用 params 進行參數傳遞
    data = pd.read_sql(sql, engine, params={'pid': '1'})

具體的參數就如上面代碼所示,使用了 %(pid)s 設置參數,再用params={‘pid’: ‘1’}傳遞參數,在Stack Overflow上有個提問也是關於這個的,裏面還有關於psycopg2 和SQLite 的參數傳遞。

三、總結對比

之前沒有想過使用參數,是因爲在SQL中我不僅要替換固定條件,而且有時候需要替換大段的SQL,所以使用 sub 會更靈活更模糊(傳入的是字符串,到了SQL裏面數字還是字符串得再處理一遍),但是使用方法自帶的參數傳遞可以很明確的傳遞正確的數據和數據類型,而且不覺得使用方法自帶的參數傳遞很優雅?


2019-10-10 添加

四、字符串的格式化

對於參數的傳遞還有另外一種就是python中的字符串格式化,format函數可以實現不帶參數、帶索引參數、帶關鍵字參數,python的字符串格式化可以參考python格式化輸出
下面是format的使用示例

in : print("{one} are {two} {three}".format(one='you', two=1, three='pig'))
out: you are 1 pig

這裏的1應該爲a,但是爲了演示傳遞整數參數

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章