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)
例外の説明
自分の状況に最も合った例外を見つけてください。 例えば、INSERT/UPDATE操作の制約違反をIntegrityErrorキャッチしたり、開発中のSQL構文問題をProgrammingError検知したりします。 基本 Error クラスはあくまで代替手段として利用してください。
| 例外 |
持ち上げたとき |
Warning |
データベースからの非致死警告。 |
Error |
すべてのデータベースエラーのベースクラス。 |
InterfaceError |
データベースインターフェース(ドライバー)に関するエラーであって、データベース自体ではありません。 |
DatabaseError |
データベースに関するエラー。 |
DataError |
処理データの問題(ゼロでの割り算、値の範囲外)によるエラー。 |
OperationalError |
データベース操作に関連するエラー(接続喪失、メモリ割り当て、トランザクションエラー)。 |
IntegrityError |
データベースの整合性が影響を受ける場合のエラー(外部キー違反、一意制約)。 |
InternalError |
内部データベースエラー(カーソル無効、トランザクションの同期外)。 |
ProgrammingError |
プログラミングの誤り(構文ミス、テーブルの見つからないこと、パラメータ数の誤り)。 |
NotSupportedError |
データベースやドライバーでサポートされていない機能です。 |
ConnectionStringParseError |
無効な接続文字列構文や未知のキーワード。 |
基本的なエラー処理
データベースエラーを処理するためにtry-exunxブロックを使用します:
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 ベースクラスから得られる3つの属性を公開します。
| 特性 |
Source |
形容 |
driver_error |
Pythonドライバー |
ODBCからはSQLSTATEが選んだ標準化された英語テキスト(例: "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 スロットリングについては、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コードは、エラー状態を識別するための5文字コードです。 最初の2文字はクラスを示し、最後の3文字はサブクラスを示します。 これらのコードを直接確認する必要はほとんどありません。 代わりに、適切なPython例外タイプ(「例外」欄に記載)を検出してください。 同じ例外タイプ内で特定のエラー条件を区別する必要がある場合、例えばデッドロック(40001)と一般的な接続障害(08S01)を区別するためにSQLSTATEコードを使用してください。
クラス00 - 成功した完成
| SQLSTATE |
例外 |
形容 |
| 00000 |
なし |
成功 |
クラス01 - 警告
| SQLSTATE |
例外 |
形容 |
| 01000 |
Warning |
一般的な警告 |
| 01001 |
Warning |
カーソル操作の競合 |
| 01002 |
Warning |
切断エラー |
| 01003 |
DataError |
set 関数で NULL 値が削除される |
| 01004 |
DataError |
文字列データ、右切り捨て |
| 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 |
DataError |
文字列データ、右切り捨て |
| 22002 |
DataError |
インジケーター変数は必須ですが、指定されていません |
| 22003 |
DataError |
範囲外の数値 |
| 22007 |
DataError |
datetime 形式が無効です |
| 22008 |
DataError |
Datetime フィールドオーバーフロー |
| 22012 |
DataError |
0 で除算しました |
| 22015 |
DataError |
間隔フィールドのオーバーフロー |
| 22018 |
DataError |
キャスト指定の文字値が無効です |
| 22019 |
DataError |
エスケープ文字が無効です |
| 22025 |
DataError |
エスケープ シーケンスが無効です |
| 22026 |
DataError |
文字列データの長さが合致しません |
クラス23 - 完全性制約違反
| SQLSTATE |
例外 |
形容 |
| 23000 |
IntegrityError |
整合性制約違反(一般) |
クラス24 - 無効カーソル状態
| SQLSTATE |
例外 |
形容 |
| 24000 |
内部エラー |
カーソル状態が無効 |
クラス25 - 無効な取引状態
| SQLSTATE |
例外 |
形容 |
| 25000 |
オペレーショナルエラー |
無効トランザクション状態 |
| 25シーズン第1期 |
オペレーショナルエラー |
取引状態不明 |
| 25シーズン2 |
オペレーショナルエラー |
取引はまだ有効です |
| 25シーズン3 |
オペレーショナルエラー |
トランザクションはロールバックされます |
クラス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 |
IntegrityError |
WITH CHECK OPTION 違反 |
クラスHY - CLI特有疾患
| SQLSTATE |
例外 |
形容 |
| HY000 |
DatabaseError |
一般的なエラー |
| HY001 |
オペレーショナルエラー |
メモリ割り当てエラー |
| HY003 |
プログラミングエラー |
無効なアプリケーション バッファーの種類 |
| HY004 |
プログラミングエラー |
SQL データ型が無効です |
| HY007 |
プログラミングエラー |
関連付けられたステートメントが準備されていません |
| HY008 |
オペレーショナルエラー |
操作が取り消されました |
| HY009 |
プログラミングエラー |
null ポインターの使用が無効です |
| HY010 |
プログラミングエラー |
関数シーケンス エラー |
| HY011 |
プログラミングエラー |
現在、属性を設定できません |
| HY012 |
プログラミングエラー |
無効なトランザクション操作コード |
| HY013 |
オペレーショナルエラー |
メモリ管理エラー |
| HY014 |
オペレーショナルエラー |
ハンドル数の上限を超えた |
| HY015 |
プログラミングエラー |
使用可能なカーソル名がありません |
| HY016 |
プログラミングエラー |
実装行ディスクリプタを変更できません |
| HY017 |
プログラミングエラー |
自動割り当てディスクリプタハンドルの不正な使用について |
| HY018 |
オペレーショナルエラー |
サーバーはキャンセルリクエストを拒否しました |
| HY019 |
プログラミングエラー |
非文字および非バイナリデータが分割で送信される |
| HY020 |
DataError |
null 値の連結を試みる |
| HY021 |
プログラミングエラー |
記述子情報の不整合 |
| HY024 |
プログラミングエラー |
属性値が無効です |
| HY090 |
プログラミングエラー |
文字列またはバッファーの長さが無効です |
| HY091 |
プログラミングエラー |
無効なディスクリプタフィールド識別子 |
| HY092 |
プログラミングエラー |
無効な属性/オプション識別子 |
| HY095 |
プログラミングエラー |
関数型が範囲外 |
| HY096 |
プログラミングエラー |
無効な情報型 |
| HY097 |
プログラミングエラー |
カラムタイプの範囲外 |
| HY098 |
プログラミングエラー |
スコープの種類が範囲外 |
| HY099 |
プログラミングエラー |
無効型の範囲外 |
| HY100 |
プログラミングエラー |
一意性オプションの種類が範囲外 |
| HY101 |
プログラミングエラー |
精度オプションの種類が範囲外 |
| HY103 |
プログラミングエラー |
無効な取得コード |
| HY104 |
プログラミングエラー |
有効桁数またはスケール値が無効です |
| HY105 |
プログラミングエラー |
パラメーターの型が無効です |
| HY106 |
プログラミングエラー |
フェッチタイプが範囲外 |
| HY107 |
プログラミングエラー |
行の値が範囲外 |
| HY109 |
プログラミングエラー |
カーソル位置が無効です |
| HY110 |
プログラミングエラー |
無効ドライバー完了 |
| HY111 |
プログラミングエラー |
無効なブックマーク値 |
| HYC00 |
NotSupportedError |
省略可能な機能が実装されていません |
| HYT00 |
オペレーショナルエラー |
タイムアウトの期限が切れました |
| HYT01 |
オペレーショナルエラー |
接続がタイムアウトしました |
クラス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()を使って失敗したトランザクションをクリーンアップします。 明示的なロールバックがなければ、接続はトランザクション失敗状態のままです。
関連するコンテンツ