mssql-python 驅動程式定義了標準的例外階層結構、常見的錯誤處理模式,以及 SQL Server 和 Azure SQL 的 SQLSTATE 程式碼映射。
例外狀況階層
mssql-python 驅動程式遵循 DB-API 2.0(PEP 249)例外階層:
Exception (builtins)
├── Warning
└── Error
├── InterfaceError
└── DatabaseError
├── DataError
├── OperationalError
├── IntegrityError
├── InternalError
├── ProgrammingError
└── NotSupportedError
ConnectionStringParseError (standalone, not part of hierarchy)
例外描述
找出最符合你情況的例外情況。 例如,捕捉 IntegrityError / 操作上的INSERT限制違規,以及ProgrammingError開發過程中的 SQLUPDATE 語法問題。 基礎職業只能 Error 當作備案。
| 例外狀況 |
當引發時 |
Warning |
資料庫中的非致命警告。 |
Error |
所有資料庫錯誤的基底類別。 |
InterfaceError |
錯誤與資料庫介面(驅動程式)有關,而非資料庫本身。 |
DatabaseError |
與資料庫相關的錯誤。 |
DataError |
因處理資料問題(除以零、值超出範圍)所產生的錯誤。 |
OperationalError |
與資料庫操作相關的錯誤(連線中斷、記憶體配置、交易錯誤)。 |
IntegrityError |
當資料庫完整性受到影響時會出現錯誤(如外鍵違規、唯一限制)。 |
InternalError |
內部資料庫錯誤(游標無效、交易不同步)。 |
ProgrammingError |
程式錯誤(語法錯誤、找不到表格、參數數量錯誤)。 |
NotSupportedError |
資料庫或驅動程式不支援此功能。 |
ConnectionStringParseError |
連接字串 語法無效或關鍵字不明。 |
基本錯誤處理
使用嘗試除外區塊來處理資料庫錯誤:
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()
透過連線的存取例外
你可以透過連線實例捕捉例外:
try:
cursor.execute("INVALID SQL")
except conn.ProgrammingError as e:
print(f"Caught via connection: {e}")
錯誤訊息結構
MSSQL-Python 例外物件會暴露三個來自驅動程式 Exception 基底類別的屬性:
| Attribute |
Source |
描述 |
driver_error |
Python 驅動程式 |
由 SQLSTATE 選擇的標準化英文文本會從 ODBC 回傳(例如 "Communication link failure", , "Invalid authorization specification""Syntax error or access violation")。 跨版本穩定;可以安全地進行子串匹配。 |
ddbc_error |
直接資料庫連接(DDBC) |
伺服器端訊息通常以 [Microsoft][SQL Server]. 作為前綴。 格式不是穩定的合約。 |
message |
組成 |
f"Driver Error: {driver_error}; DDBC Error: {ddbc_error}"。 這就是回歸的部分 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: ...
SQL Server 引擎的錯誤編號(例如 208 或 40501)不會被公開為屬性,也不會可靠地嵌入在任何字串中。 依例外子類別加上 driver_error 文字分類錯誤。 關於 Azure SQL throttling,請參閱 Retry logic.
SQLSTATE 分類
mssql-python 使用 ODBC 回傳的 SQLSTATE 來選擇 Python 例外子類別及文字。driver_error 完整的 SQLSTATE →例外映射已在 exceptions.py 驅動程式原始碼中。 下一節列出在 SQL Server 和 Azure SQL 中最常出現的 SQLSTATE。
連線錯誤
來自 mssql_python.connect() 的 mssql_python.OperationalError連線失敗與其他連線失敗相同:
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"
連線字串錯誤
連線字串解析錯誤會產生 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 程式碼參考
SQLSTATE 代碼是五個字元的代碼,用來識別錯誤狀況。 前兩個字元表示職業,後面三個字元表示子職業。 你很少需要直接檢查這些代碼。 相反地,請鎖定適當的 Python 例外類型(列於「例外」欄位)。 當你需要區分同一例外類型內的特定錯誤條件時,請使用 SQLSTATE 代碼,例如區分死結(40001)與一般連線失敗(08S01)。
00級 - 成功完成
| SQLSTATE |
例外狀況 |
描述 |
| 00000 |
None |
成功 |
01級 - 警告
| SQLSTATE |
例外狀況 |
描述 |
| 01000 |
Warning |
一般警告 |
| 01001 |
Warning |
數據指標作業衝突 |
| 01002 |
Warning |
斷線錯誤 |
| 01003 |
資料錯誤 |
set 函式中排除的 NULL 值 |
| 01004 |
資料錯誤 |
字串資料,右截斷 |
| 01006 |
Warning |
許可權未撤銷 |
| 01007 |
Warning |
未授與許可權 |
| 01S00 |
Warning |
無效 連接字串 屬性 |
| 01S01 |
Warning |
排錯 |
| 01S02 |
Warning |
選項值已變更 |
07類 - 動態SQL錯誤
| SQLSTATE |
例外狀況 |
描述 |
| 07001 |
程式設計錯誤 |
參數數量錯誤 |
| 07002 |
程式設計錯誤 |
COUNT 欄位不正確 |
| 07005 |
程式設計錯誤 |
預備陳述,而非游標規格 |
| 07006 |
程式設計錯誤 |
受限制的數據類型屬性違規 |
| 07009 |
程式設計錯誤 |
無效描述子索引 |
| 07S01 |
程式設計錯誤 |
預設參數的使用無效 |
08級 - 連接例外
| SQLSTATE |
例外狀況 |
描述 |
| 08001 |
操作錯誤 |
用戶端無法建立連線 |
| 08002 |
操作錯誤 |
使用中的連線名稱 |
| 08003 |
操作錯誤 |
連結不存在 |
| 08004 |
操作錯誤 |
伺服器拒絕連線 |
| 08007 |
操作錯誤 |
交易期間連線失敗 |
| 08S01 |
操作錯誤 |
通訊連結故障 |
第21類 - 基數違規
| SQLSTATE |
例外狀況 |
描述 |
| 21S01 |
程式設計錯誤 |
插入值清單不符合欄位清單 |
| 21S02 |
程式設計錯誤 |
衍生數據表的程度不符合數據列清單 |
類別 22 - 資料例外
| SQLSTATE |
例外狀況 |
描述 |
| 22001 |
資料錯誤 |
字串資料,右截斷 |
| 22002 |
資料錯誤 |
需要指標變數,但未提供 |
| 22003 |
資料錯誤 |
超出範圍的數值 |
| 22007 |
資料錯誤 |
無效的日期時間格式 |
| 22008 |
資料錯誤 |
日期時間欄位溢位 |
| 22012 |
資料錯誤 |
除以零 |
| 22015 |
資料錯誤 |
間隔欄位溢位 |
| 22018 |
資料錯誤 |
轉換規格的字元值無效 |
| 22019 |
資料錯誤 |
無效的逸出字元 |
| 22025 |
資料錯誤 |
無效的逸出序列 |
| 22026 |
資料錯誤 |
字串數據,長度不符 |
第23類 - 完整性約束違規
| SQLSTATE |
例外狀況 |
描述 |
| 23000 |
完整性錯誤 |
完整性約束違反(一般) |
類別 24 - 游標狀態無效
| SQLSTATE |
例外狀況 |
描述 |
| 24000 |
內部錯誤 |
無效的數據指標狀態 |
第25類 - 交易狀態無效
| SQLSTATE |
例外狀況 |
描述 |
| 25000 |
操作錯誤 |
交易狀態無效 |
| 25S01 |
操作錯誤 |
交易狀態不明 |
| 25S02 |
操作錯誤 |
交易仍然有效 |
| 25S03 |
操作錯誤 |
交易會被回滾 |
第28類 - 無效授權規範
| SQLSTATE |
例外狀況 |
描述 |
| 28000 |
操作錯誤 |
授權規格無效(登入失敗) |
類別 34 - 游標名稱無效
| SQLSTATE |
例外狀況 |
描述 |
| 34000 |
程式設計錯誤 |
無效的數據指標名稱 |
3C 類 - 重複游標名稱
| SQLSTATE |
例外狀況 |
描述 |
| 3C000 |
程式設計錯誤 |
重複的數據指標名稱 |
3D 類 - 目錄名稱無效
| SQLSTATE |
例外狀況 |
描述 |
| 3D000 |
程式設計錯誤 |
無效的目錄名稱 |
類別 3F - 無效的結構名稱
| SQLSTATE |
例外狀況 |
描述 |
| 3F000 |
程式設計錯誤 |
無效的架構名稱 |
40 類 - 交易回滾
| SQLSTATE |
例外狀況 |
描述 |
| 40001 |
操作錯誤 |
序列化失敗(死結) |
| 40002 |
操作錯誤 |
完整性約束違規導致回滾 |
| 40003 |
操作錯誤 |
語句完成未知 |
第 42 類 - 語法錯誤或存取規則違規
| SQLSTATE |
例外狀況 |
描述 |
| 42000 |
程式設計錯誤 |
語法錯誤或存取違規 |
| 42S01 |
程式設計錯誤 |
基表或檢視已經存在 |
| 42S02 |
程式設計錯誤 |
找不到基底表格或視圖 |
| 42S11 |
程式設計錯誤 |
索引已經存在 |
| 42S12 |
程式設計錯誤 |
找不到索引 |
| 42S21 |
程式設計錯誤 |
數據行已經存在 |
| 42S22 |
程式設計錯誤 |
找不到欄位 |
44級 - 違反檢查選項
| SQLSTATE |
例外狀況 |
描述 |
| 44000 |
完整性錯誤 |
WITH CHECK OPTION 違規 |
HY 類 - CLI 專屬疾病
| SQLSTATE |
例外狀況 |
描述 |
| HY000 |
資料庫錯誤 |
一般誤差 |
| HY001 |
操作錯誤 |
記憶體配置錯誤 |
| HY003 |
程式設計錯誤 |
無效的應用程式緩衝區類型 |
| HY004 |
程式設計錯誤 |
無效的 SQL 資料類型 |
| HY007 |
程式設計錯誤 |
未備妥相關聯的語句 |
| HY008 |
操作錯誤 |
行動取消 |
| HY009 |
程式設計錯誤 |
無效的 Null 指標使用 |
| HY010 |
程式設計錯誤 |
函式順序錯誤 |
| HY011 |
程式設計錯誤 |
無法立即設定屬性 |
| HY012 |
程式設計錯誤 |
無效的交易操作代碼 |
| HY013 |
操作錯誤 |
記憶體管理錯誤 |
| HY014 |
操作錯誤 |
把柄數超過上限 |
| HY015 |
程式設計錯誤 |
沒有可用的數據指標名稱 |
| HY016 |
程式設計錯誤 |
無法修改實作列描述符 |
| HY017 |
程式設計錯誤 |
自動分配描述符句柄的無效使用 |
| HY018 |
操作錯誤 |
伺服器拒絕取消請求 |
| HY019 |
程式設計錯誤 |
非字元與非二元資料分段傳送 |
| HY020 |
資料錯誤 |
嘗試串接空值 |
| HY021 |
程式設計錯誤 |
描述符資訊不一致 |
| HY024 |
程式設計錯誤 |
無效的屬性值 |
| HY090 |
程式設計錯誤 |
無效的字串或緩衝區長度 |
| HY091 |
程式設計錯誤 |
無效描述符欄位識別碼 |
| HY092 |
程式設計錯誤 |
無效屬性/選項識別碼 |
| HY095 |
程式設計錯誤 |
功能類型超出範圍 |
| HY096 |
程式設計錯誤 |
無效資訊類型 |
| HY097 |
程式設計錯誤 |
欄位類型超出範圍 |
| HY098 |
程式設計錯誤 |
望遠鏡類型超出範圍 |
| HY099 |
程式設計錯誤 |
可歸零型別超出範圍 |
| HY100 |
程式設計錯誤 |
唯一性選項類型超出範圍 |
| HY101 |
程式設計錯誤 |
準確度選項類型超出範圍 |
| HY103 |
程式設計錯誤 |
無效的取回碼 |
| HY104 |
程式設計錯誤 |
無效的有效位數或小數位數值 |
| HY105 |
程式設計錯誤 |
無效的參數類型 |
| HY106 |
程式設計錯誤 |
取物類型超出範圍 |
| HY107 |
程式設計錯誤 |
列值超出範圍 |
| HY109 |
程式設計錯誤 |
無效的數據指標位置 |
| HY110 |
程式設計錯誤 |
無效驅動程式補全 |
| HY111 |
程式設計錯誤 |
書籤值無效 |
| HYC00 |
非支援錯誤 |
未實作選擇性功能 |
| HYT00 |
操作錯誤 |
逾時已超過 |
| HYT01 |
操作錯誤 |
連線已逾時 |
Class IM - 駕駛管理員錯誤
| SQLSTATE |
例外狀況 |
描述 |
| IM001 |
介面錯誤 |
驅動程式不支援此函式 |
| IM002 |
介面錯誤 |
資料來源名稱未找到 |
| IM003 |
介面錯誤 |
無法載入指定的驅動程式 |
| IM004 |
介面錯誤 |
驅動程式的 SQLAllocHandle 在 SQL_HANDLE_ENV 失敗 |
| IM005 |
介面錯誤 |
驅動程式的 SQLAllocHandle 在 SQL_HANDLE_DBC 失敗 |
| IM006 |
介面錯誤 |
Driver's SQLSetConnectAttr failed |
| IM007 |
介面錯誤 |
未指定資料來源或驅動程式 |
| IM008 |
介面錯誤 |
對話失敗 |
| IM009 |
介面錯誤 |
無法載入翻譯 DLL |
| IM010 |
介面錯誤 |
數據源名稱太長 |
| IM011 |
介面錯誤 |
驅動程式名稱太長 |
| IM012 |
介面錯誤 |
DRIVER 關鍵詞語法錯誤 |
| IM014 |
介面錯誤 |
DSN 無效 |
| IM015 |
介面錯誤 |
檔案資料來源損壞 |
常見的 SQL Server 錯誤編號
除了 SQLSTATE,SQL Server 還提供括號內的原生錯誤編號。 這些是你在應用程式代碼中最容易遇到的錯誤。 圍繞錯誤 1205(死鎖)和暫時連線錯誤(參見 重試邏輯)來建立重試邏輯。
| 錯誤 |
訊息模式 |
Resolution |
| 208 |
無效的物件名稱。 |
確認該資料表或檢視是否存在,並檢查結構資格。 |
| 547 |
約束違反 |
外鍵或檢查約束失敗。 |
| 2627 |
唯一限制違反 |
重複的鍵值入。 |
| 2601 |
唯一索引違反 |
索引中存在重複的金鑰。 |
| 4060 |
無法開啟資料庫 |
資料庫不存在或被拒絕存取。 |
| 18456 |
登入失敗 |
認證失敗。 檢查資格。 |
| 1205 |
僵局受害者 |
交易已回復。 重試操作。 |
症狀到例外快速參考
請使用此表將常見症狀對應到您應該捕捉的例外類型:
| 症狀 |
例外狀況 |
可能的原因 |
| 「使用者登入失敗」 |
OperationalError |
錯誤的憑證或使用者未映射到資料庫。 |
| 「客戶無法建立連線」 |
OperationalError |
伺服器無法連線、防火牆或 DNS 問題。 |
| 「暫停結束」 |
OperationalError |
查詢或連線逾時。 增加逾時或優化查詢。 |
| 「物件名稱無效」 |
ProgrammingError |
沒有表格或架構未指定。 |
| 「語法錯誤」 |
ProgrammingError |
SQL 語法錯誤。 在 SSMS 中測試查詢。 |
| 「參數數量錯誤」 |
ProgrammingError |
參數數量和佔位符不符。 |
| 「違反主金鑰」 |
IntegrityError |
複製鑰匙。 使用 MERGE 或檢查後再插入。 |
| 「外來鍵違規」 |
IntegrityError |
參考的列不存在。 先插入父本。 |
| 「交易陷入僵局」 |
OperationalError (錯誤 1205) |
鎖定爭奪。 實作重試邏輯: |
| 「字串或二進位資料會被截斷」 |
DataError |
值超過欄位長度。 檢查資料或增加欄位大小。 |
| 「皈依失敗」 |
DataError |
類型不匹配。 請使用正確的 Python 欄位類型。 |
| 「未知關鍵字」 |
ConnectionStringParseError |
連接字串 關鍵字中的打字錯誤。 |
| 「Callproc 不支援」 |
NotSupportedError |
請改用 cursor.execute("EXECUTE ...")。 |
最佳做法
-
先發現具體的例外 ,再處理一般的例外。 依序從最具體的(
IntegrityError)到最不具體的(Error)。
-
資料修改操作時,務必處理 IntegrityError 。 限制違規在正常操作中是預期的(例如,使用者試圖建立重複使用者名稱)。
-
記錄完整的錯誤上下文 以便排查。 例外會暴露
driver_error (穩定、SQLSTATE 衍生文字)和 ddbc_error (伺服器端訊息)。 兩邊都記錄下來;分類於 driver_error。
- 針對暫態錯誤(連線失敗、死鎖)實作重試邏輯。 請參見 重試邏輯。
- 在例外處理程序中使用 rollback() 來清理失敗的交易。 若無明確回滾,連線仍處於交易失敗狀態。
相關內容