Zpracování chyb a SQLSTATE kódy pro mssql-python

Ovladač mssql-python definuje standardní hierarchii výjimek, běžné vzory zpracování chyb a mapování kódu SQLSTATE pro SQL Server a Azure SQL.

Hierarchie výjimek

Ovladač mssql-python se řídí hierarchií výjimek DB-API 2.0 (PEP 249):

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

ConnectionStringParseError (standalone, not part of hierarchy)

Popisy výjimek

Chyťte tu nejkonkrétnější výjimku, která odpovídá vaší situaci. Například catch IntegrityError pro porušení omezení na INSERT/UPDATE operations a ProgrammingError pro problémy se syntaxí SQL během vývoje. Základní třídu Error chytejte jen jako záložní řešení.

Exception Pokud je zvýšen
Warning Varování z databáze nejsou smrtelná.
Error Základní třída pro všechny chyby v databázi.
InterfaceError Chyby se týkaly rozhraní databáze (ovladače), nikoli samotné databáze.
DatabaseError Chyby související s databází.
DataError Chyby způsobené problémy s zpracovanými daty (dělení nulou, hodnota mimo rozsah).
OperationalError Chyby související s provozem databáze (ztráta spojení, alokace paměti, chyby transakcí).
IntegrityError Chyby při ovlivnění integrity databáze (porušení cizího klíče, jedinečné omezení).
InternalError Interní chyby v databázi (kurzor není platný, transakce není synchronizovaná).
ProgrammingError Programátorské chyby (syntaxické chyby, tabulka nenalezena, nesprávný počet parametrů).
NotSupportedError Funkce, kterou databáze ani ovladač nepodporují.
ConnectionStringParseError Neplatná syntaxe připojovací řetězec nebo neznámá klíčová slova.

Základní zpracování chyb

Používejte bloky try-except pro řešení chyb v databázi:

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()

Výjimky pro přístup přes spojení

Výjimky můžete zachytit přes instanci spojení:

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

Struktura chybových zpráv

Objekty výjimek mssql-python zpřístupňují tři atributy, které pocházejí ze základní třídyException ovladače:

Attribute Source Popis
driver_error Python ovladač Standardizovaný anglický text vybraný SQLSTATE se vrátil z ODBC (například "Communication link failure", "Invalid authorization specification", "Syntax error or access violation"). Stabilní napříč vydáním; Bezpečné pro podřetězcové párování.
ddbc_error Přímé připojení k databázi (DDBC) Zpráva na straně serveru, obvykle s předponou [Microsoft][SQL Server]. Formát není stabilní smlouva.
message Složeno f"Driver Error: {driver_error}; DDBC Error: {ddbc_error}". Tohle str(exc) se vrací.
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: ...

Chybové číslo SQL Server engine (například 208 nebo 40501) není jako atribut vystaveno a není spolehlivě vloženo ani do žádného z řetězců. Klasifikujte chyby podle výjimky, podtřídy plus driver_error text. Pro Azure SQL throttling viz Retry logic.

SQLSTATE klasifikace

mssql-python používá SQLSTATE vrácený ODBC k volbě jak podtřídy Python exception, tak textudriver_error. Kompletní mapování SQLSTATE → výjimek je ve exceptions.py zdrojovém kódu ovladače. Další sekce uvádí SQLSTATE, které se nejčastěji objevují u SQL Server a Azure SQL.

Chyby připojení

Selhání spojení z mssql_python.connect() raise mssql_python.OperationalError, stejně jako u jiných selhání konektivity:

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"

Chyby spojovacích řetězců

Chyby při parsování spojovacích řetězců zvyšují 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'

SQLSTATE kódová reference

SQLSTATE kódy jsou pětiznakové kódy, které identifikují chybové stavy. První dva znaky označují třídu a poslední tři podtřídu. Tyto kódy je jen zřídka nutné přímo kontrolovat. Místo toho zachyťte příslušný typ výjimky v Python (uvedený ve sloupci "Exception"). Používejte kódy SQLSTATE, když potřebujete rozlišit mezi konkrétními chybovými podmínkami ve stejném typu výjimky, například k rozlišení zablokování (40001) od obecného selhání spojení (08S01).

