複数行を返すかもしれないサブクエリー

SQLのサブクエリーが複数行を返すからどうとかいうエラーは型と型の演算結果がどんな型になるかのデータを入れたテーブルを検索するサブクエリーで起こっていることまで絞り込めた。そのサブクエリーと=で比較しているからだな。でも他にも同じようにやってるところがあるけどなんでここだけ? とりあえず=をINに変えれば解決はするけど、気になるのでちょっと考えてみた。
ていうか、特定のテーブルだけで起こってたのですぐにピンと来て実際は考えてない。

SELECT * FROM foo
WHERE result_type = (
  SELECT result
  FROM type_promotion
  WHERE operator = '+' AND lhs = 1 AND rhs = 2);

原因はサブクエリーのWHERE句で使ってる三つのカラム(operator, lhs, rhs)がユニークじゃないからだ。その結果条件がユニークにならないから複数行返す可能性があると判断されてたんだな。WHERE句で使ってる三つのカラムをまとめてユニークにしてやれば=にしてもエラーがでなくなった。PostgreSQLは賢いな、実際1行しか返らないデータであっても実行する前からエラーにされるのは余計なお世話な気もするけど。

 CREATE TABLE type_promotion (
  id		SERIAL,
  operator	TEXT NOT NULL,
  lhs		INTEGER NOT NULL,
  rhs		INTEGER NOT NULL,
  result	INTEGER NOT NULL,
  CONSTRAINT pk_type_promotion_id PRIMARY KEY(id),
  CONSTRAINT uq_lhs_operator_rhs UNIQUE(operator, lhs, rhs)
);

でもなんてpsql上ではエラーにならないんだろう?


このテーブル後から追加してデバッグが終わってなかったみたいだな。DROPするSQLにも書かれてないし、一昨年の最後にやりかけてたのはこれか。


これ書いててlhsとrhsとresultを外部キーにすべきことにも気がついた。typesテーブルのidが入るので。