Obsługa błędów i kody SQLSTATE dla mssql-python

Sterownik mssql-python definiuje standardową hierarchię wyjątków, typowe wzorce obsługi błędów oraz mapowania kodu SQLSTATE dla SQL Server i Azure SQL.

Hierarchia wyjątków

Sterownik mssql-python podąża za hierarchią wyjątków DB-API 2.0 (PEP 249):

Exception (builtins)
├── Warning
└── Error
    ├── InterfaceError
    └── DatabaseError
        ├── DataError
        ├── OperationalError
        ├── IntegrityError
        ├── InternalError
        ├── ProgrammingError
        └── NotSupportedError

ConnectionStringParseError (standalone, not part of hierarchy)

Opisy wyjątków

Złap najbardziej konkretny wyjątek, który pasuje do Twojej sytuacji. Na przykład catch IntegrityError za naruszenia ograniczeń na INSERT/UPDATE operacjach oraz ProgrammingError na problemy składniowe SQL podczas rozwoju. Złap klasę bazową Error tylko jako zapas.

Exception Po podniesieniu
Warning Ostrzeżenia o nieśmiertelnych zagrożeniach z bazy danych.
Error Klasa bazowa dla wszystkich błędów bazy danych.
InterfaceError Błędy związane z interfejsem bazy danych (sterownikiem), a nie z samą bazą danych.
DatabaseError Błędy związane z bazą danych.
DataError Błędy wynikające z problemów z przetwarzanymi danymi (dzielenie przez zero, wartość poza zakresem).
OperationalError Błędy związane z działaniem bazy danych (utrata połączenia, przydział pamięci, błędy transakcji).
IntegrityError Błędy przy naruszaniu integralności bazy danych (naruszenie klucza obcego, unikalne ograniczenie).
InternalError Wewnętrzne błędy bazy danych (kursor niepoprawny, transakcja niezsynchronizowana).
ProgrammingError Błędy programistyczne (błędy składniowe, tabela nie znaleziona, błędna liczba parametrów).
NotSupportedError Funkcja nieobsługiwana przez bazę danych ani sterownik.
ConnectionStringParseError Nieprawidłowa składnia parametry połączenia lub nieznane słowa kluczowe.

Podstawowe zarządzanie błędami

Używaj bloków try-except do obsługi błędów bazy danych:

import mssql_python

try:
    conn = mssql_python.connect(connection_string)
    cursor = conn.cursor()
    cursor.execute("INSERT INTO Production.Product (Name) VALUES (%(name)s)", {"name": "Test"})
    conn.commit()
except mssql_python.IntegrityError as e:
    print(f"Constraint violation: {e}")
    conn.rollback()
except mssql_python.ProgrammingError as e:
    print(f"SQL syntax error: {e}")
except mssql_python.OperationalError as e:
    print(f"Connection or operational error: {e}")
except mssql_python.Error as e:
    print(f"Database error: {e}")
finally:
    if 'conn' in locals():
        conn.close()

Wyjątki dostępu przez połączenie

Możesz wychwycić wyjątki przez instancję połączenia:

try:
    cursor.execute("INVALID SQL")
except conn.ProgrammingError as e:
    print(f"Caught via connection: {e}")

Struktura komunikatów o błędzie

Obiekty wyjątków mssql-python ujawniają trzy atrybuty pochodzące z podstawowej klasy sterownikaException:

Attribute Source Opis
driver_error Sterownik Python Standaryzowany angielski tekst wybrany przez SQLSTATE zwracał z ODBC (na przykład "Communication link failure", "Invalid authorization specification", ). "Syntax error or access violation" Stabilne w różnych wydaniach; Bezpiecznie dopasowywać podciągi.
ddbc_error Bezpośrednia łączność bazy danych (DDBC) Komunikat po stronie serwera, zazwyczaj poprzedzony przez .[Microsoft][SQL Server] Format nie jest stabilną umową.
message Składający się f"Driver Error: {driver_error}; DDBC Error: {ddbc_error}". To właśnie wraca str(exc) .
try:
    cursor.execute("SELECT * FROM no_such_table;")
