Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Használja ezt a cikket a lekérdezés végrehajtása, adattípus, teljesítmény, tranzakció és tömeges másolási problémák diagnosztizálására az mssql-python illesztőprogramban.
Lekérdezés végrehajtási problémái
A tábla vagy objektum nem található
Tünetek:
ProgrammingError: [42S02] (208) Invalid object name 'TableName'.
Lehetséges okok és megoldások:
Hibás adatbázis-kontextus
cursor.execute("SELECT DB_NAME()") print(cursor.fetchone()[0])Nem meghatározott séma
cursor.execute("SELECT * FROM dbo.TableName")A táblázat nem létezik
cursor.execute(""" SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'TableName' """)
Szintaxishiba
Tünetek:
ProgrammingError: [42000] (102) Incorrect syntax near '...'.
Megoldások:
Tesztelje az SQL utasítást az SQL Server Management Studio-ban (SSMS) a szintaxisnak ellenőrzéséhez.
Paraméterezett lekérdezést használj string interpoláció helyett:
# 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}, )
Paraméterhibák
Tünetek:
ProgrammingError: [07001] Wrong number of parameters
Megoldások:
Számold meg a helykitöltőket és paramétereket. A számlálásoknak egyezniük kell.
Válaszd ki a megfelelő paraméterstílust:
# 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())
Adattípus-problémák
Dátumidő-átalakítási hibák
Tünetek:
DataError: [22007] Invalid datetime format
Solution:
Használj Python datetime objektumokat a stringek helyett.
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())
Tizedes pontossági problémák
Tünetek:
A számok lerövidítettnek vagy helytelenül kerekítve jelennek meg.
Solution:
Pontos numerikus értékek felhasználása decimal.Decimal :
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 kódolási problémák
Tünetek:
A speciális karakterek zavarosnak tűnnek vagy hibákat okoznak.
Megoldások:
Használj nvarchar oszlopokat Unicode adatokhoz az adatbázisodban.
Adja át közvetlenül a karakterláncokat. A meghajtó kezeli a kódolást:
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())
Teljesítménnyel kapcsolatos problémák
Lassú lekérdezés végrehajtása
Lehetséges okok és megoldások:
Hiányzó indexek: Ellenőrizd az SSMS-ben a lekérdezés végrehajtási tervet.
Nagy eredményhalmazok: Használd
fetchmany()helyettefetchall():cursor.arraysize = 1000 while True: rows = cursor.fetchmany() if not rows: break process_rows(rows)Csatlakozási csoportosítás letiltva: Engedélyezd a poolinget:
import mssql_python mssql_python.pooling(max_size=20, idle_timeout=300)
Memóriaproblémák nagy méretű eredmények esetén
Tünetek:
A Python folyamat kifogy a memóriából.
Megoldások:
Az eredményeket folyamatosan dolgozza fel ahelyett, hogy minden sort a memóriába töltene.
cursor.execute("SELECT * FROM LargeTable") for row in cursor: process_row(row)Használj szerveroldali lapozást.
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
Tranzakciós problémák
Ideiglenes táblák hatóköre automatikus véglegesítés mellett
A tranzakción belül létrehozott session temp táblák (#tablename) eltűnnek, amikor a tranzakció visszafordul. Ez a viselkedés gyakran zavart okoz, amikor az automatikus commitálás ki van kapcsolva, ami az alapértelmezett:
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")
Az ideiglenes tábla létrehozása után azonnal véglegesítsd a tranzakciót, vagy használd az autocommit módot:
cursor.execute("CREATE TABLE #TempData (ID INT, Name NVARCHAR(50))")
conn.commit()
cursor.execute("INSERT INTO #TempData VALUES (1, 'test')")
conn.commit()
DDL utasítások, amelyek automatikus commit módot igényelnek, például CREATE DATABASE, egy nyílt tranzakcióban meghibásodnak. Állítsd be az automatikus véglegesítést, mielőtt futtatod őket:
conn.autocommit = True
cursor.execute("CREATE DATABASE TestDB")
conn.autocommit = False
Nem végrehajtott tranzakció
Tünetek:
Az adatváltozások nem maradnak fenn, miután lezárod a kapcsolatot.
Solution:
A(z) autocommit=False használatával, ami az alapértelmezett, hívja meg a(z) commit() elemet:
cursor.execute("CREATE TABLE #Products (Name NVARCHAR(100))")
cursor.execute(
"INSERT INTO #Products (Name) VALUES (%(name)s)",
{"name": "Widget"},
)
conn.commit()
Alternatívaként használj automatikus commit módot:
conn = mssql_python.connect(connection_string, autocommit=True)
Holtzárhibák
Tünetek:
OperationalError: [40001] (1205) Transaction ... was deadlocked on lock resources with another process
Solution:
Az újrapróbálkozás logika kezeli az azonnali hibát, de az ismétlődő holtpontok tervezési problémára utalnak. Rögzítsd a holtponti gráfot, és elemezd az utasításokat, valamint a zárolási típusokat. Gyakori javítások közé tartoznak a következők:
- Rendezze át a műveleteket úgy, hogy az egymással versengő tranzakciók ugyanabban a sorrendben szerezzék meg a zárolásokat.
- Csökkentsd a tranzakciós hatókört.
- Megfelelő indexeket adj hozzá a zár időtartamának csökkentéséhez.
A holthelyzet elemzésének teljes végigjátszásáért lásd a Deadlocks útmutatót. Ha Azure SQL Database-et használ, lásd: Holtpontok elemzése és megelőzése.
Tömegterhelési problémák
Korlátok megsértése tömegmásolás során
Tünetek:
RuntimeError: CHECK constraint ... Conflict occurred in database ...
RuntimeError: Cannot insert duplicate key ... violation of PRIMARY KEY constraint
A probléma oka
A kötegben lévő adatok megsértik a tábla korlátozásait, például az elsődleges kulcsra, az egyediségre, az ellenőrzésre vagy az idegen kulcsra vonatkozó korlátozásokat.
Solution:
Ellenőrizd az adatokat, mielőtt betöltöd. Nagy adathalmazok esetén töltsd be az adatokat egy staging table-be, majd egyesítsd őket a célponttal:
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()
Az átmeneti táblákat használó upsert mintákkal kapcsolatban lásd a következőt: Adatbetöltési és -mozgatási minták.
Oszlopleképezési hibák
Tünetek:
RuntimeError: Bulk copy failure - column count mismatch
A probléma oka
Az adatodban lévő oszlopok száma nem egyezik a céltáblák oszlopszámával, vagy az oszlopok rossz sorrendben vannak.
Solution:
Győződj meg róla, hogy adataid sorrendben és számban egyeznek a táblázat sémával:
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)
Típusütközések tömeges másolás során
Tünetek:
Az adat betöltődik, de az értékek lerövidítettek, kerekítettek vagy helytelenek.
A probléma oka
A Python értékek nem egyeznek tisztán a céloszlop típusokkal. Gyakori példák közé float tartoznak a tizedes oszlopokba betöltött értékek, amelyek csökkenthetik a pontosságot, valamint a túlméretezett láncok, amelyek fix hosszúságú oszlopokba töltődnek.
Solution:
Használj olyan Python típusokat, amelyek megfelelnek a sémádnak:
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 típusú kötési hibák
Tünetek:
A paraméterek csendben hibásodnak vagy adattípus-hibákat okoznak, amikor NumPy egész számot vagy lebegő típust használsz.
A probléma oka
A NumPy típusok, mint numpy.int64 és numpy.int32 nem mennek isinstance(x, int) át a NumPy 2.x-ben. A sofőr típuskövetkeztetése nem ismeri fel őket, ami váratlan viselkedést okoz.
Solution:
Konvertáld a NumPy értékeket natív Python típusokra, mielőtt kötöd őket:
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"]),
},
)
Nagyobb adathalmazokhoz használd az Arrow vagy Pandas integrációs útvonalakat. Ezek az útvonalak belsőleg kezelik a típuskonverziót.
Tömeges másolat ideiglenes táblázatokkal
Tünetek:
cursor.bulkcopy("#TempTable", data) megemeli a(z) RuntimeError: Invalid object name '#TempTable' értékét.
A probléma oka
bulkcopy() Nem tudom megoldani a session temp táblákat (#tablename) a metaadat-keresés korlátai miatt. A globális hőmérsékleti táblázatok (##tablename) és az állandó táblázatok működnek.
Solution:
Használj globális temp táblát vagy hagyományos staging table-t:
# 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)
Kis adathalmazokhoz, ahol a session temp táblát részesíted előnyben, használd executemany()a következőket:
cursor.execute("CREATE TABLE #Staging (ID INT, Name NVARCHAR(50))")
cursor.executemany(
"INSERT INTO #Staging (ID, Name) VALUES (?, ?)",
rows,
)