天天看點

pyodbc 操作SQL Server資料庫

pyodbc是Python包,使用ODBC驅動器來連接配接SQL Server資料庫,pyodbc的基本類型是Connection,Cursor和Row,其中,Connection表示用戶端和資料庫的連接配接,并用于送出事務;Cursor表示向資料庫發送的查詢請求,Row表示擷取的結果集。

從微軟官方文檔來看,更推薦使用pyodbc來操作SQL Server資料庫。

一,ODBC驅動程式

要使用pyodbc連接配接SQL Server資料庫,必須安裝SQL Server資料庫的ODBC 驅動程式:

Install the Microsoft ODBC Driver for SQL Server on Windows,

目前的版本是Microsoft ODBC Driver 17,支援從SQL Server 2008到目前最新的SQL Server 2019版本。

{ODBC Driver 17 for SQL Server} 
      

Microsoft ODBC Driver for SQL Server 是一個動态連結庫(DLL),包含run-time支援庫,使得程式可以使用native-code API連接配接到SQL Server資料庫。

使用pyodbc連接配接資料庫的基本操作,連接配接資料庫,執行查詢,并周遊查詢結果:

import pyodbc

# Specifying the ODBC driver, server name, database, etc. directly
cn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};SERVER=localhost;DATABASE=testdb;UID=me;PWD=pass')

# Create a cursor from the connection
cursor = cn.cursor()

#Selecting Some Data
cursor.execute("select user_id, user_name from users")
rows = cursor.fetchall()
for row in rows:
    print(row.user_id, row.user_name)

cn.close()      

二,連接配接對象

連接配接對象代表Python和資料庫的連接配接,通過connect()函數來建立連接配接對象,連接配接對象通過ODBC驅動程式來通路SQL Server資料庫:

cn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};SERVER=localhost;DATABASE=mine;UID=user;PWD=pwd')      

1,連接配接對象的屬性

cn.autocommit 是連接配接對象的一個屬性,預設情況下,連接配接對象是不會自動送出的,該屬性的值是False。在執行完成查詢請求之後,需要顯示送出。

如果設定autocommit為True,那麼設定連接配接為自動送出模式:

cn.autocommit = True      

cn.timeout, 用于設定逾時時間,機關是秒,預設值是0,表示不限制時間。

2,連接配接對象可以建立Cursor對象

mycursor = cn.cursor()      

3,連接配接對象送出或復原事務

如果Cursor對象執行的是更新操作,比如執行UPDATE、DELETE或INSERT等更新操作,那麼必須通過連接配接對象來顯式送出事務;如果執行的更新操作失敗,連接配接對象必須顯式復原事務。如果Cursor對象執行的SELECT操作,不需要送出事務或者復原事務。

cn.commit()
cn.rollback()      

4,關閉連接配接對象

當關閉連接配接時,任何未送出的查詢語句都會復原,更新操作的結果将會丢失。當連接配接對象被删除,特别是超出作用域時,連接配接會自動關閉,但是,推薦顯式關閉連接配接。

cn.close()      

三,Cursor對象

Cursor對象用于管理每個fetch操作的上下文,Cursor對象通過Connection對象來建立。

1,執行SQL語句

Cursor調用execute()函數來執行SQL語句:

execute(sql, *parameters)
executemany(sql, *params)      

execute()函數隻執行一次SQL語句,可以向SQL語句傳遞參數,傳參的格式有以下兩種:

# standard
cursor.execute("select a from tbl where b=? and c=?", (x, y))
# pyodbc extension
cursor.execute("select a from tbl where b=? and c=?", x, y)      

executemany()可以對每組參數執行相同的SQL語句,

params = [ ('A', 1), ('B', 2) ]
cursor.executemany("insert into t(name, id) values (?, ?)", params)      

該語句等價于執行execute()函數兩次:

params = [ ('A', 1), ('B', 2) ]
for p in params:
    cursor.execute("insert into t(name, id) values (?, ?)", p)      

如果設定cursor.fast_executemany = True,可以提高executemany()函數的性能,該屬性預設是False。

