pymssql 介紹

pymssql包是Python語言用於連接SQL Server資料庫的驅動程式(或者稱作DB API),它是最終和資料庫進行交互的工具。SQLAlchemy包就是利用pymssql包實現和SQL Server資料庫交互的功能的。

一,pymssql包的基本組成

pymssql包由兩個模組構成:pymssql 和 _mssql,pymssql 是建立在_mssql模組之上的模組,相對來說,_mssql性能更高。

pymssql模組由Connection和Cursor 兩個大類構成:

  • Connection類代表MS SQL Sever資料庫的一個連接,
  • Cursor類用於向資料庫發送查詢請求,並獲取查詢的的結果。

二,連接

連接對象用於連接SQL Server引擎,並設置連接的屬性,比如連接超時,字符集等。

1,創建連接對象

pymssql通過類函數來構建連接對,在創建連接對象的同時,打開連接:

class pymssql.Connection(user, password, host, database, timeout, login_timeout, charset, as_dict)

2,構建Cursor對象

在創建連接對象之後,創建Cursor對象,使用Cursor對象向資料庫引擎發送查詢請求,並獲取查詢的結果:

Connection.cursor(as_dict=False)

as_dict是布爾類型,默認值是False,表示返回的數據是元組(tuple)類型;如果設置為True,返回的數據集是字典(dict)類型。

3,提交查詢和自動提交模式

在執行查詢之後,必須提交當前的事務,以真正執行Cursor對象的查詢請求:

Connection.commit()

默認情況下,自動提交模式是關閉的,用戶可以設置自動提交,pymssql自動執行Cursor發送的查詢請求:

Connection.autocommit(status)

status是bool值,True表示打開自動提交模式,False表示關閉自動提交模式,默認值是False。

4,關閉連接

在執行完查詢之後,關閉連接:

Connection.close()

三,Cursor

通過打開的連接對象來創建Cursor對象,通過Cursor對象向資料庫引擎發送查詢請求,並獲取查詢的結果。

1,執行查詢

Cursor對象調用execute**()函數來執行查詢請求,

Cursor.execute(operation)
Cursor.execute(operation, params)
Cursor.executemany(operation, params_seq)

參數注釋:

  • operation:表示執行的sql語句,
  • params :表示sql語句的參數,
  • params_seq:參數序列,用於sql語句包含多個參數的情況。

注意,除設置自動提交模式之外,必須在執行查詢之後,通過連接對象來提交查詢。

Connection.commit()

如果sql語句只包含一個參數,那麼必須在sql語句中顯式使用%s或%d作為佔位符,分別用於引用字元型的參數和數值型的參數。

cursor.execute('SELECT * FROM persons WHERE salesrep=%s', 'John Doe')

如果sql語句包含多個參數,那麼使用list來傳遞參數:

cursor.executemany(
    "INSERT INTO persons VALUES (%d, %s, %s)",
    [(1, 'John Smith', 'John Doe'),
     (2, 'Jane Doe', 'Joe Dog'),
     (3, 'Mike T.', 'Sarah H.')])

2,獲取查詢結果

Cursor對象調用fetch**()函數來獲取查詢的結果:

Cursor.fetchone()
Cursor.fetchmany(size=None)
Cursor.fetchall()

fetch**()函數是迭代的:

  • fetchone():表示從查詢結果中獲取下一行(next row)
  • fetchmany():表示從查詢結果中獲取下面的多行(next batch)
  • fetchall():表示從查詢結果中獲取剩餘的所有數據行(all remaining)

3,跳過結果集

當查詢的結果包含多個結果集時,可以跳過當前的結果集,跳到下一個結果集:

Cursor.nextset()

如果當前結果集還有數據行未被讀取,那麼這些剩餘的數據行會被丟棄。

四,執行存儲過程

Cursor對象有函數callproc(),用於執行存儲過程:

Cursor.callproc(sp_name, paras)

第一個參數是存儲過程的名稱,第二個參數是一個元組類型,

五,pymssql模組的基本操作

 1,pymssql的基本操作

from os import getenv
import pymssql