except mssql_python.ProgrammingError as exc:
    print(exc.driver_error)  # Base table or view not found
    print(exc.ddbc_error)    # [Microsoft][SQL Server]Invalid object name 'no_such_table'.
    print(exc)               # Driver Error: Base table or view not found; DDBC Error: ...

Numer błędu silnika SQL Server (taki jak 208 lub 40501) nie jest ujawniany jako atrybut i nie jest niezawodnie osadzony w żadnym ze znaków znaków. Klasyfikuj błędy według podklasy wyjątku plus driver_error tekst. Aby uzyskać ograniczenie Azure SQL, zobacz Retry logic.

Klasyfikacja SQLSTATE

mssql-python wykorzystuje SQLSTATE zwracany przez ODBC do wyboru zarówno podklasy wyjątku Python, jak i driver_error tekstu. Pełne mapowanie wyjątków SQLSTATE → znajduje się exceptions.py w źródle sterownika. Następna sekcja wymienia stany SQL, które najczęściej pojawiają się w SQL Server i Azure SQL.

Błędy połączenia

Awarie połączenia z mssql_python.connect() podniesioną mssql_python.OperationalError, tak samo jak inne awarie łączności:

import mssql_python

try:
    conn = mssql_python.connect(
        "Server=unreachable-server.database.windows.net;"
        "Database=<database>;"
        "Authentication=ActiveDirectoryDefault;"
        "Encrypt=yes"
    )
except mssql_python.OperationalError as e:
    print(f"Connection failed: {e.driver_error}")
    # e.driver_error: "Client unable to establish connection"

Błędy ciągu połączenia

Błędy parsowania łańcuchów połączeń powodują ConnectionStringParseError:

try:
    conn = mssql_python.connect("Servr=localhost;")  # Typo
except mssql_python.ConnectionStringParseError as e:
    print(f"Invalid connection string: {e}")
    # Output: Unknown keyword 'Servr'

Referencja kodu SQLSTATE

Kody SQLSTATE to pięcioznakowe kody identyfikujące błędy. Pierwsze dwie postacie wskazują klasę, a ostatnie trzy podklasę. Rzadko trzeba bezpośrednio sprawdzać te kody. Zamiast tego złap odpowiedni typ wyjątku w Python (wymieniony w kolumnie "Exception"). Używaj kodów SQLSTATE, gdy musisz rozróżnić konkretne błędy w obrębie tego samego typu wyjątku, na przykład aby odróżnić martwy punkt (40001) od ogólnej awarii połączenia (08S01).

Klasa 00 - Pomyślne ukończenie

SQLSTATE Exception Opis
00000 Żaden Success

Klasa 01 - Ostrzeżenie

SQLSTATE Exception Opis
01000 Warning Ostrzeżenie ogólne
01001 Warning Konflikt operacji kursora
01002 Warning Błąd rozłączenia
01003 DataError Wartość NULL wyeliminowana w funkcji set
01004 DataError Dane ciągowe, obcinanie z prawej
01006 Warning Nie odwołano uprawnień
01007 Warning Nie udzielono uprawnień
01S00 Warning Nieprawidłowy atrybut parametry połączenia
01S01 Warning Błąd w wierszu
01S02 Warning Zmieniono wartość opcji

Klasa 07 - Dynamiczny błąd SQL

SQLSTATE Exception Opis
07001 ProgrammingError Błędna liczba parametrów
07002 ProgrammingError Nieprawidłowe pole COUNT
07005 ProgrammingError Przygotowane zdanie, a nie specyfikacja kursora
07006 ProgrammingError Naruszenie atrybutu typu danych z ograniczeniami
07009 ProgrammingError Nieprawidłowy indeks deskryptorów
07S01 ProgrammingError Nieprawidłowe użycie parametru domyślnego

Klasa 08 - Wyjątek połączenia

SQLSTATE Exception Opis
08001 OperationalError Klient nie może nawiązać połączenia
08002 OperationalError Używana nazwa połączenia
08003 OperationalError Połączenie nie istnieje
08004 OperationalError Serwer odrzucił połączenie
08007 OperationalError Awaria połączenia podczas transakcji
08S01 OperationalError Błąd połączenia komunikacyjnego