Třída 00 - Úspěšné dokončení

SQLSTATE Exception Popis
00000 Žádný Success

Třída 01 - Varování

SQLSTATE Exception Popis
01000 Warning Obecné upozornění
01001 Warning Konflikt operace kurzoru
01002 Warning Chyba odpojení
01003 Chyba data Hodnota NULL byla eliminována ve funkci set
01004 Chyba data Řetězcová data, zkrácení zprava
01006 Warning Oprávnění se neodvolal
01007 Warning Oprávnění se neuděluje
01S00 Warning Neplatný atribut připojovací řetězec
01S01 Warning Chyba v řádku
01S02 Warning Změna hodnoty možnosti

Třída 07 - Dynamická chyba SQL

SQLSTATE Exception Popis
07001 ProgrammingError Špatný počet parametrů
07002 ProgrammingError Nesprávné pole COUNT
07005 ProgrammingError Připravené tvrzení, nikoli specifikace kurzoru
07006 ProgrammingError Porušení atributu omezeného datového typu
07009 ProgrammingError Index neplatných deskriptorů
07S01 ProgrammingError Neplatné použití výchozího parametru

Třída 08 - Výjimka pro spojení

SQLSTATE Exception Popis
08001 OperationalError Klient nedokáže navázat spojení
08002 OperationalError Používaný název spojení
08003 OperationalError Spojení neexistuje
08004 OperationalError Server spojení odmítl
08007 OperationalError Selhání spojení během transakce
08S01 OperationalError Selhání komunikačního propojení

Třída 21 - Porušení kardinálnosti

SQLSTATE Exception Popis
21S01 ProgrammingError Seznam vložených hodnot neodpovídá seznamu sloupců
21S02 ProgrammingError Stupeň odvozené tabulky neodpovídá seznamu sloupců

Třída 22 - Výjimka pro data

SQLSTATE Exception Popis
22001 Chyba data Řetězcová data, zkrácení zprava
22002 Chyba data Požadovaná proměnná ukazatele, ale není zadána
22003 Chyba data Číselná hodnota mimo rozsah
22007 Chyba data Neplatný formát data a času
22008 Chyba data Přetečení pole Datetime
22012 Chyba data Dělení nulou
22015 Chyba data Přetečení pole intervalu
22018 Chyba data Neplatná hodnota znaku pro specifikaci přetypování
22019 Chyba data Neplatný řídicí znak
22025 Chyba data Neplatná řídicí sekvence
22026 Chyba data Řetězcová data, neshoda délky

Třída 23 - Porušení integrity

SQLSTATE Exception Popis
23000 IntegrityError Porušení integrity (obecné)

Třída 24 - Neplatný stav kurzoru

SQLSTATE Exception Popis
24000 Vnitřní chyba Neplatný stav kurzoru

Třída 25 - Neplatný stav transakce

SQLSTATE Exception Popis
25000 OperationalError Neplatný stav transakce
25S01 OperationalError Stav transakce neznámý
25S02 OperationalError Transakce je stále aktivní
25S03 OperationalError Transakce je vrácena zpět

Třída 28 - Specifikace neplatné autorizace

SQLSTATE Exception Popis
28000 OperationalError Neplatná specifikace autorizace (přihlášení selhalo)

Třída 34 - Neplatné jméno kurzoru

SQLSTATE Exception Popis
34000 ProgrammingError Neplatný název kurzoru

Třída 3C - Duplikát názvu kurzoru

SQLSTATE Exception Popis
3C000 ProgrammingError Duplicitní název kurzoru

Třída 3D - Neplatné katalogové jméno

SQLSTATE Exception Popis
3D000 ProgrammingError Neplatný název katalogu

Třída 3F - Neplatné schématové jméno

SQLSTATE Exception Popis
3F000 ProgrammingError Neplatný název schématu

Třída 40 - Návrat transakcí zpět

SQLSTATE Exception Popis
40001 OperationalError Selhání serializace (zablokování)
40002 OperationalError Porušení integrity způsobilo návrat zpět
40003 OperationalError Neznámé dokončování příkazů

Třída 42 - Chyba syntaxe nebo porušení přístupových pravidel

