Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu makaleyi sürücüyle ilgili sorgu yürütme, veri türü, performans, işlem ve toplu kopyalama sorunlarını mssql-python teşhis etmek için kullanın.
Sorgu yürütme sorunları
Tablo veya nesne bulunamadı
Belirti -leri:
ProgrammingError: [42S02] (208) Invalid object name 'TableName'.
Olası nedenler ve çözümler:
Yanlış veritabanı bağlamı
cursor.execute("SELECT DB_NAME()") print(cursor.fetchone()[0])Belirtilmemiş şema
cursor.execute("SELECT * FROM dbo.TableName")Tablo yok
cursor.execute(""" SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'TableName' """)
Söz dizimi hatası
Belirti -leri:
ProgrammingError: [42000] (102) Incorrect syntax near '...'.
Çözümler:
Sözdizimi doğrulamak için SQL ifadesini SQL Server Management Studio (SSMS)'de test edin.
Dizi interpolasyonu yerine parametrizlenmiş bir sorgu kullanın:
# Don't use string interpolation for query parameters. cursor.execute(f"SELECT * FROM Production.Product WHERE Name = '{name}'") # Use parameters. cursor.execute( "SELECT * FROM Production.Product WHERE Name = %(name)s", {"name": name}, )
Parametre hataları
Belirti -leri:
ProgrammingError: [07001] Wrong number of parameters
Çözümler:
Yer tutucuları ve parametreleri say. Sayılar aynı olmalı.
Doğru parametre stilini seçin:
# Qmark style: positional parameters cursor.execute( "SELECT * FROM Production.Product " "WHERE ProductID = ? AND Name LIKE ?", (1, "Adjustable%"), ) print(cursor.fetchone()) # Pyformat style: named parameters cursor.execute( "SELECT * FROM Production.Product " "WHERE ProductID = %(id)s AND Name LIKE %(name)s", {"id": 1, "name": "Adjustable%"}, ) print(cursor.fetchone())
Veri tipi sorunları
Tarih saati dönüşüm hataları
Belirti -leri:
DataError: [22007] Invalid datetime format
Çözüm:
Dizeler yerine Python datetime nesneleri kullanın.
from datetime import datetime
cursor.execute("CREATE TABLE #Events (EventDate DATETIME)")
# This value raises an error because the date is invalid.
try:
cursor.execute(
"INSERT INTO #Events (EventDate) VALUES (%(event_date)s)",
{"event_date": "2024-13-45"},
)
except Exception as e:
print(f"Expected error: {e}")
# Use a Python datetime object.
cursor.execute(
"INSERT INTO #Events (EventDate) VALUES (%(event_date)s)",
{"event_date": datetime(2024, 3, 15)},
)
cursor.execute("SELECT EventDate FROM #Events")
print(cursor.fetchone())
Ondalık hassasiyet sorunları
Belirti -leri:
Sayılar kısaltılmış veya yanlış yuvarlanmış gibi görünür.
Çözüm:
Kesin sayısal değerler için decimal.Decimal kullanın:
from decimal import Decimal
cursor.execute("CREATE TABLE #PriceDemo (ListPrice DECIMAL(10, 2))")
cursor.execute(
"INSERT INTO #PriceDemo (ListPrice) VALUES (%(list_price)s)",
{"list_price": Decimal("19.99")},
)
Unicode kodlama sorunları
Belirti -leri:
Özel karakterler karışık görünür veya hatalara yol açar.
Çözümler:
Veritabanınızdaki Unicode verileri için nvarchar sütunlarını kullanın.
Dizgeleri doğrudan iletin. Sürücü kodlamayı yönetir:
cursor.execute("CREATE TABLE #UnicodeDemo (Name NVARCHAR(50))") cursor.execute( "INSERT INTO #UnicodeDemo (Name) VALUES (%(name)s)", {"name": "日本語"}, ) cursor.execute("SELECT Name FROM #UnicodeDemo") print(cursor.fetchone())
Performans sorunları
Yavaş sorgu yürütme
Olası nedenler ve çözümler:
Eksik indeksler: SSMS'de sorgu yürütme planını kontrol edin.
Büyük sonuç kümeleri: Yerine
fetchall()kullanınfetchmany():cursor.arraysize = 1000 while True: rows = cursor.fetchmany() if not rows: break process_rows(rows)Bağlantı havuzlama devre dışı bırakıldı: Havuzlama etkinleştirin:
import mssql_python mssql_python.pooling(max_size=20, idle_timeout=300)
Büyük sonuçlarda bellek sorunları
Belirti -leri:
Python sürecinin belleği tükeniyor.
Çözümler:
Tüm satırları belleğe yüklemek yerine sonuçları akış yapın.
cursor.execute("SELECT * FROM LargeTable") for row in cursor: process_row(row)Sunucu tarafı sayfalama kullanın.
page_size = 1000 offset = 0 while True: cursor.execute( "SELECT * FROM LargeTable ORDER BY ID " "OFFSET ? ROWS FETCH NEXT ? ROWS ONLY", (offset, page_size), ) rows = cursor.fetchall() if not rows: break process_rows(rows) offset += page_size
İşlem sorunları
Otomatik commit ile geçici tablo kapsamı
Bir işlem içinde oluşturduğunuz oturum geçici tabloları (#tablename) işlem geri çekildiğinde kaybolur. Bu davranış genellikle otomatik commit kapalı olduğunda karışıklığa yol açar ve bu varsayılan durumdur:
conn = mssql_python.connect(connection_string)
cursor = conn.cursor()
cursor.execute("CREATE TABLE #TempData (ID INT, Name NVARCHAR(50))")
cursor.execute("INSERT INTO #TempData VALUES (1, 'test')")
# An explicit rollback or an error removes #TempData.
conn.rollback()
# This statement fails with "Invalid object name '#TempData'".
cursor.execute("SELECT * FROM #TempData")
Geçici bir tablo oluşturduktan hemen sonra commit yapın veya otomatik commit modunu kullanın:
cursor.execute("CREATE TABLE #TempData (ID INT, Name NVARCHAR(50))")
conn.commit()
cursor.execute("INSERT INTO #TempData VALUES (1, 'test')")
conn.commit()
Otomatik commit modunu gerektiren DDL ifadeleri, örneğin CREATE DATABASE, açık bir işlem içinde başarısız olur. Bunları çalıştırmadan önce otomatik işlemeyi ayarlayın:
conn.autocommit = True
cursor.execute("CREATE DATABASE TestDB")
conn.autocommit = False
İşlem yapılmadı
Belirti -leri:
Bağlantı kapattıktan sonra veri değişiklikleri devam etmiyor.
Çözüm:
Varsayılan olan autocommit=False ile commit() çağrısını yapın:
cursor.execute("CREATE TABLE #Products (Name NVARCHAR(100))")
cursor.execute(
"INSERT INTO #Products (Name) VALUES (%(name)s)",
{"name": "Widget"},
)
conn.commit()
Alternatif olarak, otomatik commit modunu kullanın:
conn = mssql_python.connect(connection_string, autocommit=True)
Kilitlenme hataları
Belirti -leri:
OperationalError: [40001] (1205) Transaction ... was deadlocked on lock resources with another process
Çözüm:
Yeniden deneme mantığı anında hatayı yönetir, ancak tekrarlayan çıkmazlar bir tasarım sorunu olduğunu gösterir. Deadlock grafiğini yakalayın ve ifadeleri ile kilit türlerini analiz edin. Yaygın çözümler arasında şu değişiklikler yer alır:
- Rakip işlemler aynı sırayla kilitler elde etmek için işlemleri yeniden sıralar.
- İşlem kapsamını azaltın.
- Kilit süresini azaltmak için uygun indeksler ekleyin.
Deadlock analizine dair ayrıntılı bir açıklama için Kilitlenmeler rehberine bakın. Azure SQL Veritabanı kullanıyorsanız, Kilitlenmeleri analiz etme ve önleme konusuna bakın.
Toplu yükleme sorunları
Toplu kopide sırasında kısıtlama ihlalleri
Belirti -leri:
RuntimeError: CHECK constraint ... Conflict occurred in database ...
RuntimeError: Cannot insert duplicate key ... violation of PRIMARY KEY constraint
Neden:
Toplu işlemdeki verileriniz, birincil anahtar, benzersiz, denetim veya yabancı anahtar kısıtlamaları gibi tablo kısıtlamalarını ihlal ediyor.
Çözüm:
Verileri yüklemeden önce doğrulayın. Büyük veri setleri için, veriyi bir aşamalama tablosuna yükleyin ve ardından hedefe birleştirin:
cursor.execute("CREATE TABLE ##Staging (ID INT, Name NVARCHAR(100))")
cursor.bulkcopy("##Staging", rows)
# Check for duplicate rows before the merge.
cursor.execute("""
SELECT s.ID
FROM ##Staging AS s
INNER JOIN dbo.Target AS t
ON s.ID = t.ID
""")
dupes = cursor.fetchall()
if dupes:
print(f"Skipping {len(dupes)} duplicate rows")
# Insert rows that don't exist in the target.
cursor.execute("""
INSERT INTO dbo.Target (ID, Name)
SELECT s.ID, s.Name
FROM ##Staging AS s
WHERE NOT EXISTS (
SELECT 1
FROM dbo.Target AS t
WHERE t.ID = s.ID
)
""")
conn.commit()
Aşama tablolarıyla upsert desenleri için bkz. Veri yükleme ve hareket desenleri.
Sütun eşleme hataları
Belirti -leri:
RuntimeError: Bulk copy failure - column count mismatch
Neden:
Verinizdeki sütun sayısı, hedef tablo sütun sayısıyla eşleşmiyor ya da sütunlar yanlış sırada.
Çözüm:
Verilerinizin sırayla ve sayısal olarak tablo şemasıyla eşleştiğinden emin olun:
from decimal import Decimal
cursor.execute("""
SELECT COLUMN_NAME, DATA_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'MyTable'
ORDER BY ORDINAL_POSITION
""")
for col in cursor.fetchall():
print(col)
rows = [
(1, "Widget", Decimal("19.99")),
(2, "Gadget", Decimal("29.99")),
]
cursor.bulkcopy("dbo.MyTable", rows)
Toplu kopyalama sırasında tip uyumsuzlukları
Belirti -leri:
Veri yüklenir, ancak değerler kısaltılmış, yuvarlatılmış veya yanlıştır.
Neden:
Python değerleri hedef sütun tipleriyle tam olarak eşleşmez. Yaygın örnekler arasında, decimal sütunlarına yüklenen ve hassasiyet kaybına yol açabilen float değerler ile sabit uzunluktaki sütunlara yüklenen gereğinden uzun dizeler yer alır.
Çözüm:
Şemanıza uyan Python türlerini kullanın:
from decimal import Decimal
rows = [
# Use Decimal for decimal and numeric columns.
(1, "Widget", Decimal("19.99")),
# Avoid float values because they can lose precision.
# (1, "Widget", 19.99),
]
cursor.bulkcopy("dbo.Products", rows)
NumPy tip bağlanma hataları
Belirti -leri:
NumPy tamsayı veya float tipleri kullandığınızda parametreler sessizce başarısız olur veya veri tipi hatalarını artırır.
Neden:
numpy.int64 ve numpy.int32 gibi NumPy türleri, NumPy 2.x'te isinstance(x, int) denetimini geçmez. Sürücünün tip çıkarımı onları tanımaz, bu da beklenmedik davranışlara yol açar.
Çözüm:
NumPy değerlerini bağlamadan önce yerel Python tiplerine dönüştürün:
import numpy as np
cursor.execute(
"SELECT * FROM Production.Product WHERE ProductID = %(product_id)s",
{"product_id": int(np.int64(42))},
)
for _, row in df.iterrows():
cursor.execute(
"INSERT INTO #Orders (ProductID, Qty) "
"VALUES (%(product_id)s, %(qty)s)",
{
"product_id": int(row["ProductID"]),
"qty": int(row["Qty"]),
},
)
Daha büyük veri setleri için Arrow veya pandas entegrasyon yollarını kullanın. Bu yollar tip dönüşümünü dahili olarak yönetir.
Geçici tablolarla toplu kopyalama
Belirti -leri:
cursor.bulkcopy("#TempTable", data), RuntimeError: Invalid object name '#TempTable' yükseltir.
Neden:
bulkcopy() meta veri arama sınırlamaları nedeniyle oturum geçici tablolarını (#tablename) çözemiyor. Genel geçici tablolar (##tablename) ve kalıcı tablolar çalışır.
Çözüm:
Küresel bir geçici tablo veya normal bir aşama tablosu kullanın:
# A global temp table is visible to all sessions and is dropped
# when the last session disconnects.
cursor.execute("CREATE TABLE ##Staging (ID INT, Name NVARCHAR(50))")
cursor.bulkcopy("##Staging", rows)
# Alternatively, use a permanent staging table.
cursor.execute("CREATE TABLE dbo.Staging (ID INT, Name NVARCHAR(50))")
cursor.bulkcopy("dbo.Staging", rows)
Oturum geçici tablosunu tercih ettiğiniz küçük veri kümeleri için şunları kullanın executemany():
cursor.execute("CREATE TABLE #Staging (ID INT, Name NVARCHAR(50))")
cursor.executemany(
"INSERT INTO #Staging (ID, Name) VALUES (?, ?)",
rows,
)