1クエリで外部キーを取得しつつレコードを保存する(sqlite/js)

SQL

Booksテーブル(id, title, author_id)とAuthorsテーブル(id, name)があるとして、
本のタイトルと著者名の2つのデータをもってBooksテーブルにInsertしたいとします。

BooksテーブルではAuthor_idが必要なため、これを取得する必要があります。
深く考えずに実装すると、

const getQuery = `SELECT id FORM authors WHERE name = $name`;
db.get(getQuery, {$name: name}, (err, row)=>{
    authorId = row.id;
    const insertQuery = `INSERT INTO books(title, author_id)
                         VALUES($title, $author_id)`
    db.run(insertQuery, {$title: title, $author_id: authorId });
})

こんな感じでGetクエリのコールバックでInsertクエリを発行する感じになります。
これはこれでなんの問題もありませんが、2回クエリを発行するのが無駄だと思いません?

実はINSERT文はVALUES()の代わりにSELECT文も使えます。
別のテーブルからコピーを取ってきて、そのデータを用いてそのままINSERTできます。

const insertQuery = `INSERT INTO books(title, author_id)
                    SELECT title, author_id FROM anotherBooksTable`;

このクエリを発行するとanotherBooksTableのレコードを取得して、booksテーブルにInsertできます。

これを応用すると以下のようなことができます。

const insertQuery = `INSERT INTO books(title, author_id)
                    SELECT id, $title FROM authors WHERE name = $name`;
db.run(insertQuery, {$title: title, $name: name})

クエリの発行回数も減ったし、なによりコールバックがなくなったのですっきりしました。

コメント