Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Sterownik mssql-python zapewnia metody kursora do wykonywania zapytań SQL, parametryzowanych zapytań, operacji wsadowych oraz przygotowanych instrukcji.
Podstawowe wykonywanie zapytań
Użyj metody kursora execute() do uruchamiania instrukcji SQL:
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()
Zapytania sparametryzowane
Zawsze używaj zapytań sparametryzowanych, aby zapobiec wstrzyknięciu kodu SQL. Domyślny styl parametrów sterownika to pyformat (nazwane symbole zastępcze), ale obsługuje także qmark (pozycyjne symbole zastępcze). Użyj qmark dla sekwencji ucieczki ODBC {CALL}.
Styl Pyformat (domyślny)
Używaj nazwanych symboli zastępczych w składni %(name)s i przekaż słownik:
cursor.execute(
"SELECT Name, ListPrice FROM Production.Product WHERE Color = %(color)s AND ListPrice > %(price)s",
{"color": "Black", "price": 10.00}
)
Styl Qmark
Używaj pozycyjnych symboli zastępczych z ? i przekaż krotkę lub listę:
cursor.execute(
"SELECT Name, ListPrice FROM Production.Product WHERE ProductSubcategoryID = ? AND ListPrice > ?",
(1, 10.00)
)
Sterownik automatycznie wykrywa styl parametrów na podstawie zapytań SQL i typów parametrów.
INSERT, UPDATE, DELETE operacje
Dla instrukcji modyfikacji danych używaj parametryzowanych zapytań i zatwierdzaj transakcję:
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}")
Wykonanie wsadowe za pomocą executemany()
Użyj executemany(), aby wydajnie wstawiać wiele wierszy. Sterownik stosuje kolumnowe wiązanie parametrów, aby uzyskać wysoką wydajność:
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}")
W stylu „qmark”:
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()
Wsadowe wykonywanie wielu instrukcji
Użyj batch_execute() na połączeniu do wykonania wielu różnych instrukcji w jednym wywołaniu:
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]}")
Zapytania przygotowywane
Sterownik domyślnie przygotowuje zapytania (use_prepare=True). Gdy wykonasz ten sam ciąg SQL wielokrotnie na tym samym kursorze, sterownik automatycznie ponownie wykorzystuje przygotowane zdanie przy kolejnych wywołaniach:
# 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()
Aby pominąć przygotowanie i użyć bezpośredniego wykonania:
cursor.execute(
"SELECT Name, ListPrice FROM Production.Product WHERE ProductSubcategoryID = 1",
use_prepare=False # Uses SQLExecDirectW instead of SQLPrepareW
)
Wykonywanie na poziomie połączenia
Dla prostych, jednorazowych zapytań użyj execute() bezpośrednio na połączeniu:
# Creates cursor, executes, and returns cursor
cursor = conn.execute("SELECT TOP 10 Name, ListPrice FROM Production.Product")
rows = cursor.fetchall()
cursor.close()
Procedury przechowywane
Wywołuj procedury przechowywane przy użyciu EXECUTE lub składni escape ODBC {CALL}. Aby uzyskać informacje o parametrach wyjściowych, wielu zestawach wyników i wzorcach transakcyjnych, zobacz Procedury przechowywane.
cursor.execute(
"EXECUTE dbo.uspGetManagerEmployees @BusinessEntityID = %(business_entity_id)s",
{"business_entity_id": 16}
)
rows = cursor.fetchall()
Ustaw rozmiary wejść
Użyj setinputsizes(), aby jawnie deklarować typy parametrów, co może poprawić wydajność w przypadku operacji wsadowych:
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
Nie wszystkie stałe typów SQL działają z setinputsizes().
SQL_WVARCHAR i SQL_INTEGER są niezawodne. Dla wartości dziesiętnych użyj automatycznego wnioskowania typów sterownika zamiast SQL_DECIMAL, które ma znany problem (GitHub #503).
Obsługa błędów
Umieść operacje na bazie danych w blokach try-except:
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()
Najlepsze rozwiązania
- Zawsze używaj parametryzowanych zapytań , aby zapobiec wstrzykiwaniu SQL.
-
Używaj bulk copy do zbiorczego wstawiania danych zamiast wielu wywołań
execute(). - Jawnie zatwierdzaj transakcje, gdy wyłączysz tryb autocommit.
- Zamykaj kursory i połączenia , gdy to robisz, aby uwolnić zasoby.
- Używaj menedżerów kontekstu do automatycznego czyszczenia zasobów:
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