Klasa 21 - Naruszenie kardynalności

SQLSTATE Exception Opis
21S01 ProgrammingError Lista wartości nie pasuje do listy kolumn.
21S02 ProgrammingError Stopień tabeli pochodnej nie jest zgodny z listą kolumn

Klasa 22 - Wyjątek dla danych

SQLSTATE Exception Opis
22001 DataError Dane ciągowe, obcinanie z prawej
22002 DataError Zmienna wskaźnika jest wymagana, ale nie jest podana
22003 DataError Wartość liczbowa poza zakresem
22007 DataError Nieprawidłowy format daty/godziny
22008 DataError Przepełnienie pola daty/godziny
22012 DataError Dzielenie według zera
22015 DataError Przepełnienie pola interwału
22018 DataError Nieprawidłowa wartość znaku dla specyfikacji rzutu
22019 DataError Nieprawidłowy znak ucieczki
22025 DataError Nieprawidłowa sekwencja ucieczki
22026 DataError Dane ciągu, niezgodność długości

Klasa 23 - Naruszenie ograniczeń integralności

SQLSTATE Exception Opis
23000 IntegrityError Naruszenie ograniczeń integralności (ogólne)

Klasa 24 - Nieprawidłowy stan kursora

SQLSTATE Exception Opis
24000 Błąd Wewnętrzny Nieprawidłowy stan kursora

Klasa 25 - Nieprawidłowy stan transakcji

SQLSTATE Exception Opis
25000 OperationalError Nieprawidłowy stan transakcji
25S01 OperationalError Stan transakcji nieznany
25S02 OperationalError Transakcja nadal jest aktywna
25S03 OperationalError Transakcja jest cofana

Klasa 28 - Nieprawidłowa specyfikacja autoryzacji

SQLSTATE Exception Opis
28000 OperationalError Nieprawidłowa specyfikacja autoryzacji (logowanie zawiodło)

Klasa 34 - Nieprawidłowa nazwa kursora

SQLSTATE Exception Opis
34000 ProgrammingError Nieprawidłowa nazwa kursora

Klasa 3C - Podwójna nazwa kursora

SQLSTATE Exception Opis
3C000 ProgrammingError Zduplikowana nazwa kursora

Klasa 3D - Nieprawidłowa nazwa katalogowa

SQLSTATE Exception Opis
3D000 ProgrammingError Nieprawidłowa nazwa wykazu

Klasa 3F - Nieprawidłowa nazwa schematu

SQLSTATE Exception Opis
3F000 ProgrammingError Nieprawidłowa nazwa schematu

Klasa 40 - Wycofanie transakcji

SQLSTATE Exception Opis
40001 OperationalError Awaria serializacji (martwy punkt)
40002 OperationalError Naruszenie ograniczeń integralności spowodowało cofnięcie
40003 OperationalError Ukończenie instrukcji nieznane

Klasa 42 - Błąd składni lub naruszenie reguły dostępu

SQLSTATE Exception Opis
42000 ProgrammingError Błąd składniowy lub naruszenie dostępu
42S01 ProgrammingError Tabela podstawowa lub widok już istnieje
42S02 ProgrammingError Nie można odnaleźć tabeli podstawowej lub widoku
42S11 ProgrammingError Indeks już istnieje
42S12 ProgrammingError Nie znaleziono indeksu
42S21 ProgrammingError Kolumna już istnieje
42S22 ProgrammingError Nie znaleziono kolumny

Klasa 44 - Z OPCJĄ ODZNACZENIA naruszenie

SQLSTATE Exception Opis
44000 IntegrityError Z NARUSZENIEM OPCJI SPRAWDZANIA

Klasa HY – Specyficzny dla CLI stan

