SQLの制約エラーの詳細を取得する方法
1つ前のエントリで、SQLの制約はエラーの詳細拾えなくて使えないわーといったのが聞こえたわけではないのだろうが、Bruce Momijan(PostgreSQLのCore Developer)がこんなエントリを書いていた。
Matching Server and Client Constraints
- チェック制約を使うと無効なデータの入力を避けることができるが、ユーザーに対するフィードバックにはあまり役に立たない。1つの改善案は、制約に名前をつけること
CREATE TABLE ledger (id SERIAL, balance NUMERIC(10,2) CONSTRAINT "Zero and negative balances not allowed" CHECK (balance > 0)); INSERT INTO ledger VALUES (DEFAULT, -2.00); ERROR: new row for relation "ledger" violates check constraint "Zero and negative balances not allowed" DETAIL: Failing row contains (1, -2.00).
エラーメッセージを解析して制約名を取得することができる。けどまあそれでも色々問題あるけど
PostgreSQL 9.3からは、より簡単に制約名を取得することができるようになる
みたいなことが書かれているようだ。ドキュメントを見てみたところ、9.3ではPQresultErrorField()
の引数に以下のものが追加されている。
- PG_DIAG_SCHEMA_NAME
- PG_DIAG_TABLE_NAME
- PG_DIAG_COLUMN_NAME
- PG_DIAG_DATATYPE_NAME
- PG_DIAG_CONSTRAINT_NAME
ドライバが対応すれば、これらの値をクライアントから取得できるようになるだろう。
また、制約に名前をつけるというのはMySQLでも可能だ。MySQLはCHECK制約はサポートされていないので外部キー制約の例。
mysql> CREATE TABLE Bugs( -> bug_id int NOT NULL, -> reported_by bigint unsigned, -> PRIMARY KEY (bug_id), -> CONSTRAINT `報告者が変だよ!` FOREIGN KEY (reported_by) REFERENCES Accounts(account_id) -> ); Query OK, 0 rows affected (0.02 sec) mysql> mysql> insert into Bugs values (1, 1000); ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`sqlap`.`Bugs`, CONSTRAINT `報告者が変だよ!` FOREIGN KEY (`reported_by`) REFERENCES `Accounts` (`account_id`))