mssql-pythonドライバーは、クエリ結果を取得するための複数のフェッチメソッド、行アクセスパターン、カーソルナビゲーション機能を提供します。
取得メソッド
SELECTクエリを実行した後、フェッチメソッドを使って結果を取得します。
fetchone()
1 行を返します。これ以上利用可能な行がない場合は 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
フェッチャル()
残りのすべての行をリストとして返します:
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。 - 列がnullableな場合
None値を明示的に扱います。