SQLSTATE Exception Opis
HY000 DatabaseError Błąd ogólny
HY001 OperationalError Błąd alokacji pamięci
HY003 ProgrammingError Nieprawidłowy typ bufora aplikacji
HY004 ProgrammingError Nieprawidłowy typ danych SQL
HY007 ProgrammingError Powiązane oświadczenie nie jest przygotowane
HY008 OperationalError Operacja anulowana
HY009 ProgrammingError Nieprawidłowe użycie wskaźnika o wartości null
HY010 ProgrammingError Błąd sekwencji funkcji
HY011 ProgrammingError Atrybut nie może być teraz ustawiony
HY012 ProgrammingError Nieprawidłowy kod operacji transakcyjnej
HY013 OperationalError Błąd zarządzania pamięcią
HY014 OperationalError Limit liczby przekroczonych uchwytów
HY015 ProgrammingError Brak nazwy kursora
HY016 ProgrammingError Nie można modyfikować deskryptora wiersza implementacyjnego
HY017 ProgrammingError Nieprawidłowe użycie automatycznie przydzielanego uchwytu deskryptorów
HY018 OperationalError Serwer odrzucił prośbę o anulowanie
HY019 ProgrammingError Dane nie-znakowe i niebinarne przesyłane w kawałkach
HY020 DataError Próba połączenia wartości zerowej
HY021 ProgrammingError Niespójne informacje o deskryptorze
HY024 ProgrammingError Nieprawidłowa wartość atrybutu
HY090 ProgrammingError Nieprawidłowa długość ciągu lub buforu
HY091 ProgrammingError Nieprawidłowy identyfikator pola deskryptorowego
HY092 ProgrammingError Nieprawidłowy identyfikator atrybutu/opcji
HY095 ProgrammingError Typ funkcji poza zakresem
HY096 ProgrammingError Nieprawidłowy typ informacji
HY097 ProgrammingError Typ kolumny poza zasięgiem
HY098 ProgrammingError Typ lunety poza zasięgiem
HY099 ProgrammingError Typ nullable poza zasięgiem
HY100 ProgrammingError Typ opcji unikatowości poza zakresem
HY101 ProgrammingError Typ opcji dokładności poza zakresem
HY103 ProgrammingError Nieprawidłowy kod odzyskiwania
HY104 ProgrammingError Nieprawidłowa precyzja lub wartość skali
HY105 ProgrammingError Nieprawidłowy typ parametru
HY106 ProgrammingError Typ aportowania poza zasięgiem
HY107 ProgrammingError Wartość wiersza poza zakresem
HY109 ProgrammingError Nieprawidłowa pozycja kursora
HY110 ProgrammingError Nieprawidłowe uzupełnienie sterownika
HY111 ProgrammingError Nieprawidłowa wartość zakładek
HYC00 NieSupportedError Opcjonalna funkcja nie zaimplementowana
HYT00 OperationalError Upłynął limit czasu
HYT01 OperationalError Upłynął limit czasu połączenia

Klasa IM - Błąd menedżera sterownika

SQLSTATE Exception Opis
IM001 InterfaceError Sterownik nie obsługuje tej funkcji
IM002 InterfaceError Nazwa źródła danych nie znaleziona
IM003 InterfaceError Określony sterownik nie mógł być załadowany
IM004 InterfaceError Driver's SQLAllocHandle na SQL_HANDLE_ENV nieudał się
IM005 InterfaceError Driver's SQLAllocHandle na SQL_HANDLE_DBC nie powiódł
IM006 InterfaceError SQLSetConnectAttr sterownika zawiódł
IM007 InterfaceError Nie podano źródła danych ani sterownika
IM008 InterfaceError Dialog zawiódł
IM009 InterfaceError Nie można załadować tłumaczenia DLL
IM010 InterfaceError Nazwa źródła danych jest zbyt długa
IM011 InterfaceError Nazwa kierowcy za długa
IM012 InterfaceError Błąd składni słów kluczowych DRIVER
IM014 InterfaceError Nieprawidłowy DSN
IM015 InterfaceError Uszkodzone źródło danych plików

Typowe liczby błędów SQL Server

