用 mssql-python 管理連線

大多數應用程式遵循簡單的模式:開啟連線、執行查詢、關閉連線。 以下章節將涵蓋開啟與關閉連線、使用上下文管理器、設定自動提交,以及連線屬性的操作。

開啟連線

利用這個 connect() 函式建立連結。 提供包含伺服器、資料庫和驗證資訊的連線字串:

import mssql_python

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;Database=<database>;"
    "Authentication=ActiveDirectoryDefault;Encrypt=yes"
)

connect() 函式接受:

  • 將連線字串作為第一個位置引數,或使用 connection_str 關鍵字。
  • 驅動程式將其合併成連線字串的個別關鍵字。
  • 其他選項如 autocommittimeoutattrs_before和 。

你可以兩種方法混合使用。 關鍵字會覆寫連接字串中的值;當您在組態中儲存基礎連接字串,並在每次呼叫時覆寫像是 timeout 這類設定時,這會非常有用:

# Base connection string from config, with per-call overrides
conn = mssql_python.connect(
    "Server=<server>.database.windows.net;Database=<database>;"
    "Authentication=ActiveDirectoryDefault;Encrypt=yes",
    timeout=30,
    autocommit=True
)

關閉連線

完成後務必關閉連線,讓連線回到連線池並釋放伺服器資源。 未封閉的連線會佔據伺服器端記憶體,最終可能導致連線池耗盡,導致新的連線嘗試被阻塞或失敗。

conn = mssql_python.connect(connection_string)
try:
    # Use the connection
    cursor = conn.cursor()
    cursor.execute("SELECT 1")
finally:
    conn.close()

一旦關閉,該連線將無法使用:

conn.close()
print(conn.closed)  # True

# This raises an error
cursor = conn.cursor()  # InterfaceError: Cannot create cursor on closed connection

多次呼叫 close() 是安全的(冪등性):

conn.close()
conn.close()  # No error

情境管理器

在大多數應用程式中使用該 with 語句來管理連線。 它保證在區塊結束時,即使發生例外,驅動程式也會關閉連線。 此方法消除了因通話遺漏 close() 而洩漏連線的風險:

with mssql_python.connect(connection_string) as conn:
    cursor = conn.cursor()
    cursor.execute("CREATE TABLE #Demo (Name NVARCHAR(50))")
    cursor.execute("INSERT INTO #Demo (Name) VALUES ('Widget')")
    conn.commit()  # Must commit explicitly when autocommit=False
# Connection automatically closed

上下文管理器會在退出時關閉連線。 它 不會 自動提交或回滾交易:

  • 一律:在結束時呼叫 close(),無論是否發生例外。
  • close() 行為:若 autocommit=False,則在連線關閉時,任何未提交的變更都會被回滾。
  • 你必須明確呼叫conn.commit()才能持續執行變更。

此設計遵循 PEP 249 的行為模式,並防止意外發生部分提交。 如果您的程式碼在執行到 commit() 之前引發例外,進行中的交易會安全地回滾:

# Equivalent manual code:
conn = mssql_python.connect(connection_string)
try:
    cursor = conn.cursor()
    cursor.execute("CREATE TABLE #Demo (Name NVARCHAR(50))")
    cursor.execute("INSERT INTO #Demo (Name) VALUES ('Widget')")
    conn.commit()  # Must commit explicitly
finally:
    conn.close()  # Rolls back uncommitted changes if autocommit=False

自動提交模式

預設情況下, autocommit=False這表示每個語句都執行於隱含交易中。 你必須呼叫 conn.commit() 以持續執行變更或 conn.rollback() 丟棄它們。 隱式交易是資料修改最安全的選擇,因為它允許將多個語句合併成單一原子操作。

當你希望每個語句立即提交時,請啟用自動提交。 自動提交對於 DDL 操作(CREATE TABLEALTER INDEX)、唯讀工作負載或不需要交易群組的管理腳本非常有用:

conn = mssql_python.connect(connection_string)
print(conn.autocommit)  # False

cursor = conn.cursor()
cursor.execute("CREATE TABLE #Demo (Name NVARCHAR(50))")
cursor.execute("INSERT INTO #Demo (Name) VALUES ('Widget')")
conn.commit()  # Required to persist changes

啟用自動提交,讓每個語句立即提交。 在建立連線時使用 autocommit=True,或在連線後使用 setautocommit() 或直接指派屬性來切換:

# At connection time
conn = mssql_python.connect(connection_string, autocommit=True)

# Or after connection (both forms work)
conn.setautocommit(True)
conn.autocommit = True
print(conn.autocommit)  # True

# Now changes are committed automatically
cursor = conn.cursor()
cursor.execute("SELECT TOP 1 Name FROM Production.Product")
print(cursor.fetchone().Name)
# No commit() needed

連線超時

設定連線逾時,以控制驅動程式在引發錯誤前會等待多久來建立連線。 對於部署在網路不穩定環境或伺服器無法連線時快速故障的應用程式來說,合理的連線逾時非常重要:

# At connection time (in seconds)
conn = mssql_python.connect(connection_string, timeout=30)

