データベースの基本 — Webアプリの「記憶」を理解する

バイブコーディング入門 — 第18回

前回のおさらいと、今回のテーマ

前回(第17回)では、セキュリティの基本を学んだ。HTTPSによる通信の暗号化、XSS・SQLインジェクション・CSRFという3大攻撃手法、そしてAIにセキュリティレビューを依頼するテンプレート。アプリを公開する前に最低限チェックすべきことがわかった。

その中で「SQLインジェクション」という攻撃を学んだ。データベースへの問い合わせ文を改ざんする攻撃だった。しかし、そもそも「データベース」とは何なのか。

あなたが12人の税理士事務所の所長だとしよう。バイブコーディングで顧問先管理アプリを作り始めた。AIに「顧問先の情報を保存して、検索できるようにしたい」と伝えたら、AIがこう返してきた。

「Supabaseにテーブルを作成します。clients テーブルに company_name、representative、contract_date、monthly_fee カラムを設定します。外部キーで contacts テーブルとリレーションを張りますね」

テーブル。カラム。外部キー。リレーション。何を言っているのかさっぱりわからない。でも、AIが自信たっぷりに進めているから、とりあえず「はい」と答えてしまう。

この「とりあえず、はい」が危ない。データベースの構造を理解していないと、次のような問題が起きる。

  • AIが作ったテーブル構造に問題があっても気づけない
  • データが増えたときに動作が極端に遅くなる
  • 必要なデータを取り出すときに、AIへの指示がうまく伝わらない
  • 第17回で学んだSQLインジェクションのリスクを正しく評価できない

今回は、バイブコーダーが最低限知っておくべきデータベースの基礎を解説する。

今回学ぶこと:

  • データベースとは何か(Excelとの違い)
  • テーブル・行・列の構造
  • SQLの基本(SELECT, INSERT, UPDATE, DELETE)
  • リレーション(テーブル同士のつながり)
  • Supabaseとは何か、なぜバイブコーディングで使われるのか
  • AIにデータベース設計を依頼するテンプレート

第2回の3層構造の知識と、第17回のSQLインジェクションの知識が、ここで一本の線につながる。

データベースとは何か — アプリの「記憶」

第2回で、Webアプリは3層構造で動いていると学んだ。フロントエンド(見た目)、バックエンド(処理)、データベース(記憶)の3つだ。

データベースは、この3層目にあたる「記憶」の部分だ。

人間に例えてみよう。フロントエンドは「顔」、バックエンドは「脳」、データベースは「記憶」だ。あなたが誰かに「田中さんの電話番号は?」と聞いたとき、脳が記憶から情報を探し出して、口で答える。Webアプリも同じだ。ブラウザ(フロントエンド)が「田中さんの情報を見せて」とリクエストし、サーバー(バックエンド)がデータベースから探し出して返す。

データベースがなければ、アプリは何も覚えられない。ログイン情報、顧客データ、商品リスト、注文履歴、すべてが消えてしまう。ページを閉じて開き直すたびに、まっさらな状態に戻る。

Excelとデータベースの違い

データベースと聞いて、Excelのスプレッドシートを思い浮かべた方は多いだろう。実際、構造は似ている。行と列でデータを整理する点は同じだ。

しかし、決定的な違いが3つある。

1つ目: 同時アクセスへの対応。Excelは基本的に1人が1つのファイルを開いて作業する。複数人が同時に同じセルを編集すると、データが壊れることがある。データベースは、100人、1,000人が同時にアクセスしても、データの整合性(つじつまが合った状態)を保つ仕組みが備わっている。

2つ目: データ量への対応。Excelは数万行を超えると動作が重くなる。データベースは、数百万行、数千万行のデータを扱っても高速に検索できる。顧問先100社の情報なら体感差はないが、顧問先ごとに月次仕訳1,000件、10年分で12万件となると、Excelでは限界がある。

3つ目: プログラムからの操作。ExcelをWebアプリから自動的に読み書きするのは手間がかかる。データベースは、プログラムから「このデータを取ってきて」「この行を更新して」と命令するのが前提の設計になっている。だからWebアプリのバックエンドと相性がよい。

テーブル・行・列 — データベースの基本構造

データベースの中身は「テーブル」で整理されている。テーブルとは、日本語で言えば「表」だ。Excelのシートに近いイメージだと思ってよい。

税理士事務所の例で考えてみよう。顧問先管理アプリには、次のようなテーブルがあるとする。

clients テーブル(顧問先一覧):