SQLSTATE Exception Popis
42000 ProgrammingError Chyba syntaxe nebo porušení přístupu
42S01 ProgrammingError Základní tabulka nebo zobrazení již existují.
42S02 ProgrammingError Základní tabulka nebo zobrazení nebyly nalezeny.
42S11 ProgrammingError Index již existuje.
42S12 ProgrammingError Index nebyl nalezen.
42S21 ProgrammingError Sloupec již existuje.
42S22 ProgrammingError Sloupec nebyl nalezen.

Třída 44 - S MOŽNOSTÍ ZAŠKRTNOUT porušení

SQLSTATE Exception Popis
44000 IntegrityError PORUŠENÍ FUNKCE CHECK OPTION

Třída HY – CLI-specifická podmínka

SQLSTATE Exception Popis
HY000 Chyba databáze Obecná chyba
HY001 OperationalError Chyba přidělení paměti
HY003 ProgrammingError Neplatný typ aplikačního bufferu
HY004 ProgrammingError Neplatný typ SQL dat
HY007 ProgrammingError Související prohlášení není připraveno
HY008 OperationalError Operace byla zrušena.
HY009 ProgrammingError Neplatné použití ukazatele null
HY010 ProgrammingError Chyba posloupnosti funkcí
HY011 ProgrammingError Atribut nelze nyní nastavit
HY012 ProgrammingError Neplatný kód operace transakce
HY013 OperationalError Chyba správy paměti
HY014 OperationalError Limit překročeného počtu rukojeti
HY015 ProgrammingError Není k dispozici název kurzoru
HY016 ProgrammingError Nelze upravovat deskriptor řádku implementace
HY017 ProgrammingError Neplatné použití automaticky alokovaného descriptorového handle
HY018 OperationalError Server odmítl žádost o zrušení
HY019 ProgrammingError Neznaková a nebinární data odesílaná v částech
HY020 Chyba data Pokus o spojení nulové hodnoty
HY021 ProgrammingError Nekonzistentní informace o popisech
HY024 ProgrammingError Neplatná hodnota atributu
HY090 ProgrammingError Neplatná délka řetězce nebo vyrovnávací paměti
HY091 ProgrammingError Neplatný identifikátor pole deskriptoru
HY092 ProgrammingError Neplatný identifikátor atributu/opce
HY095 ProgrammingError Typ funkce mimo rozsah
HY096 ProgrammingError Typ neplatné informace
HY097 ProgrammingError Typ sloupce mimo dosah
HY098 ProgrammingError Typ zaměřovače mimo dosah
HY099 ProgrammingError Nullable typ mimo dosah
HY100 ProgrammingError Typ možnosti jedinečnosti mimo rozsah
HY101 ProgrammingError Typ možnosti přesnosti mimo rozsah
HY103 ProgrammingError Neplatný kód pro získání
HY104 ProgrammingError Neplatná přesnost nebo hodnota škály
HY105 ProgrammingError Neplatný typ parametru
HY106 ProgrammingError Typ aportu mimo dosah
HY107 ProgrammingError Hodnota řádku mimo rozsah
HY109 ProgrammingError Neplatná pozice kurzoru
HY110 ProgrammingError Dokončení neplatného ovladače
HY111 ProgrammingError Neplatná hodnota záložek
HYC00 NotSupportedError Nepovinná funkce není implementována.
HYT00 OperationalError Vypršel časový limit.
HYT01 OperationalError Vypršel časový limit připojení

Třída IM - Chyba správce ovladačů

SQLSTATE Exception Popis
IM001 InterfaceError Ovladač tuto funkci nepodporuje.
IM002 InterfaceError Název zdroje dat nenalezen
IM003 InterfaceError Specifikovaný ovladač nemohl být načítán
IM004 InterfaceError Driver's SQLAllocHandle na SQL_HANDLE_ENV selhal
IM005 InterfaceError Driver's SQLAllocHandle on SQL_HANDLE_DBC failed
IM006 InterfaceError Driver SQLSetConnectAttr selhal
IM007 InterfaceError Není specifikován žádný zdroj dat ani ovladač
IM008 InterfaceError Dialog selhal
IM009 InterfaceError Nelze načíst překlad DLL
IM010 InterfaceError Název zdroje dat je příliš dlouhý
IM011 InterfaceError Jméno řidiče je příliš dlouhé
IM012 InterfaceError Chyba syntaxe klíčových slov v DRIVER
IM014 InterfaceError Neplatné DSN
IM015 InterfaceError Poškozený zdroj datových dat souboru