Poza SQLSTATE, SQL Server udostępnia natywne numery błędów w nawiasach. To są błędy, na które najczęściej natrafisz w kodzie aplikacji. Buduj logikę powtórek wokół błędu 1205 (martwy punkt) i przejściowych błędów połączenia (patrz logika powtórki).

Błąd Wzorzec komunikatu Rozdzielczość
208 Nieprawidłowa nazwa obiektu Sprawdź, czy tabela lub widok istnieje i sprawdź kwalifikację schematu.
547 Naruszenie ograniczeń Klucz obcy lub ograniczenie sprawdzające zawiodło.
2627 Naruszenie unikalnego ograniczenia Wstawiono duplikat wartości klucza.
2601 Unikalne naruszenie indeksu W indeksie istnieje duplikat klucza.
4060 Nie można otworzyć bazy danych Baza danych nie istnieje lub dostęp jest odmawiany.
18456 Logowanie nie powiodło się Niepowodzenie uwierzytelniania. Sprawdź uprawnienia.
1205 Ofiara zakleszczenia Transakcja została wycofana. Spróbuj ponownie wykonać operację.

Szybkie odniesienie od objawów do wyjątków

Użyj tej tabeli, aby przypisać typowe objawy do typu wyjątku, który powinieneś wychwycić:

Objaw Exception Prawdopodobna przyczyna
"Zalogowanie użytkownika się nie powiodło" OperationalError Błędne dane logowania lub użytkownik nie został przypisany do bazy danych.
"Klient nie może nawiązać połączenia" OperationalError Serwer niedostępny, problem z zaporą sieciową lub DNS.
"Timeout minął" OperationalError Zapytanie lub limit połączenia. Wydłuż czas na wydłużenie lub zoptymalizuj zapytanie.
"Nieprawidłowa nazwa obiektu" ProgrammingError Tabela nie istnieje ani schemat nie jest określony.
"Nieprawidłowa składnia" ProgrammingError Błąd składni SQL. Zapytanie testowe w SSMS.
"Błędna liczba parametrów" ProgrammingError Liczba parametrów nie zgadza się z tymczasowymi parametrami.
"Naruszenie KLUCZA GŁÓWNEGO" IntegrityError Zduplikuj klucz. Użyj MERGE lub sprawdź przed włożeniem.
"Naruszenie KLUCZA OBCEGO" IntegrityError Odwołany wiersz nie istnieje. Najpierw wstaw rodzica.
"Transakcja utknęła w martwym punkcie" OperationalError (błąd 1205) Walka o blokadę. Zaimplementuj logikę ponawiania prób.
"Dane ciągowe lub binarne byłyby obcięte" DataError Wartość przekracza długość kolumny. Sprawdź dane lub powiększ rubrykę.
"Konwersja zakończona niepowodzeniem" DataError Niezgodność typu Użyj właściwego typu Python dla kolumny.
"Nieznane słowo kluczowe" ConnectionStringParseError Literówka w słowie kluczowym parametry połączenia.
"Callproc nie jest obsługiwany" NotSupportedError Użyj cursor.execute("EXECUTE ...") zamiast tego.

Najlepsze rozwiązania

  • Złap konkretne wyjątki przed ogólnymi. Uporządkuj od najbardziej szczegółowego (IntegrityError) do najmniej szczegółowego (Error).
  • Zawsze obsługuj IntegrityError do operacji modyfikacji danych. Naruszenia ograniczeń są spodziewane w normalnej pracy (na przykład użytkownik próbujący utworzyć duplikatową nazwę użytkownika).
  • Zapisz pełny kontekst błędu do rozwiązywania problemów. Wyjątek eksponuje driver_error (stabilny, pochodzący z SQLSTATE tekst) oraz ddbc_error (wiadomość po stronie serwera). Rejestruj oba; klasyfikuj na .driver_error
  • Implementuj logikę powtórek dla błędów przejściowych (awarie połączenia, martwe punkty). Zobacz logikę ponownego próbowania.
  • Użyj rollback() w obsługach wyjątków, aby usunąć nieudane transakcje. Bez wyraźnego cofnięcia połączenie pozostaje w stanie nieudanej transakcji.