mssql-python 驅動程式提供多種擷取方法、列存取模式及游標導航功能,用於查詢結果的擷取。
擷取方法
執行 SELECT 查詢後,使用取指方法取得結果。
fetchone()
回傳單一資料列;如果沒有更多資料列可用,則回傳 None:
cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product")
row = cursor.fetchone()
while row:
print(f"{row.ProductID}: {row.Name} - ${row.ListPrice}")
row = cursor.fetchone()
fetchmany()
回傳一串列。
cursor.arraysize 控制預設批次大小(預設:1):
cursor.execute("SELECT * FROM Production.Product")
cursor.arraysize = 100 # Fetch 100 rows at a time
while True:
rows = cursor.fetchmany()
if not rows:
break
for row in rows:
print(row.Name)
你也可以直接指定大小:
rows = cursor.fetchmany(50) # Fetch up to 50 rows
fetchall()
以清單形式回傳所有剩餘的列:
cursor.execute("SELECT * FROM Production.Product WHERE Color = 'Black'")
rows = cursor.fetchall()
print(f"Found {len(rows)} products")
for row in rows:
print(row.Name)
fetchval()
回傳第一列的第一欄,對純量查詢非常有用。
count = cursor.execute("SELECT COUNT(*) FROM Production.Product").fetchval()
print(f"Total products: {count}")
max_price = cursor.execute("SELECT MAX(ListPrice) FROM Production.Product").fetchval()
print(f"Highest price: ${max_price}")
列存取模式
該 Row 類別支援多重存取模式。
索引存取
按位置存取資料欄(從零開始):
cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID < 5")
row = cursor.fetchone()
product_id = row[0]
name = row[1]
price = row[2]
屬性存取
依名稱存取欄位:
cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID < 5")
row = cursor.fetchone()
product_id = row.ProductID
name = row.Name
price = row.ListPrice
小寫欄位名稱
全域啟用小寫屬性名稱:
import mssql_python
settings = mssql_python.get_settings()
settings.lowercase = True
cursor.execute("SELECT ProductID, Name FROM Production.Product WHERE ProductID < 5")
row = cursor.fetchone()
print(row.productid, row.name) # Lowercase access
settings.lowercase = False # Restore default
反覆運算
列支援對數值的迭代:
cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID < 5")
row = cursor.fetchone()
for value in row:
print(value)
游標迭代
直接對游標進行迭代以處理資料列:
cursor.execute("SELECT * FROM Production.Product")
for row in cursor:
print(row.Name)
這種模式等同於反覆呼叫 fetchone() 。
欄位元資料
透過 cursor.description 存取資料欄資訊:
cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID < 5")
for col in cursor.description:
name, type_code, display_size, internal_size, precision, scale, null_ok = col
print(f"Column: {name}, Type: {type_code}, Nullable: {null_ok}")
行數
屬性 cursor.rowcount 表示:
- 對於 SELECT:在
execute()之後、開始擷取之前,會傳回 -1。 一旦開始擷取,就會顯示到目前為止已累計擷取的資料列數。 - 對於 INSERT/UPDATE/DELETE:受影響的列數。
cursor.execute("SELECT * FROM Production.Product")
print(f"Rows returned: {cursor.rowcount}")
cursor.execute("CREATE TABLE #PriceUpd (Name NVARCHAR(50), Price DECIMAL(10,2), CategoryID INT)")
cursor.execute("INSERT INTO #PriceUpd VALUES ('A',10,1),('B',20,1),('C',30,2)")
cursor.execute("UPDATE #PriceUpd SET Price = Price * 1.1 WHERE CategoryID = 1")
print(f"Rows updated: {cursor.rowcount}")
游標導航
skip()
略過資料列而不擷取:
cursor.execute("SELECT * FROM Production.Product ORDER BY ProductID")
cursor.skip(10) # Skip first 10 rows
row = cursor.fetchone() # Returns 11th row
scroll()
將游標位置往前移動:
cursor.execute("SELECT * FROM Production.Product ORDER BY ProductID")
# Move forward 5 rows from current position
cursor.scroll(5, mode='relative')
row = cursor.fetchone()
Note
驅動程式僅支援正值的 mode='relative'。 絕對定位和向後捲動會引發 NotSupportedError,因為驅動程式使用的是僅向前游標。
行號
追蹤目前位置:
cursor.execute("SELECT * FROM Production.Product")
print(f"Initial position: {cursor.rownumber}") # -1 (before first fetch)
row = cursor.fetchone()
print(f"After fetchone: {cursor.rownumber}") # 0 (first row fetched)
多個結果集
用於 nextset() 處理多個結果集:
cursor.execute("""
SELECT * FROM Production.Product WHERE Color = 'Black';
SELECT * FROM Production.ProductCategory;
SELECT COUNT(*) FROM Production.Product;
""")
# First result set
products = cursor.fetchall()
print(f"Products: {len(products)}")
# Move to second result set
if cursor.nextset():
categories = cursor.fetchall()
print(f"Categories: {len(categories)}")
# Move to third result set
if cursor.nextset():
count = cursor.fetchval()
print(f"Total count: {count}")
大型結果集
對於大型結果集,請以批次處理列來管理記憶體:
def process_batch(rows):
# Example: print each row. Replace with your own logic.
for row in rows:
print(row)
cursor.execute("SELECT * FROM LargeTable")
cursor.arraysize = 1000
while True:
rows = cursor.fetchmany()
if not rows:
break
process_batch(rows)
print(f"Processed {cursor.rownumber} rows so far")
情境管理器
使用上下文管理器進行自動資源清理:
with mssql_python.connect(connection_string) as conn:
with conn.cursor() as cursor:
cursor.execute("SELECT * FROM Production.Product")
for row in cursor:
print(row.Name)
# Cursor and connection closed automatically
最佳做法
-
對於大型結果集,請使用
fetchmany(),以避免將所有內容載入記憶體。 - 完成後請關閉游標,以釋放伺服器資源。
- 使用欄位名稱 (屬性存取)以獲得更易讀的程式碼。
- 在資料修改陳述式之後檢查
rowcount。 - 當資料行可為空值時,請明確處理
None值。