2,fetch結果

從cursor對象中擷取單行:

cursor.fetchone()      

從cursor對象中擷取多行:

cursor.fetchone(size=1)      

從cursor對象中擷取所有行:

cursor.fetchall()      

3,跳到下一個結果集

此方法将使Cursor對象跳至下一個可用結果集,并丢棄目前結果集中的所有剩餘行。 如果沒有更多結果集,則該方法傳回False。 否則,它将傳回True,随後對fetch方法的調用将傳回下一個結果集中的行。

如果執行傳回多個結果的存儲過程,那麼主要使用此方法。

cursor.nextset()      

4,關閉連接配接

在不再需要cursor時,請使用關閉Cursor對象。

cursor.close()      

如果試圖通路已經被關閉的cursor,程式将會出錯。Cursor對象會在被删除或者超出作用域時自動關閉。

四,Row對象

Row對象調用fetch函數傳回的一行資料,row對象的值可以被替換,從同一個select語句中傳回的row對象共享記憶體。

row對象可以通過索引來通路資料,也可以通過列名來通路資料:

cursor.execute("select album_id, photo_id from photos where user_id=1")
row = cursor.fetchone()
print(row.album_id, row.photo_id)
print(row[0], row[1])  # same as above, but less readable      

fetchone()函數傳回的是單行Row對象,fetchmany()函數 或這fetchall()函數傳回的rows對象的清單:

cursor.execute("select album_id, photo_id from photos where user_id=1")
rows = cursor.fetchall()
for row in rows:
    row.album_id=1
    row.photo_id=1001
      

五,上下文管理器

Connection對象和Cursor對象都支援Python的上下文管理(Context manager),使用with語句來自動關閉Connection對象和Cursor對象,并調用Connection對象的commit()函數來送出查詢。

1,Connection對象的上下文管理器

Connection對象的上下文管理器,不僅自動關閉連接配接,還會送出查詢:

with pyodbc.connect('mydsn') as cnxn:
    do_stuff

#等價于
cnxn = pyodbc.connect('mydsn')
do_stuff
if not cnxn.autocommit:
    cnxn.commit()        

2,Cursor對象的上下文管理器

Cursor對象的上下文管理器,會自動關閉Cursor,還會送出查詢:

with cnxn.cursor() as crsr:
    do_stuff

#等價于
crsr = cnxn.cursor()
do_stuff
if not cnxn.autocommit:
    cnxn.commit()        

3,使用上下文管理器來查詢結果

import pyodbc

# Specifying the ODBC driver, server name, database, etc. directly
with pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};SERVER=localhost;DATABASE=testdb;UID=me;PWD=pass') as cn:

    # Create a cursor from the connection
    with cn.cursor() as cursor:
        
        #Selecting Some Data
        cursor.execute("select user_id, user_name from users")
        rows = cursor.fetchall()
        for row in rows:
            print(row.user_id, row.user_name)      

4,使用上下文管理器來執行更新操作

在執行更新操作,需要顯式送出事務

import pyodbc

with pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};SERVER=localhost;DATABASE=testdb;UID=me;PWD=pass') as cn:
    try:
        cn.autocommit = False
        with cn.cursor() as cursor:
            params = [ ('A', 1), ('B', 2) ]
            cursor.executemany("insert into t(name, id) values (?, ?)", params)
    except pyodbc.DatabaseError as err:
        cn.rollback()
    else:
        cn.commit()
    finally:
        cn.autocommit = True      

六,調用存儲過程

pyodbc 使用{call ...}來調用存儲過程,調用存儲過程的格式如下:

cursor.execute("{CALL usp_NoParameters}")

params = (14, "Dinsdale")
cursor.execute("{CALL usp_HaveParammeters (?,?)}", params)      

參考文檔:

pyodbc wiki

作者

:悅光陰

出處

:http://www.cnblogs.com/ljhdo/

本文版權歸作者和部落格園所有,歡迎轉載,但未經作者同意,必須保留此段聲明,且在文章頁面醒目位置顯示原文連接配接,否則保留追究法律責任的權利。