Mengambil data dengan mssql-python

Driver mssql-python menawarkan beberapa metode pengambilan, pola akses baris, dan fitur navigasi kursor untuk mengambil hasil kueri.

Metode pengambilan

Setelah menjalankan kueri SELECT, gunakan metode fetch untuk mengambil hasil.

fetchone()

Mengembalikan satu baris atau None jika tidak ada lagi baris yang tersedia:

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()

Mengembalikan daftar baris. cursor.arraysize Mengontrol ukuran batch default (default: 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)

Anda juga dapat menentukan ukuran secara langsung:

rows = cursor.fetchmany(50)  # Fetch up to 50 rows

fetchall()

Mengembalikan semua baris yang tersisa sebagai daftar:

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()

Mengembalikan kolom pertama dari baris pertama, yang berguna untuk kueri skalar.

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}")

Pola akses baris

Kelas ini Row mendukung beberapa pola akses.

Akses indeks

Akses kolom berdasarkan posisi (berbasis nol):

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]

Akses atribut

Akses kolom berdasarkan nama:

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

Nama kolom dalam huruf kecil

Aktifkan nama atribut huruf kecil secara global:

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

Iteration

Baris mendukung iterasi atas nilai:

cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID < 5")
row = cursor.fetchone()

for value in row:
    print(value)

Iterasi kursor

Lakukan iterasi langsung pada kursor untuk memproses baris:

cursor.execute("SELECT * FROM Production.Product")

for row in cursor:
    print(row.Name)

Pola ini setara dengan memanggil fetchone() berulang kali.

Metadata kolom

Akses informasi kolom melalui 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}")

Jumlah baris

Atribut cursor.rowcount menunjukkan:

  • Untuk SELECT: Mengembalikan -1 setelah execute() hingga proses pengambilan dimulai. Setelah Anda mulai mengambil data, ini mencerminkan jumlah kumulatif baris yang telah diambil hingga saat ini.
  • Untuk INSERT/UPDATE/DELETE: Jumlah baris yang terpengaruh.
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}")

Navigasi kursor

lewati ()

Lewati baris tanpa mengambil datanya:

cursor.execute("SELECT * FROM Production.Product ORDER BY ProductID")
cursor.skip(10)  # Skip first 10 rows
row = cursor.fetchone()  # Returns 11th row

scroll()

Pindahkan posisi kursor ke depan:

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

Driver hanya mendukung mode='relative' yang bernilai positif. Pemosisian absolut dan pengguliran mundur dinaikkan NotSupportedError karena driver menggunakan kursor maju saja.

nomor baris

Lacak posisi saat ini:

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)

Beberapa kumpulan hasil

Gunakan nextset() untuk memproses beberapa kumpulan hasil:

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}")

Kumpulan hasil yang besar

Untuk kumpulan hasil besar, proses baris dalam batch untuk mengelola memori:

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")

Manajer konteks

Gunakan pengelola konteks untuk pembersihan sumber daya otomatis:

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

Praktik terbaik

  • Gunakan fetchmany() untuk hasil besar untuk menghindari memuat semuanya ke dalam memori.
  • Tutup kursor saat selesai untuk melepaskan sumber daya server.
  • Gunakan nama kolom (akses atribut) untuk kode yang lebih mudah dibaca.
  • Periksa rowcount setelah pernyataan modifikasi data.
  • Tangani nilai None secara eksplisit saat kolom dapat bernilai null.