# Or after connection
conn.timeout = 60
print(conn.timeout)  # 60

逾時時間為 0 表示沒有逾時限制(會無限期等待)。 在生產環境中設定合理的逾時時間;沒有設定逾時的連線嘗試一旦卡住,就會永久阻塞呼叫執行緒。

連線屬性

用於 set_attr() 在執行時修改連線行為。 連線屬性控制低階驅動程式設定,如存取模式、交易隔離及封包大小。 大多數應用程式不需要更改這些屬性,但它們在特定情境下很有用:

  • 唯讀模式:防止在報告查詢中誤寫。
  • 交易隔離:控制並行交易的互動方式( SERIALIZABLE 用於嚴格一致性,用於 READ_COMMITTED 一般用途)。
  • 封包大小:針對高延遲或高吞吐量網路進行調整。
import mssql_python

conn = mssql_python.connect(connection_string)

# Set read-only mode
conn.set_attr(mssql_python.SQL_ATTR_ACCESS_MODE, mssql_python.SQL_MODE_READ_ONLY)

# Set transaction isolation level
conn.set_attr(mssql_python.SQL_ATTR_TXN_ISOLATION, mssql_python.SQL_TXN_SERIALIZABLE)

可用屬性:

恆定 描述
SQL_ATTR_CONNECTION_TIMEOUT 連線逾時(以秒為單位)。
SQL_ATTR_LOGIN_TIMEOUT 登入逾時時間(秒)
SQL_ATTR_PACKET_SIZE 網路封包大小。
SQL_ATTR_ACCESS_MODE 唯讀或讀寫模式。
SQL_ATTR_TXN_ISOLATION 交易隔離層級。
SQL_ATTR_CURRENT_CATALOG 目前的資料庫名稱。

預連接屬性

某些屬性必須在驅動程式建立連線前設定(例如,登入逾時)。 把它們傳過去 attrs_before

conn = mssql_python.connect(
    connection_string,
    attrs_before={
        mssql_python.SQL_ATTR_LOGIN_TIMEOUT: 30,
        mssql_python.SQL_ATTR_CONNECTION_TIMEOUT: 60,
    }
)

取得連線資訊

用於 getinfo() 擷取驅動程式與伺服器的元資料,用於日誌記錄、診斷或根據伺服器能力調整行為:

conn = mssql_python.connect(connection_string)

# Server information
print(f"Server name: {conn.getinfo(mssql_python.SQL_SERVER_NAME)}")
print(f"Database name: {conn.getinfo(mssql_python.SQL_DATABASE_NAME)}")

# Driver information
print(f"Driver name: {conn.getinfo(mssql_python.SQL_DRIVER_NAME)}")
print(f"Driver version: {conn.getinfo(mssql_python.SQL_DRIVER_VER)}")

取得可用資訊常數清單:

constants = mssql_python.get_info_constants()
for name, value in constants.items():
    print(f"{name}: {value}")

搜尋跳脫字元

searchescape 屬性會傳回在 LIKE 模式中用來逸出萬用字元(%_)的字元。 用它來安全地搜尋使用者輸入中的字面通配字元:

escape = conn.searchescape

# Use in queries with wildcard characters
cursor.execute(
    f"SELECT Name FROM Production.Product WHERE Name LIKE '%{escape}%%' ESCAPE '{escape}'"
)
# Matches names containing literal '%' character

編碼與解碼

為 SQL 陳述式與結果設定文字編碼。 預設設定對大多數應用程式都有效。 只有當你連接到使用非 UTF-8 編碼欄位 char/varchar 的伺服器時,才會更改它們。 伺服器所使用的編碼取決於 欄位排序

# Set encoding for outbound text
conn.setencoding(encoding='utf-8')

# Get current encoding settings
settings = conn.getencoding()
print(settings)  # {'encoding': 'utf-8', 'ctype': ...}

# Set decoding for inbound text from specific SQL types
conn.setdecoding(mssql_python.SQL_CHAR, encoding='utf-8')

# Get current decoding settings
settings = conn.getdecoding(mssql_python.SQL_CHAR)
print(settings)

預設編碼:

方向 SQL 類型 預設編碼
出站(str) SQL_WCHAR utf-16le
Inbound SQL_CHAR utf-8
Inbound SQL_WCHAR utf-16le
Inbound SQL_WMETADATA utf-16le

最佳做法

  • 使用上下文管理器with 區塊)來管理應用程式碼中的所有連線。 即使有例外,他們也能保證清理。
  • 使用連線池 (預設啟用)以提升效能。 請參見 連線池
  • 為你的網路環境設定適當的逾時時間。 30 秒的逾時設定適用於大多數雲端部署;若為跨區域或 VPN 連線,請提高逾時時間。
  • 使用 autocommit=False(預設值)來處理需要交易的原子性的資料修改情境。
  • 使用 autocommit=True 進行 DDL 操作、唯讀查詢及管理腳本。
  • 不要跨線分享連結。 驅動程式的執行緒安全等級為 1(執行緒可以共用模組,但不允許連接)。