LoginSignup
3
2

More than 3 years have passed since last update.

Exposedで外部キー制約がないテーブルでもInner Joinしたい

Posted at

KotlinのExposedでつまづいたときのお話です。
ここを参考に。

問題

外部キー制約がないテーブル同士をinnerJoinで結合しようとするとエラーになってしまう
(there is no matching primary key/foreign key pair and constraint missing)

解決方法

innerJoinメソッドではなく、joinメソッドを使用します。

詳細

以下のようにします。

UserTable.join(TodoTable, JoinType.INNER, UserTable.id, TodoTable.userId)

上記のコードを見ていただければ使い方は大体わかると思いますが、引数は以下のようになっています。
(結合するテーブル、結合のタイプ、結合条件に使用するカラム1、結合条件に使用するカラム2)
上記のコードを実行すると、以下のSQLが生成されます。

SELECT `user`.id, `user`.`name`, Todo.id, Todo.title, Todo.done, Todo.user_id FROM `user` INNER JOIN Todo ON `user`.id = Todo.user_id

また、5つ目の引数として、追加条件を渡すことも可能です。

        UserTable.join(TodoTable, JoinType.INNER, UserTable.id, TodoTable.userId) {
            UserTable.name eq TodoTable.title
        }.selectAll().toList()

上記を実行すると以下のようになります。

SELECT `user`.id, `user`.`name`, Todo.id, Todo.title, Todo.done, Todo.user_id FROM `user` INNER JOIN Todo ON `user`.id = Todo.user_id AND  (`user`.`name` = Todo.title)

原因

ExposedのinnerJoin leftJoin rightJoinは、使用する際にテーブル結合するテーブル同士に存在する外部キー制約にのっとった結合条件を使用するようです。つまり、以下のようなテーブルでinnerJoinをしようとすると、

object UserTable : Table("users") {
    val id = uuid("id")
    val name = varchar("name", 20)
}

object TodoTable : Table() {
    val id = integer("id")
    val title = varchar("title", 50)
    val done = bool("done")
    //ユーザーテーブルへの外部キーを持つ
    val userId = uuid("user_id").references(UserTable.id)
}

//innserJoinをやってみる
TodoTable.innerJoin(UserTable).selectAll().toList()

以下のようなSQLを生成しようとします。

SELECT Todo.id, Todo.title, Todo.done, Todo.user_id, `user`.id, `user`.`name` FROM Todo INNER JOIN `user` ON `user`.id = Todo.user_id

TodoTable.innerJoin(UserTable).selectAll().toList()では特に条件を指定しなくとも、外部キーによる結合条件が自動的に入っていることがわかると思います。
ここで、仮に結合テーブルに外部キー制約がないと、結合条件がわからないということでthere is no matching primary key/foreign key pair and constraint missingが発生して落ちてしまうわけですね。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2