id company_name representative contract_date monthly_fee
1 株式会社山田商事 山田太郎 2024-04-01 50000
2 有限会社鈴木工業 鈴木一郎 2023-10-15 80000
3 合同会社佐藤デザイン 佐藤花子 2025-01-10 35000

このテーブルには、3つの重要な概念がある。

行(ロウ、row): 横の1行がデータ1件を表す。上の表では、「株式会社山田商事」の情報が1行目、「有限会社鈴木工業」が2行目だ。行のことを「レコード」とも呼ぶ。Excelの行と同じ感覚だ。

列(カラム、column): 縦の1列がデータの種類を表す。「company_name」が会社名、「monthly_fee」が月額顧問料、という具合だ。列のことを「フィールド」とも呼ぶ。Excelの列見出しと同じ感覚だ。

id: 各行を一意に(重複なく)識別するための番号だ。「主キー」(プライマリーキー、Primary Key)と呼ばれる。なぜ必要なのか。もし「山田商事」という会社が2社あったとき、会社名だけでは区別できない。id=1 と id=4 のように、番号で区別する。Excelの行番号に似ているが、データベースのidは削除しても番号が詰まらない(1, 2, 3 の2を削除しても、1, 3 のまま)。

型(データの種類)を決める

Excelでは、1つのセルに文字でも数字でも日付でも自由に入れられる。データベースは違う。各列には「型」(データの種類)を事前に決める。

主な型:

  • text(テキスト): 文字列。会社名、住所、メモなど
  • integer(インテジャー): 整数。金額、数量、年齢など
  • boolean(ブーリアン): 真偽値。「はい」か「いいえ」の2択。「契約中かどうか」など
  • date(デイト): 日付。契約日、期限日など
  • timestamp(タイムスタンプ): 日時。「2026年4月16日 14:30:00」のように時刻まで含む

なぜ型を決めるのか。型を決めておくと、間違ったデータが入るのを防げる。monthly_fee(月額顧問料)をinteger型にしておけば、誰かが間違えて「五万円」と文字で入れようとしたときに、データベースがエラーを出して防いでくれる。Excelだと「五万円」がそのまま入ってしまい、集計のときにエラーになる。

SQL — データベースへの「お願い」の書き方

SQLは、データベースに対して「お願い」をするための言語だ。第17回でSQLインジェクションを学んだとき、SQL文が少し出てきた。今回は、もう少し詳しく見ていこう。

少しだけコードが出てくるが、意味を理解できればよい。自分で書く必要はない。バイブコーディングでは、AIがSQL文を書いてくれる。あなたが知っておくべきなのは「AIが書いたSQL文が何をしているのか」を読み取る力だ。

SQLの基本操作は4つだ。この4つを覚えれば、データベースで行われていることの大部分がわかる。

SELECT — データを取ってくる

SELECT(セレクト)は「このデータを取ってきて」というお願いだ。最も頻繁に使う操作だ。

SELECT company_name, monthly_fee FROM clients

これは「clientsテーブルから、会社名と月額顧問料を取ってきて」という意味だ。結果は:

company_name monthly_fee
株式会社山田商事 50000
有限会社鈴木工業 80000
合同会社佐藤デザイン 35000

条件を付けることもできる。

SELECT company_name, monthly_fee FROM clients WHERE monthly_fee >= 50000

WHERE(ウェア)は「条件」だ。「月額顧問料が5万円以上の顧問先だけ取ってきて」という意味になる。結果は山田商事と鈴木工業の2件だ。

並び順を指定することもできる。

SELECT company_name, monthly_fee FROM clients ORDER BY monthly_fee DESC

ORDER BY(オーダーバイ)は「並べ替え」、DESC(デスク)は「降順」(大きい順)だ。月額顧問料が高い順に並ぶ。

INSERT — データを追加する

INSERT(インサート)は「新しいデータを追加して」というお願いだ。

INSERT INTO clients (company_name, representative, contract_date, monthly_fee)
VALUES ('株式会社田中建設', '田中次郎', '2026-04-01', 60000)

これは「clientsテーブルに、田中建設の情報を1行追加して」という意味だ。idは自動で採番されるので、指定しなくてよい。

UPDATE — データを更新する

UPDATE(アップデート)は「既存のデータを変更して」というお願いだ。

UPDATE clients SET monthly_fee = 55000 WHERE id = 1

これは「clientsテーブルで、id=1の行(山田商事)の月額顧問料を55,000円に変更して」という意味だ。

WHEREを付け忘れると、全行が更新されてしまう。UPDATEとDELETEでWHEREを忘れるのは、データベース操作で最も怖いミスの1つだ。

DELETE — データを削除する

DELETE(デリート)は「データを削除して」というお願いだ。

