Kelola koneksi dengan mssql-python

Sebagian besar aplikasi mengikuti pola sederhana: buka koneksi, jalankan kueri, tutup koneksi. Bagian berikut mencakup pembukaan dan penutupan koneksi, menggunakan pengelola konteks, mengonfigurasi penerapan otomatis, dan bekerja dengan atribut koneksi.

Membuka koneksi

Gunakan fungsi connect() untuk membangun koneksi. Berikan string koneksi yang berisi detail server, database, dan autentikasi Anda:

import mssql_python

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

Fungsi connect() menerima:

  • String koneksi sebagai argumen posisional pertama atau kata kunci connection_str.
  • Kata kunci individual yang digabungkan oleh driver ke dalam string koneksi.
  • Opsi lain seperti autocommit, timeout, dan attrs_before.

Anda dapat mencampur kedua pendekatan tersebut. Kata kunci mengganti nilai dalam string koneksi, yang berguna saat Anda menyimpan string koneksi dasar dalam konfigurasi dan mengganti pengaturan seperti timeout per panggilan:

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

Menutup koneksi

Selalu tutup koneksi setelah selesai untuk mengembalikannya ke kumpulan koneksi dan melepaskan sumber daya server. Koneksi yang tidak tertutup menyimpan memori sisi server dan pada akhirnya dapat menghabiskan kumpulan koneksi, menyebabkan upaya koneksi baru diblokir atau gagal.

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

Setelah ditutup, koneksi tidak dapat digunakan:

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

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

Menelepon close() beberapa kali aman (idempoten):

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

Manajer konteks

Gunakan pernyataan with untuk mengelola koneksi di sebagian besar aplikasi. Ini menjamin bahwa pengemudi menutup koneksi saat blok keluar, bahkan jika terjadi pengecualian. Pendekatan ini menghilangkan risiko koneksi bocor dari panggilan yang terlupakan 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

Pengelola konteks menutup koneksi saat keluar. Ini tidak secara otomatis meng-commit atau membatalkan transaksi:

  • Selalu: Memanggil close() saat keluar, baik terjadi pengecualian maupun tidak.
  • close() perilaku: Jika autocommit=False, setiap perubahan yang belum dikomitkan akan dibatalkan saat koneksi ditutup.
  • Anda harus memanggil conn.commit() secara eksplisit untuk mempertahankan perubahan.

Desain ini mengikuti perilaku PEP 249 dan mencegah penerapan parsial yang tidak disengaja. Jika kode Anda memunculkan pengecualian sebelum mencapai commit(), transaksi yang sedang berlangsung akan dikembalikan dengan aman:

# 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

Mode komit otomatis

Secara default, autocommit=False, yang berarti setiap pernyataan berjalan di dalam transaksi implisit. Anda harus memanggil conn.commit() untuk menyimpan perubahan atau conn.rollback() untuk membatalkannya. Transaksi implisit adalah pilihan teraman untuk modifikasi data karena memungkinkan Anda mengelompokkan beberapa pernyataan ke dalam satu operasi atom.

Aktifkan penerapan otomatis saat Anda ingin setiap pernyataan segera diterapkan. Autocommit berguna untuk operasi DDL (CREATE TABLE, ALTER INDEX), beban kerja baca-saja, atau skrip administrasi yang tidak memerlukan pengelompokan transaksi:

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

Aktifkan autocommit untuk setiap statemen agar langsung dikomit. Gunakan autocommit=True saat menghubungkan, atau aktifkan/nonaktifkan setelah tersambung dengan setautocommit() atau penetapan properti secara langsung:

# 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

Waktu koneksi habis

Atur batas waktu koneksi untuk mengontrol berapa lama driver menunggu untuk membuat koneksi sebelum menimbulkan kesalahan. Batas waktu koneksi yang wajar penting untuk aplikasi yang disebarkan di lingkungan dengan jaringan yang tidak dapat diandalkan atau untuk gagal dengan cepat saat server tidak dapat dijangkau:

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

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

