C Sharpens you up

http://qiita.com/yuba に移しつつあります

SQLのカラム制約はテーブル制約と等価

SQLのテーブルにcol_A, col_Bというカラムがあるとしますよ。ここでCHECK(col_A = col_B)という制約を、col_Aにカラム制約として付けたとします。すると

UPDATE my_table SET col_A = col_A + 1;

なんて操作は阻止されます。当然。では、

UPDATE my_table SET col_B = col_B + 1;

という操作は禁止されるの?

制約はカラムcol_Aに付いてるからcol_Bの変更は監視外なのかな? いや、制約はそう簡単に破られない?
こういう疑問が生じた場合、SQLだと実装依存と答えておけば正解なことが多くてやになるんですが、PostgreSQLでまず実験してみました。その結果は、

カラム制約を書いても内部でテーブル制約に変換されてしまう。
よって結果的に阻止される。

という意外な結果に。詳細は裏付け調査してくれたこちらの記事を参照。

PostgreSQLのこの仕様は実際SQL的にどうなんだという点は確認しておくべきでしょう。

SQL-92仕様書の263ページ。

The <column constraint definition> is equivalent to a
<table constraint definition> as follows:

http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt

なんたること、カラム制約はテーブル制約と等価というのがSQLの標準仕様でした。等価なら、内部で勝手に変換してしまうPostgreSQLの動作にもまったく問題ございません。

世の中にはわりと

「列制約」と「テーブル制約」の違い:列制約が列のみに適用されるのに対し、テーブル制約が列のグループに適用されるということ。

制約 - Oracle学習ノート

という誤解がまかり通っているわけですが、実際カラム制約とテーブル制約が別々に定義されてたらそりゃ仕方ないですね。

ちなみに、なぜそこまで気になるなら最初からテーブル制約だけ書いていればいいのにカラム制約のことを気にするかって、使ってるER作図ツールだとカラム制約の方が書きやすいもんで。