DELETE FROM clients WHERE id = 2

これは「clientsテーブルから、id=2の行(鈴木工業)を削除して」という意味だ。

DELETEもWHEREを忘れると全行が消える。「DELETE FROM clients」とだけ書くと、全顧問先のデータが消滅する。第17回のSQLインジェクションで「最悪の場合、テーブルを全削除できる」と書いたのは、このことだ。

CRUD — 4つの操作をまとめて

この4つの操作は、頭文字を取ってCRUD(クラッド)と呼ばれる。

  • C: Create(作成)→ INSERT
  • R: Read(読み取り)→ SELECT
  • U: Update(更新)→ UPDATE
  • D: Delete(削除)→ DELETE

Webアプリで行われるデータ操作は、ほぼこの4つに分類できる。顧問先を「登録する」「一覧で見る」「情報を修正する」「解約して削除する」。すべてCRUDだ。

リレーション — テーブル同士のつながり

ここからが、Excelとデータベースの最大の違いだ。

Excelでは、1つのシートにすべての情報を詰め込むことが多い。顧問先の基本情報も、担当者の連絡先も、面談の記録も、同じシートの右にどんどん列を増やしていく。

データベースでは、情報を複数のテーブルに分けて管理する。そして、テーブル同士を「つなげる」。この「つながり」をリレーション(関係)と呼ぶ。

なぜ分けるのか。1つの表にすべてを入れると、データの重複が起きるからだ。

例を見てみよう。顧問先「山田商事」には、担当者が3人いるとする。経理の佐藤さん、総務の田中さん、社長の山田さんだ。

1つのテーブルにすべて入れると:

company_name monthly_fee contact_name contact_role contact_phone
株式会社山田商事 50000 佐藤美穂 経理 03-1111-2222
株式会社山田商事 50000 田中健一 総務 03-1111-3333
株式会社山田商事 50000 山田太郎 社長 03-1111-1111

「株式会社山田商事」と「50000」が3回繰り返されている。月額顧問料が変わったとき、3行すべてを更新しなければならない。1つ更新し忘れたら、データの不整合(つじつまが合わない状態)が起きる。

データベースでは、こう分ける。

clients テーブル:

id company_name monthly_fee
1 株式会社山田商事 50000

contacts テーブル:

id client_id name role phone
1 1 佐藤美穂 経理 03-1111-2222
2 1 田中健一 総務 03-1111-3333
3 1 山田太郎 社長 03-1111-1111

contacts テーブルの client_id が「1」になっている。これは clients テーブルの id=1(山田商事)を指している。この client_id のことを「外部キー」(フォーリンキー、Foreign Key)と呼ぶ。外部キーは「別のテーブルの行を指し示すポインター」だ。

こうすれば、山田商事の月額顧問料が変わっても、clients テーブルの1行を更新するだけで済む。担当者が何人いても、会社情報は1箇所だけだ。

1対多の関係

上の例では、1つの顧問先に複数の担当者がいる。これを「1対多」の関係と呼ぶ。1つの「親」に対して、複数の「子」がぶら下がる構造だ。

Webアプリでよく出てくる1対多の例:

  • 1人のユーザーが複数の注文を持つ(ECサイト)
  • 1つの会社が複数の従業員を持つ(人事管理)
  • 1つのプロジェクトが複数のタスクを持つ(タスク管理)
  • 1人の顧問先が複数の月次報告を持つ(税理士事務所アプリ)

バイブコーディングでAIが「外部キーでリレーションを張ります」と言ったとき、それはこの「1対多の関係を設定する」という意味だ。

JOINでテーブルを結合する

テーブルを分けたのはいいが、「山田商事の担当者一覧を見たい」というときはどうするのか。分かれているデータを1つにまとめて表示する必要がある。

このとき使うのがJOIN(ジョイン)だ。JOINは「2つのテーブルを、共通のキーで結合する」操作だ。

SELECT clients.company_name, contacts.name, contacts.role
FROM clients
JOIN contacts ON clients.id = contacts.client_id
WHERE clients.id = 1

これは「clientsテーブルとcontactsテーブルを、clients.idとcontacts.client_idが一致する行同士でつなげて、山田商事(id=1)の会社名・担当者名・役職を取ってきて」という意味だ。

結果は:

company_name name role
株式会社山田商事 佐藤美穂 経理
株式会社山田商事 田中健一 総務
株式会社山田商事 山田太郎 社長

JOINは最初は複雑に感じるかもしれないが、イメージとしては「2つのExcelシートを、共通の番号を使って1つの表にまとめる」操作だと思えばよい。

