Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Der mssql-python-Treiber bietet Cursor-Methoden für SQL-Abfrageausführung, parametrisierte Abfragen, Batch-Operationen und vorbereitete Anweisungen.
Grundlegende Abfrageausführung
Verwenden Sie die execute() Methode eines Cursors, um SQL-Anweisungen auszuführen:
import mssql_python
conn = mssql_python.connect(connection_string)
cursor = conn.cursor()
cursor.execute("SELECT Name, ListPrice FROM Production.Product WHERE Color = 'Black'")
rows = cursor.fetchall()
for row in rows:
print(row.Name, row.ListPrice)
cursor.close()
conn.close()
Parametrisierte Abfragen
Verwenden Sie parametrisierte Abfragen immer, um die SQL-Einfügung zu verhindern. Der standardmäßige Paramstyle des Treibers ist pyformat (benannte Platzhalter), er unterstützt aber auch qmark (positionale Platzhalter). Verwenden Sie qmark für ODBC-{CALL}Escape-Sequenzen.
Pyformat-Stil (Standard)
Verwenden Sie benannte Platzhalter mit der %(name)s-Syntax und übergeben Sie ein Wörterbuch:
cursor.execute(
"SELECT Name, ListPrice FROM Production.Product WHERE Color = %(color)s AND ListPrice > %(price)s",
{"color": "Black", "price": 10.00}
)
Qmark-Stil
Verwenden Sie positionsbezogene Platzhalter mit ? und passieren Sie ein Tupel oder eine Liste:
cursor.execute(
"SELECT Name, ListPrice FROM Production.Product WHERE ProductSubcategoryID = ? AND ListPrice > ?",
(1, 10.00)
)
Der Treiber erkennt automatisch den Parameterstil basierend auf deiner SQL-Abfrage und den Parametertypen.
INSERT, UPDATE, DELETE Operationen
Für Datenänderungsanweisungen verwenden Sie parametrisierte Abfragen und committen Sie die Transaktion:
cursor.execute("CREATE TABLE #ExecDemo (Name NVARCHAR(50), CategoryID INT, Price DECIMAL(10,2))")
cursor.execute(
"INSERT INTO #ExecDemo (Name, CategoryID, Price) VALUES (%(name)s, %(category)s, %(price)s)",
{"name": "New Product", "category": 1, "price": 19.99}
)
conn.commit()
print(f"Rows affected: {cursor.rowcount}")
Batch-Ausführung mit Executemany()
Verwenden Sie executemany(), um mehrere Zeilen effizient einzufügen. Der Treiber verwendet spaltenweise Parameterbindung für hohe Leistung:
products = [
{"name": "Product A", "category": 1, "price": 10.00},
{"name": "Product B", "category": 1, "price": 15.00},
{"name": "Product C", "category": 2, "price": 20.00},
]
cursor.execute("CREATE TABLE #BatchDemo (Name NVARCHAR(50), CategoryID INT, Price DECIMAL(10,2))")
cursor.executemany(
"INSERT INTO #BatchDemo (Name, CategoryID, Price) VALUES (%(name)s, %(category)s, %(price)s)",
products
)
conn.commit()
print(f"Rows inserted: {cursor.rowcount}")
Mit qmark-Stil:
products = [
("Product A", 1, 10.00),
("Product B", 1, 15.00),
("Product C", 2, 20.00),
]
cursor.execute("CREATE TABLE #QmarkDemo (Name NVARCHAR(50), CategoryID INT, Price DECIMAL(10,2))")
cursor.executemany(
"INSERT INTO #QmarkDemo (Name, CategoryID, Price) VALUES (?, ?, ?)",
products
)
conn.commit()
Batch-Ausführung mehrerer Anweisungen
Verwenden Sie batch_execute() für die Verbindung, um mehrere verschiedene Anweisungen in einem einzigen Aufruf auszuführen:
results, cursor = conn.batch_execute(
[
"CREATE TABLE #BatchExec (Name NVARCHAR(50), CategoryID INT)",
"INSERT INTO #BatchExec (Name, CategoryID) VALUES (%(name)s, %(cat)s)",
"SELECT COUNT(*) FROM #BatchExec"
],
[
None, # No params for CREATE
{"name": "New Item", "cat": 1}, # Params for INSERT
None # No params for SELECT
]
)
print(f"CREATE result: {results[0]}")
print(f"INSERT affected: {results[1]} rows")
print(f"Row count: {results[2][0][0]}")
Vorbereitete Anweisungen
Der Treiber bereitet standardmäßig Abfragen vor (use_prepare=True). Wenn du denselben SQL-String mehrfach auf demselben Cursor ausführst, verwendet der Treiber die vorbereitete Anweisung automatisch bei nachfolgenden Aufrufen:
# First execution prepares the statement
cursor.execute(
"SELECT Name, ListPrice FROM Production.Product WHERE ProductSubcategoryID = %(subcategory_id)s",
{"subcategory_id": 1},
)
rows1 = cursor.fetchall()
# Same SQL string on same cursor → driver reuses the prepared plan
cursor.execute(
"SELECT Name, ListPrice FROM Production.Product WHERE ProductSubcategoryID = %(subcategory_id)s",
{"subcategory_id": 2},
)
rows2 = cursor.fetchall()
Um die Vorbereitung zu überspringen und stattdessen direkte Ausführung zu verwenden:
cursor.execute(
"SELECT Name, ListPrice FROM Production.Product WHERE ProductSubcategoryID = 1",
use_prepare=False # Uses SQLExecDirectW instead of SQLPrepareW
)
Ausführung auf Verbindungsebene
Für einfache einmalige Abfragen verwenden Sie execute() direkt auf der Verbindung:
# Creates cursor, executes, and returns cursor
cursor = conn.execute("SELECT TOP 10 Name, ListPrice FROM Production.Product")
rows = cursor.fetchall()
cursor.close()
Gespeicherte Prozeduren
Rufen Sie gespeicherte Prozeduren mit EXECUTE oder der ODBC-Escape-Syntax {CALL} auf. Informationen zu Ausgabeparametern, mehreren Ergebnismengen und Transaktionsmustern finden Sie unter Gespeicherte Prozeduren.
cursor.execute(
"EXECUTE dbo.uspGetManagerEmployees @BusinessEntityID = %(business_entity_id)s",
{"business_entity_id": 16}
)
rows = cursor.fetchall()
Eingabegrößen festlegen
Verwenden Sie setinputsizes() , um Parametertypen explizit zu deklarieren, was die Leistung für Batch-Operationen verbessern kann:
cursor.setinputsizes([
(mssql_python.SQL_WVARCHAR, 50, 0), # NVARCHAR(50)
(mssql_python.SQL_INTEGER, 0, 0), # INT
])
cursor.executemany(
"SELECT ProductID, Name FROM Production.Product WHERE Name LIKE ? AND ProductSubcategoryID = ?",
[("Road%", 2), ("Mountain%", 1)]
)
Note
Nicht alle SQL-Typkonstanten funktionieren mit setinputsizes().
SQL_WVARCHAR und SQL_INTEGER zuverlässig sind. Für Dezimalwerte verwenden Sie die automatische Typinferenz des Treibers anstelle von SQL_DECIMAL, da hierfür ein bekanntes Problem besteht (GitHub #503).
Fehlerbehandlung
Datenbankoperationen in Try-Except-Blöcke einschließen:
try:
cursor.execute("CREATE TABLE #ErrDemo (Name NVARCHAR(50) NOT NULL)")
cursor.execute("INSERT INTO #ErrDemo (Name) VALUES (%(name)s)", {"name": None})
conn.commit()
except mssql_python.IntegrityError as e:
print(f"Constraint violation: {e}")
conn.rollback()
except mssql_python.ProgrammingError as e:
print(f"SQL error: {e}")
conn.rollback()
Bewährte Methoden
- Verwenden Sie immer parametrisierte Abfragen, um SQL-Injektionen zu verhindern.
-
Verwenden Sie bulk copy für Masseneinfügungen anstelle mehrerer
execute()-Aufrufe. - Bestätigen Sie Transaktionen explizit, wenn Sie den Autocommit-Modus deaktivieren.
- Schließen Sie Cursor und Verbindungen , wenn Sie fertig sind, um Ressourcen freizusetzen.
- Verwenden Sie Kontextmanager für die automatische Ressourcenbereinigung:
with mssql_python.connect(connection_string) as conn:
with conn.cursor() as cursor:
cursor.execute("SELECT TOP 5 Name, ListPrice FROM Production.Product")
rows = cursor.fetchall()
# Connection and cursor automatically closed