Nilai timeout sebesar 0 berarti tidak ada batas waktu (menunggu tanpa batas). Tentukan batas waktu yang wajar di lingkungan produksi; percobaan koneksi yang macet tanpa batas waktu akan memblokir thread pemanggil secara permanen.

Atribut koneksi

Gunakan set_attr() untuk mengubah perilaku koneksi saat runtime. Atribut koneksi mengontrol pengaturan driver tingkat rendah seperti mode akses, isolasi transaksi, dan ukuran paket. Sebagian besar aplikasi tidak perlu mengubah atribut ini, tetapi aplikasi ini berguna untuk skenario tertentu:

  • Mode baca-saja: Mencegah penulisan yang tidak disengaja dalam kueri pelaporan.
  • Isolasi transaksi: Mengontrol bagaimana transaksi bersamaan berinteraksi (gunakan SERIALIZABLE untuk konsistensi yang ketat, READ_COMMITTED untuk penggunaan umum).
  • Ukuran paket: Sesuaikan untuk jaringan latensi tinggi atau throughput tinggi.
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)

Atribut yang tersedia:

Konstanta Deskripsi
SQL_ATTR_CONNECTION_TIMEOUT Batas waktu koneksi dalam hitungan detik.
SQL_ATTR_LOGIN_TIMEOUT Batas waktu masuk dalam hitungan detik.
SQL_ATTR_PACKET_SIZE Ukuran paket jaringan.
SQL_ATTR_ACCESS_MODE Mode baca-saja atau baca-tulis.
SQL_ATTR_TXN_ISOLATION Tingkat isolasi transaksi.
SQL_ATTR_CURRENT_CATALOG Nama database saat ini.

Atribut prakoneksi

Beberapa atribut harus diatur sebelum driver membuat koneksi (misalnya, batas waktu masuk). Lewati mereka melalui attrs_before:

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

Mendapatkan informasi koneksi

Gunakan getinfo() untuk mengambil metadata driver dan server untuk pengelogan, diagnostik, atau perilaku adaptasi berdasarkan kemampuan server:

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

Dapatkan daftar konstanta info yang tersedia:

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

Cari karakter escape

Properti searchescape mengembalikan karakter yang digunakan sebagai karakter escape untuk wildcard (% dan _) dalam pola LIKE. Gunakan ini untuk mencari karakter wildcard literal dengan aman dalam input pengguna:

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

Pengkodean dan penguraian kode

Konfigurasikan pengodean teks untuk pernyataan dan hasil SQL. Pengaturan default berfungsi untuk sebagian besar aplikasi. Ubah pengaturan tersebut hanya jika Anda terhubung ke server yang menggunakan pengodean non-UTF-8 untuk kolom char/varchar. Pengodean yang digunakan server bergantung pada kolase kolom:

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

Pengodean bawaan:

Arah Jenis SQL Enkode bawaan
Keluar (str) SQL_WCHAR utf-16le
Masukan SQL_CHAR utf-8
Masukan SQL_WCHAR utf-16le
Masukan SQL_WMETADATA utf-16le

Praktik terbaik

  • Gunakan pengelola konteks (with blok) untuk semua koneksi dalam kode aplikasi. Mereka menjamin pembersihan bahkan ketika pengecualian terjadi.
  • Gunakan pengumpulan koneksi untuk performa yang lebih baik (diaktifkan secara default). Lihat Pengumpulan koneksi.
  • Atur batas waktu yang sesuai untuk lingkungan jaringan Anda. Batas waktu 30 detik cocok untuk sebagian besar penerapan cloud; tingkatkan untuk koneksi lintas wilayah atau VPN.
  • Penggunaan autocommit=False (default) untuk skenario modifikasi data di mana Anda memerlukan atomisitas transaksional.
  • Penggunaan autocommit=True untuk operasi DDL, kueri baca-saja, dan skrip admin.
  • Jangan berbagi koneksi antarutas. Tingkat keamanan ulir driver adalah 1 (ulir dapat berbagi modul tetapi bukan koneksi).