Supabase — バイブコーダーの味方

ここまでデータベースの基礎を学んだ。では、バイブコーディングでは具体的にどうやってデータベースを使うのか。

答えは、多くの場合「Supabase(スーパーベース)」だ。

Supabaseは、データベースを含む一連のサービスを、Webブラウザから簡単に使えるようにしたサービスだ。正式には「BaaS(バース、Backend as a Service)」と呼ばれるカテゴリに属する。バックエンドの機能を、サービスとして提供してくれるものだ。

なぜSupabaseがバイブコーディングで人気なのか

理由は3つある。

1つ目: データベースの構築が不要。通常、データベースを使うには、サーバーにデータベースソフトをインストールし、設定し、管理する必要がある。Supabaseを使えば、Webブラウザでプロジェクトを作るだけで、データベースがすぐに使える状態になる。

2つ目: SQL文を書かなくてもよい。Supabaseには「クエリビルダー」と呼ばれる仕組みがあり、JavaScriptのコードでデータベースを操作できる。

たとえば、「月額顧問料が5万円以上の顧問先を取ってくる」という操作は:

SQL文で書くと:

SELECT * FROM clients WHERE monthly_fee >= 50000

Supabaseのクエリビルダーで書くと:

supabase.from('clients').select('*').gte('monthly_fee', 50000)

どちらも同じことをしている。クエリビルダーの方が「プログラムのコード」に馴染みやすく、AIもこちらの形式でコードを生成することが多い。そして第17回で学んだ通り、クエリビルダーは自動でSQLインジェクション対策をしてくれる。

3つ目: 認証機能が付いている。第16回で学んだ認証(ログイン)の仕組みが、Supabaseには最初から含まれている。メール・パスワード認証、Googleログイン、パスワードリセットなど、自分でゼロから作らなくてよい。

Supabaseのダッシュボード

SupabaseにはWebブラウザで使える管理画面(ダッシュボード)がある。ここで、Excelのように視覚的にテーブルの中身を見たり、行を追加したり、構造を変更したりできる。

バイブコーディングでは、AIがコードからSupabaseを操作する。しかし、「今テーブルにどんなデータが入っているか」を確認したいときは、このダッシュボードを開けばよい。SQLを知らなくても、データの状態をExcel感覚で確認できる。

RLS — 行レベルのアクセス制御

Supabaseには「RLS(アールエルエス、Row Level Security)」という機能がある。日本語で言えば「行レベルのセキュリティ」だ。

これは「誰がどの行を見られるか」を制御する仕組みだ。たとえば、「ログインしているユーザーは、自分が作成したデータだけを見られる」「管理者はすべてのデータを見られる」といったルールを設定できる。

なぜこれが重要なのか。RLSを設定しないと、Supabaseのデータベースにアクセスできる人は、すべてのデータを自由に読み書きできてしまう。顧問先管理アプリで、AさんがBさんの顧問先データを見られてしまったり、悪意のあるユーザーが他人のデータを削除できてしまったりする。

バイブコーディングでSupabaseを使うとき、AIに「RLSは設定してありますか?」と確認することを強く推奨する。

バイブコーダーのデータベース設計テンプレート

バイブコーディングでAIにデータベース設計を依頼するとき、次のテンプレートを使うと精度が上がる。


テンプレート: データベース設計の依頼

「このアプリで管理したいデータは以下の通り。適切なテーブル設計をしてほしい。

管理したいデータ:

  • (例: 顧問先の会社情報 — 会社名、代表者名、住所、契約日、月額顧問料)
  • (例: 担当者の連絡先 — 名前、役職、電話番号、メールアドレス、どの会社の人か)
  • (例: 面談記録 — 日時、参加者、議題、メモ、次回アクション)

設計にあたって以下を守ってほしい:

  1. データの重複を避けるために、適切にテーブルを分けてリレーションを設定してほしい
  2. 各テーブルにidの主キーを設定してほしい
  3. 作成日時と更新日時のカラムを全テーブルに付けてほしい
  4. Supabase上に作成してほしい
  5. RLS(Row Level Security)を設定して、ログインユーザーのみアクセスできるようにしてほしい
  6. 作成するテーブルの一覧と、各テーブルのカラム(列名・型・説明)を一覧表で見せてほしい

設計ができたら、テーブル間の関係(1対多など)も図で説明してほしい。」


ポイントは最後の「一覧表で見せてほしい」と「関係も図で説明してほしい」だ。AIが作った設計を、自分の目で確認できる形にしてもらう。何を言っているかわからないまま先に進むのが一番危険だ。

