Open7
Drizzleのデータ取得方法

- Drizzleドキュメント
https://orm.drizzle.team/docs/select
selectとqueryの違い
-
select:
- QLのSELECT文を作成。
- 型安全にJOINやWHEREを追加できる
- 実行時にSQLを組み立てる
-
query:
- Dirzzleで事前に定義されたSQLクエリのプリセットを作成し、実行する関数。つまり、クエリを事前に定義し、関数として再利用できる。
- selectよりも簡単に書ける
- 実行時ではなく事前に定義し事項される
- プログラムの実行中に条件やパラメーターに応じて、SQL文の内容を組み立てるクエリのこと
- 例: ユーザーの入力に応じてWHERE句を追加・JOINの有無・ソード順を動的に変更

selectの書き方
- selectカラムで任意の表現
-
使い道: SQLの組み込み関数を利用して、データの正規化や検索の一貫性を確保する
const result = await db.select({ id: users.id, lowerName: sql<string>`lower(${users.name})`, }).from(users); select "id", lower("name") from "users";
-
条件付きselect
async function selectUsers(withName: boolean) { return db .select({ id: users.id, ...(withName ? { name: users.name } : {}), }) .from(users); } const users = await selectUsers(true);
-
Distinct select
- SQLのSELECT DISTICTに相当
- 指定したカラムの組み合わせが重複する行を取り除いて、ユニークなレコードのみを返す
-
sqlを使うと生のSQLをかける
- 下記の2つは一緒
import { eq, and, sql } from 'drizzle-orm'; await db.select().from(users).where( and( eq(users.id, 42), eq(users.name, 'Dan') ) ); await db.select().from(users).where(sql`${users.id} = 42 and ${users.name} = 'Dan'`); select "id", "name", "age" from "users" where "id" = 42 and "name" = 'Dan'; select "id", "name", "age" from "users" where "id" = 42 and "name" = 'Dan';
- 下記の2つは一緒
-
with句
- 複雑なクエリをシンプルにする時に使う
- with句で作成したSQLをselectに限らずinsert,update,deletと一緒に使うこともできる
- with句とsubqueryの違い
- with句
- 一時的なテーブルを作成し、それをメインクエリで利用
- 同じクエリ内で複数回参照できる
- 再帰CTEに(WITH RECURSIVE)により、階層構造のデータを扱いやすい
- with句
- subquery
- メインクエリ内に直接()を使ってクエリを埋め込む
- 同じクエリ内で再利用はできないので、1回限りのデータ取得に適している。同じ条件で別の処理をするときに再度同じサブクエリを書く必要がある。
const sq = db.$with('sq').as(db.select().from(users).where(eq(users.id, 42))); const result = await db.with(sq).select().from(sq); with sq as (select "id", "name", "age" from "users" where "id" = 42) select "id", "name", "age" from sq;
-
cast
- castは、SQLでデータ型を変換するための関数
- CAST (値 AS 変換後のデータ型) として使う
- castはポスグレならbigintでMySQLなら少数として扱われるが、これらは数値ではなく文字列値として扱われるためcast(... as int)が必要
-

insertの書き方
- returningでinsertした値を取得できる
- 複数のレコード挿入
await db.insert(users).values([{ name: 'Andrew' }, { name: 'Dan' }]);
- コンフリクト処理
- onConflictDoNothing: 何もしない
- onConflictDoUpdate: 更新する

updateの書き方
- 特になし

deleteの書き方
- 特になし

filterの書き方
-
ne: is not equal
db.select().from(table).where(ne(table.column1, table.column2)) SELECT * FROM table WHERE table.column1 <> table.column2
-
gt: nより大きい
-
gte: n以上
-
lt: nより小さい
-
lte: lte以内
-
inArray: nが指定した配列内に存在するか
-
between: nがx - yの範囲内か

joinの書き方
- INNER JOIN
- 内部結合
- テーブル同士を内部結合し、条件に合致したレコードのみ取得する
- LEFT JOIN
- 左外部結合
- 内部結合とは違い、右側テーブルの条件に合致しないが左側テーブルに存在しているレコードも取得する
- RIGHT JOIN
- 右外部結合
- 左外部結合の逆で、左側テーブルに存在しているレコードは、右側テーブルの条件に合わなくても全て取得する
- FULL JOIN
- 完全外部結合
- 左側、右側テーブルので、片方のテーブルに条件がマッチしなくても全てのレコードを取得する