Běžná čísla chyb v SQL Server

Kromě SQLSTATE poskytuje SQL Server nativní čísla chyb v závorkách. To jsou chyby, na které se nejčastěji setkáte v aplikačním kódu. Postavte logiku opakovaných pokusů kolem chyby 1205 (zablokování) a přechodných chyb připojení (viz logika opakování).

Error Vzor zprávy Rozlišení
208 Neplatný název objektu Ověřte, že tabulka nebo pohled existuje, a zkontrolujte kvalifikaci schématu.
547 Porušení omezení Cizí klíč nebo kontrolní omezení selhalo.
2627 Porušení jedinečného omezení Byla vložena duplicitní hodnota klíče.
2601 Porušení jedinečného indexu V indexu existuje duplicitní klíč.
4060 Nelze otevřít databázi Databáze neexistuje nebo je přístup odepřen.
18456 Přihlášení se nezdařilo. Selhání autentizace. Zkontrolujte si přihlašovací údaje.
1205 Oběť zablokování Transakce byla vrácena zpět. Zkuste operaci zopakovat.

Rychlá referencie od symptomů k výjimkám

Použijte tuto tabulku k přiřazení běžných příznaků na typ výjimky, který byste měli zachytit:

Příznak Exception Pravděpodobná příčina
"Přihlášení pro uživatele selhalo" OperationalError Špatné přihlašovací údaje nebo uživatel není přiřazen k databázi.
"Klient nedokáže navázat spojení" OperationalError Server nedostupný, problém s firewallem nebo DNS.
"Vypršel časový limit" OperationalError Dotaz nebo vypršení připojení k připojení. Zvyšte časový limit nebo optimalizujte dotazy.
"Neplatné jméno objektu" ProgrammingError Tabulka neexistuje ani schéma není specifikováno.
"Nesprávná syntaxe" ProgrammingError Chyba v syntaxi SQL. Testovací dotaz v SSMS.
"Špatný počet parametrů" ProgrammingError Počet parametrů neodpovídá zástupcům.
"Porušení PRIMÁRNÍHO KLÍČE" IntegrityError Duplikát klíče. Použijte MERGE nebo zkontrolujte před vložením.
"Porušení CIZÍHO KLÍČE" IntegrityError Odkazovaný řádek neexistuje. Nejprve vložte rodiče.
"Transakce byla zablokována" OperationalError (chyba 1205) Boj o zámky. Implementujte logiku opakování.
"Řetězcová nebo binární data by byla zkrácena" DataError Hodnota přesahuje délku sloupce. Zkontrolujte data nebo zvětšete velikost sloupce.
"Konverze selhala" DataError Neshoda typů Použijte správný typ v Python pro sloupec.
"Neznámé klíčové slovo" ConnectionStringParseError Překlep v klíčovém slově připojovací řetězec.
"Callproc není podporován" NotSupportedError Místo toho použijte cursor.execute("EXECUTE ...").

Osvědčené postupy

  • Chyťte konkrétní výjimky před obecnými. Pořadí od nejkonkrétnějšího (IntegrityError) po nejméně specifické (Error).
  • Vždy zvládejte IntegrityError pro operace úpravy dat. Porušení omezení se očekává při běžném provozu (například uživatel se snaží vytvořit duplicitní uživatelské jméno).
  • Zaznamenejte celý kontext chyby pro řešení problémů. Výjimka exponuje driver_error (stabilní, ze SQLSTATE odvozený text) a ddbc_error (zprávu na straně serveru). Zaznamenejte obojí; klasifikujte na driver_error.
  • Implementujte logiku opakování pro přechodné chyby (selhání spojení, zablokování). Viz logika opakování.
  • Použijte rollback() v obslužných obslužcích výjimek k vyčištění neúspěšných transakcí. Bez explicitního rollbacku zůstává spojení ve stavu neúspěšné transakce.