インデックス — 検索を速くする仕組み

データが少ないうちは気にならないが、データが増えてきたときに重要になるのが「インデックス」だ。

インデックスは、日本語で言えば「索引」だ。辞書の後ろにある「あいうえお順の索引」を想像してほしい。辞書で「データベース」という言葉を探すとき、1ページ目から順番にめくっていたら途方もない時間がかかる。索引を使えば「た行」→「て」→「データベース: 234ページ」と、すぐにたどり着ける。

データベースのインデックスもまったく同じ原理だ。「この列はよく検索に使うから、索引を作っておいてね」とデータベースに指示しておくと、検索が格段に速くなる。

たとえば、顧問先を会社名で検索することが多いなら、company_name列にインデックスを作る。顧問先が1,000社あっても、インデックスがあれば一瞬で見つかる。インデックスがないと、1,000行を1行ずつ順番にチェックすることになる。

バイブコーディングでは、AIに「よく検索する列にインデックスを付けてほしい」と伝えればよい。具体的にどの列がよく検索されるかは、あなたの業務を知っているあなた自身が一番わかっている。「会社名で検索することが多い」「契約日で絞り込むことが多い」と伝えれば、AIが適切にインデックスを設定してくれる。

よくある不安と答え

SQLを覚えなければいけないのか

覚えなくてもバイブコーディングはできる。AIがSQL文やSupabaseのコードを書いてくれるからだ。ただし、SELECT・INSERT・UPDATE・DELETEの4つが「何をしているか」を読み取れると、AIとのやりとりの精度が格段に上がる。「この操作はSELECTだから、データは変わらないな」「DELETEか、消えるのか。WHERE条件は正しいか」と判断できるようになる。

データが消えたらどうなるのか

Supabaseには自動バックアップ機能がある。Proプラン(月額25ドル、約3,800円)以上なら、毎日自動でバックアップが取られる。万が一データが消えても、バックアップから復元できる。ただし、無料プランでは自動バックアップはないので、重要なデータを扱うなら有料プランへの移行を検討した方がよい。

Supabaseの無料プランでどこまでできるか

Supabase無料プランの主な制限(2026年4月時点):

  • データベースのストレージ: 500MB
  • 月間アクティブユーザー: 50,000人
  • プロジェクト数: 2つ
  • 自動バックアップ: なし
  • 1週間操作がないとデータベースが一時停止する

12人の税理士事務所のアプリなら、無料プランで十分に動く。顧問先100社、各社の担当者・面談記録を合わせても、500MBには到底届かない。ユーザー数も50,000人の制限には遠い。ただし、1週間操作がないと一時停止する点は注意が必要だ。業務で毎日使うアプリなら問題ないが、月に数回しか使わないアプリなら有料プランの方が安心だ。

ExcelからSupabaseにデータを移行できるか

移行できる。Supabaseのダッシュボードには、CSVファイル(カンマ区切りの表データ)をインポートする機能がある。ExcelのデータをCSV形式で保存し、Supabaseにインポートすればよい。AIに「ExcelのデータをSupabaseに移行したい。CSVインポートの手順を教えて」と聞けば、具体的な手順を案内してくれる。

まとめ

データベースは、Webアプリの「記憶」だ。Excelと似た構造(テーブル・行・列)だが、同時アクセス・大量データ・プログラムからの操作に強い。SQL(SELECT, INSERT, UPDATE, DELETE)はデータベースへの「お願い」の書き方で、4つの操作を覚えればデータベースで何が行われているかの大部分がわかる。テーブルを分けてリレーション(外部キー)でつなぐことで、データの重複を防ぐ。Supabaseはこれらの仕組みを、バイブコーダーが使いやすい形で提供してくれるサービスだ。

次回は「環境変数とデプロイ — 『ローカルで動く』から『世界に公開』へ」。アプリを自分のパソコンで動かしている段階から、インターネット上に公開する方法を解説する。環境変数(APIキーなどの秘密情報の管理方法)と、Vercelを使ったデプロイの手順を学ぶ。

参考リファレンス

  • 前回: 第17回「HTTPS・セキュリティの基本 — 『知らなかった』では済まない」(/articles/vc-017)
  • 次回: 第19回「環境変数とデプロイ — 『ローカルで動く』から『世界に公開』へ」(/articles/vc-019)
  • 第2回「フロントエンド・バックエンド・データベース — 3層構造を理解する」(/articles/vc-002)
  • 第17回「HTTPS・セキュリティの基本」内のSQLインジェクション解説(/articles/vc-017)
  • バイブコーディング入門 カリキュラム(/vibe-coding)