1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

以下のドキュメントに基づいて解説します。
また、データベーステーブルの作成及びRLSポリシーの設定は完了している前提とします。

RLSポリシーについては、以下参照。

環境変数の設定

supabseプロジェクトのページから以下の2つの変数を取得し、.env.localファイルに記述する

.env.local
NEXT_PUBLIC_SUPABASE_URL=<SUBSTITUTE_SUPABASE_URL>
NEXT_PUBLIC_SUPABASE_ANON_KEY=<SUBSTITUTE_SUPABASE_ANON_KEY>

Supabaseパッケージのインストール

以下をターミナルで実行し、パッケージをインストールする

npm install @supabase/supabase-js

Supabaseクライアントの作成

Next.jsプロジェクト内でSupabaseのクライアントを作成していく

  1. プロジェクトのルートディレクトリにutils/supabaseディレクトリを作成
  2. utils/supabaseディレクトリにserver.tsx, client.tsxを作成
utils/supabase/client.tsx
import { createBrowserClient } from "@supabase/ssr";
import { Database } from "@/types/database.types";

export const createClient = () => {

    createBrowserClient<Database>(
        process.env.NEXT_PUBLIC_SUPABASE_URL!,
        process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    );
};
utils/supabase/server.tsx

import { createServerClient, type CookieOptions } from "@supabase/ssr";
import { cookies } from "next/headers";
import { Database } from "@/types/database.types";

export const createClient = async() => {

  const cookieStore = await cookies();  

  return createServerClient<Database>(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        get(name: string) {
          return cookieStore.get(name)?.value;
        },
        set(name: string, value: string, options: CookieOptions) {
          try {
            cookieStore.set({ name, value, ...options });
          } catch (error) {
            // The `set` method was called from a Server Component.
            // This can be ignored if you have middleware refreshing
            // user sessions.
          }
        },
        remove(name: string, options: CookieOptions) {
          try {
            cookieStore.set({ name, value: "", ...options });
          } catch (error) {
            // The `delete` method was called from a Server Component.
            // This can be ignored if you have middleware refreshing
            // user sessions.
          }
        },
      },
    },
  );
};

使用する

サーバサイドで使用する

page.tsx
import { createClient } from '@/utils/supabase/server';
export default async function Instruments() {
  const supabase = await createClient();
  const { data: instruments } = await supabase.from("instruments").select();
  return <pre>{JSON.stringify(instruments, null, 2)}</pre>
}

クライアントサイドで使用する

page.tsx
'use client'

import { createClient } from '@/utils/supabase/client';
export default async function Instruments() {
  const supabase = await createClient();
  const { data: instruments } = await supabase.from("instruments").select();
  return <pre>{JSON.stringify(instruments, null, 2)}</pre>
}

クエリの書き方

.from(tableName)

対象のテーブルを指定します。

supabase.from('users')

.select(columns)

カラムを指定します。*で全カラム指定。

supabase.from('users').select('*')
supabase.from('users').select('id, name')
supabase.from('users').select('profile(id, bio)') // リレーションの取得

.insert(data)

新しいレコードを挿入します。

const { data, error } = await supabase
  .from('users')
  .insert([{ name: 'Taro', age: 30 }])

.update(data)

レコードを更新します。.eq()などで条件を指定する必要があります。

const { data, error } = await supabase
  .from('users')
  .update({ age: 31 })
  .eq('id', 1)

.delete()

レコードを削除します。.eq()などで条件を指定する必要があります。

const { data, error } = await supabase
  .from('users')
  .delete()
  .eq('id', 1)

比較系フィルター( .eq(column, value) .neq() .gt() .gte() .lt() .lte() )

フィルター条件を指定します。

.select('*').eq('id', 1)       // id = 1
.select('*').neq('age', 20)    // age != 20
.select('*').gt('age', 20)     // age > 20
.select('*').gte('age', 20)    // age >= 20
.select('*').lt('age', 30)     // age < 30
.select('*').lte('age', 30)    // age <= 30

セット・範囲系フィルタ( .in(column, [values]) .notIn() .is() .not() )

指定カラムが配列内要素との一致・不一致によってフィルターします

.in() : 配列に含まれる
.notIn() : 配列に含まれない
.is() : nullの比較
.not() : 否定(特殊系)

.select('*').in('id', [1, 2, 3])         // id == 1 or 2 or 3
.select('*').notIn('id', 'in', '(1, 2)') // id != 1 and id != 2
.select('*').is('deleted_at', null)      // deleted_at == null
.select('*').not(id, 'eq', 0)            // status != 0

部分一致検索・パターンマッチ( .like(column, pattern) .ilike() .textSearch() .match() )

部分一致・全部一致で検索します(%をワイルドカードに使用)

// '太郎'に部分一致
.select('*').like('name', '%太郎%')
// '@gmail.com'に大文字小文字無視の部分一致
.select('*').ilike('email', '%@gmail.com')
// patternに全部一致するフルテキスト検索
.select('*').textSearch('description', 'search term')
// name == 'Taro' and age == 30 に一致するデータ
.select('*').match({ name: 'Taro', age: 30 })

.order(column, { ascending: true/false })

ascending: true/falseで(降順・昇順)並び替えを行います

// `created_at`カラムについて昇順で並び替える
.select('*').order('created_at', { ascending: false })

.limit(count)

取得件数を制限します

// 10件のみ取得する
.select('*').limit(10)

.single() / .maybeSingle()

.single() :1件だけ取得することを期待(なければエラー)
.maybeSingle():1件取得できれば返す(なくてもエラーにならない)

// id == 1のデータを1件だけ取得する(なければエラー)
.select('*').eq('id', 1).single()

.rpc(function_name, params)

Supabaseのストアドプロシージャ(PostgreSQL関数)を呼び出します

const { data, error } = await supabase
  .rpc('get_user_posts', { user_id: 1 })

複数条件の組み合わせ例

const { data, error } = await supabase
  .from('users')
  .select('*')
  .gt('age', 20)
  .lt('age', 50)
  .like('name', '%太郎%')
  .order('created_at', { ascending: false })
  .limit(10)

Supabaseはバックエンドで PostgREST を使用しており、クエリチェーンで指定された条件(.eq(), .gt(), .like()など)は、最終的に1つのHTTPクエリパラメータ群に変換されてサーバーに送信されます。

このため、以下のように順番を変えても、SQLに変換されたときには同じ意味のWHERE句になります。

ただし順序が意味を持つケースもある

順不同が前提ですが、以下のような非フィルター系メソッド(副作用があるもの)が絡む場合は、順序に注意が必要です。

❌ 良くない例

// 更新前にフィルターせずに .update() を呼ぶと全件対象になる可能性
supabase
  .from('users')
  .update({ status: 'active' })  // ← この時点で全件対象になる
  .eq('country', 'Japan')

✅ 正しい順序

// フィルターしてから更新
supabase
  .from('users')
  .eq('country', 'Japan')
  .update({ status: 'active' })
1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?