server = getenv("PYMSSQL_TEST_SERVER")
user = getenv("PYMSSQL_TEST_USERNAME")
password = getenv("PYMSSQL_TEST_PASSWORD")

conn = pymssql.connect(server, user, password, "tempdb")
cursor = conn.cursor(as_dict=False)
cursor.execute("TSQL query")
cursor.executemany("INSERT INTO persons VALUES (%d, %s, %s)",
    [(1, 'John Smith', 'John Doe'),
     (2, 'Jane Doe', 'Joe Dog'),
     (3, 'Mike T.', 'Sarah H.')])
# you must call commit() to persist your data if you don't set autocommit to True
conn.commit()

cursor.execute('SELECT * FROM persons WHERE salesrep=%s', 'John Doe')
row = cursor.fetchone()
while row:
    print("ID=%d, Name=%s" % (row[0], row[1]))
    row = cursor.fetchone()

conn.close()

2,以字典集返回數據行

conn = pymssql.connect(server, user, password, "tempdb")
cursor = conn.cursor(as_dict=True)

cursor.execute('SELECT * FROM persons WHERE salesrep=%s', 'John Doe')
for row in cursor:
    print("ID=%d, Name=%s" % (row['id'], row['name']))

conn.close()

3,使用with語句

with是上下文管理器,可以自動關閉上下文。

如果使用with語句來創建連接對象和Cursor對象,那麼就不需要顯式的關閉連接和Cursor對象,在語句執行完成之後,Python會自動檢測連接對象和Cursor對象的作用域,一旦連接對象或Cursor對象不再有效,Python就會關閉連接或Cursor對象。

with pymssql.connect(server, user, password, "tempdb") as conn:
    with conn.cursor(as_dict=True) as cursor:
        cursor.execute('SELECT * FROM persons WHERE salesrep=%s', 'John Doe')
        for row in cursor:
            print("ID=%d, Name=%s" % (row['id'], row['name']))

六,附上程式碼庫

 附上程式碼,以饗讀者。

import pymssql
from sqlalchemy import create_engine
import pandas as pd
from sqlalchemy.sql import text as sql_text

class DBHelper:
    def __init__(self):
        self.name='DB Helper'
        self.db_host = r'sql server'
        self.db_name = 'db name'
        self.db_user = r'sa' 
        self.db_password = r'pwd'

######################################################
##                   data connection                ##
######################################################

    def get_engine(self):
        str_format = 'mssql+pymssql://{0}:{1}@{2}/{3}?charset=utf8'
        connection_str = str_format.format(self.db_user,self.db_password,self.db_host,self.db_name)
        engine = create_engine(connection_str,echo=False)
        return engine

    def get_pymssql_conn(self):
        conn = pymssql.connect(self.db_host, self.db_user, self.db_password, self.db_name)
        return conn


######################################################
##                common SQL APIs                   ##
######################################################

    def write_data(self,df,destination,if_exists='append',schema='dbo'):
        engine = self.get_engine()
        df.to_sql(destination, con=engine, if_exists=if_exists,index = False, schema=schema
, method='multi', chunksize=1000) def read_data(self,sql): engine = self.get_engine() df = pd.read_sql(sql, con=engine) return df def exec_sql(self,sql): engine = self.get_engine() con = engine.connect() with con.begin() as tran: con.execute(sql_text(sql).execution_options(autocommit=True)) def exec_sp(self,sp_name,*paras): with pymssql.connect(self.db_host, self.db_user, self.db_password, database=self.db_name) as conn: with conn.cursor(as_dict=False) as cursor: try: cursor.callproc(sp_name, paras) conn.commit() except Exception as e: print(e) def exec_sp_result(self,sp_name,*paras): with pymssql.connect(self.db_host, self.db_user, self.db_password, database=self.db_name) as conn: with conn.cursor(as_dict=True) as cursor: try: cursor.callproc(sp_name, paras) cursor.nextset() result=cursor.fetchall() conn.commit() df=pd.DataFrame.from_records(result) return df except Exception as e: print(e)

 

參考文檔:

pymssql introduction