はじめに
サポートチームには、チケット同士の対応関係を失わずに、検索や更新ができる記録が必要です。Cloudflare D1 は、関連する情報をテーブルに保存し、必要なデータを記述する言語である SQL を受け付けるマネージドデータベースです。テーブルはスプレッドシートに似ています。各行が 1 件のチケットを表し、名前付きの列にそのフィールドが格納されます。
このコースを開始する前に、LabEx を Cloudflare アカウントに接続するを完了してください。 この実験では、LabEx VM のターミナル、デバイス認証、アカウント確認、実際のアカウント ID の保存方法を学びます。直接この実験を開始する場合は、先にこのラボを完了してください。また、簡単な JavaScript Worker の基本を理解している必要があります。SQL の知識は必要ありません。
この実験では、データベースを作成し、有効なチケットのルールを定義し、ローカルの練習用レコードとクラウド上のレコードを区別します。使い捨ての D1 データベースが 1 つ必要です。デプロイ済みの Worker は使用しません。
自分の学習用アカウントと新しい VM を使用してください。セットアップでは、まず Node.js 22.22.0 を準備し、その後 /home/labex/project/ticket-database でプロジェクト専用の Wrangler 4.131.1 と評価に必要な依存関係を npm install でインストールします。直接依存するバージョンは固定されており、インストール時に専用の lockfile が作成されます。セットアップ中にクラウドへのログインや、評価対象となるデータベース操作は実行されません。個人のマシンでは、プロジェクト内で npm install --save-dev wrangler@4.131.1 を実行して同じ Wrangler バージョンをインストールしてください。
この演習では、D1 Free allowances の範囲内で小規模な合成レコードを使用します。既存のアカウント使用量もこの上限に含まれます。購入済みのドメインは必要ありません。リソースの削除とログアウトの両方を確認するまで、この VM を保持してください。
この VM を認証してアカウントを選択する
このステップでは、新しいターミナルを自分の学習用アカウントに接続します。Dashboard にログインしただけでは、VM は認証されません。D1 の権限によって、データベースの作成、SQL の変更、削除が可能になります。認証する前に、Background Access を含む実際の同意ページを確認してください。
準備済みのプロジェクトを開き、固定されている CLI のバージョンを確認します。
cd /home/labex/project/ticket-database
npx wrangler --version
4.131.1 と表示されることを確認してください。デバイス認証を開始します。--device はブラウザに入力するコードを表示し、--browser=false はブラウザを開くかどうかを自分で選べるようにします。
npx wrangler login --device --browser=false --scopes account:read user:read d1:write
表示された URL をブラウザで開き、現在のコードを入力し、自分の学習用アカウントと権限を確認して認証します。ターミナルに成功メッセージが表示されるまで待ってください。パスワードやトークンをプロジェクトファイルに貼り付けないでください。

この例では、アカウントへのアクセスと必要なバックグラウンドアクセスに加えて、D1 Write が表示されています。認証する前に、選択した学習用アカウントが自分のものであることを確認してください。
npx wrangler whoami --json
loggedIn: true を確認し、アカウントが 1 つだけ表示される場合でも、アカウントの name と id を読み取ってください。使用するアカウントの ID を、次の設定にコピーします。次のシェル変数では、他の学習者との衝突を避けるために、ランダムな 6 バイト(12 個の 16 進数文字)を使用します。ヒアドキュメントによって、JSON 行の間にある JSON が書き込まれます。内部では $RUN が展開されます。
$schema の前のバックスラッシュは、この JSON キーを文字どおり保持します。$RUN は引き続き今回の実行に固有の名前に展開されます。
RUN=labex-c04-d01-$(openssl rand -hex 6)
cat > wrangler.jsonc <<JSON
{
"\$schema": "./node_modules/wrangler/config-schema.json",
"name": "$RUN",
"account_id": "YOUR_ACCOUNT_ID",
"main": "src/index.js",
"compatibility_date": "2026-09-15",
"workers_dev": true,
"preview_urls": false
}
JSON
ブロックを実行する前に、YOUR_ACCOUNT_ID を置き換えてください。RUN が利用できる状態を保つため、このターミナルは開いたままにします。name は今回の実行を識別し、account_id はクラウド操作の対象アカウントを選択します。このファイルは通常の JSON であり、JSONC としても有効です。このファイルを書き込んだだけでは、Worker はデプロイされません。
ローカルにチケットテーブルを作成する
このステップでは、データベースが適用する列とルールである スキーマ を定義します。まずクラウド上のコンテナとそのバインディングを作成しますが、最初の SQL 変更はローカルに限定します。
使い捨てのクラウドデータベースを作成します。--binding DB はアプリケーションコードから参照する短い名前を設定し、--update-config は実際の名前と UUID を wrangler.jsonc に記録し、--use-remote=false は開発環境をローカルに保ちます。
npx wrangler d1 create "$RUN-db" --binding DB --update-config --use-remote=false
作成された名前と ID を読み取り、保存されたバインディングを確認します。
cat wrangler.jsonc
DB エントリには、今回の実行で作成したデータベース名が設定されている必要があります。バインディングは、コードとリソースを接続する設定です。その UUID はクラウドデータベースを識別します。一方、--local を指定すると、この VM 内の別の SQLite データベースが使用されます。SQL コマンドでは、必ず --local または --remote のいずれかを指定してください。
CREATE TABLE はテーブルを定義します。INTEGER PRIMARY KEY は、各行に一意の数値 ID を付与します。TEXT は文字列を保存します。NOT NULL は値の欠落を禁止し、CHECK はルール外の値を拒否します。DEFAULT は、INSERT でそのフィールドが省略された場合に値を設定します。これらのチェックにより、不完全なチケットを防ぎやすくなります。
スキーマと 2 件の合成レコードを SQL ファイルに書き込みます。引用符付きの SQL マーカーにより、シェルが内容を解釈しないようにします。SQL 文はセミコロンで終わります。INSERT INTO では、列名と各行の値を対応させます。
cat > schema.sql <<'SQL'
CREATE TABLE tickets (
id INTEGER PRIMARY KEY,
subject TEXT NOT NULL CHECK(length(trim(subject)) > 0),
status TEXT NOT NULL DEFAULT 'open' CHECK(status IN ('open','closed')),
source TEXT NOT NULL
);
INSERT INTO tickets (id, subject, status, source) VALUES
(1, 'Cannot sign in', 'open', 'seed'),
(2, 'Invoice copy', 'closed', 'seed');
SQL
このファイルをローカルデータベースだけに適用します。
npx wrangler d1 execute DB --local --file schema.sql
コマンドが成功すると、ローカルデータベースで実行されたことが表示されます。これだけでは、リモートデータベースにテーブルが存在することは確認できません。SQLite の PRAGMA table_info を使って列定義を確認します。
npx wrangler d1 execute DB --local --command "PRAGMA table_info(tickets);"
id、subject、status、source が表示されることを確認してください。pk フィールドは主キーを示し、notnull は必須値であることを示します。
ローカルの行を検索、更新、削除する
このステップでは、基本的な SQL を練習し、ローカルだけに存在する目印のレコードを追加します。SELECT は列を選択し、FROM はテーブルを指定し、WHERE は一致する行を絞り込み、ORDER BY は結果の順序を一定にします。
npx wrangler d1 execute DB --local --command "SELECT id, subject FROM tickets WHERE status = 'open' ORDER BY id;"
結果として、チケット 1 の Cannot sign in が表示されます。コマンド全体を囲む二重引用符の内側では、SQL の文字列に単一引用符を使用しています。ローカルの練習用チケットを追加します。
npx wrangler d1 execute DB --local --command "INSERT INTO tickets (id, subject, source) VALUES (3, 'Local rehearsal', 'local');"
UPDATE は一致する行を変更します。実行前に必ず WHERE 条件を確認してください。WHERE を省略すると、すべての行が変更されます。
npx wrangler d1 execute DB --local --command "UPDATE tickets SET status = 'closed' WHERE id = 3;"
無効なステータスを指定して、制約によってデータが保護されることを確認します。
npx wrangler d1 execute DB --local --command "UPDATE tickets SET status = 'lost' WHERE id = 3;"
このコマンドは意図的に失敗させます。認証エラーやネットワークエラーではなく、CHECK constraint failed というメッセージが表示されることを確認してください。行のステータスは closed のままです。使い捨ての行を 1 件作成してから削除します。DELETE は述語に一致する行だけを削除します。
npx wrangler d1 execute DB --local --command "INSERT INTO tickets (id, subject, source) VALUES (4, 'Temporary', 'local'); DELETE FROM tickets WHERE id = 4;"
残りの行を読み取ります。
npx wrangler d1 execute DB --local --command "SELECT id, subject, status, source FROM tickets ORDER BY id;"
ID 1、2、3 が表示されることを確認してください。チケット 3 は closed で、source は local です。チケット 4 は表示されません。失敗した UPDATE によって、有効な行が変更されていないことも確認します。
リモートデータベースに初期データを投入して確認する
このステップでは、同じスキーマをクラウドデータベースに適用し、ローカルでの変更が自動的には反映されていないことを確認します。--remote を指定すると、選択したアカウントのデータベース UUID に対して SQL 文が送信されます。
npx wrangler d1 execute DB --remote --file schema.sql
確認を求められた場合は、このラボ用データベースだけを確認してください。ローカルの練習用行と同じ ID で、データが異なるリモート専用の行を追加します。
npx wrangler d1 execute DB --remote --command "INSERT INTO tickets (id, subject, source) VALUES (3, 'Cloud inbox', 'remote');"
2 つの保存先を明示的に読み取ります。
npx wrangler d1 execute DB --remote --command "SELECT id, subject, status, source FROM tickets ORDER BY id;"
npx wrangler d1 execute DB --local --command "SELECT id, subject, status, source FROM tickets ORDER BY id;"
リモートのチケット 3 は Cloud inbox、open、remote です。ローカルのチケット 3 は Local rehearsal、closed、local のままです。この違いによって、意図した対象を選択できていることが確認できます。
Cloudflare Dashboard で同じアカウントを選択し、Storage & databases → D1 SQLite Database を開きます。今回の実行で作成した正確なデータベース名を見つけ、詳細ページを開いてください。データベース ID が wrangler.jsonc の値と一致することを確認します。利用できる場合は、読み取り専用のテーブルビューで tickets を確認してください。そこでレコードを作成したり編集したりしないでください。行の内容は上記の SQL の結果で確認できます。Metrics のカウントが遅れて表示されても、問題ありません。
データベースを削除する前に、このステップの検証を実行してください。

Explore Data を開き、Studio で tickets を選択します。行を編集せずに確認してください。例のランダムなデータベース名はテスト実行のもので、自分の名前とは異なります。チケット 3 は Cloud inbox、source は remote です。一方、ローカルデータベースには引き続き Local rehearsal、source が local の行があります。
使い捨てリソースを削除する
このステップでは、VM がまだ認証されている間に、このラボで作成したリソースだけを削除します。先にすべての機能確認を完了してください。削除の検証が終わるまで、設定を保持します。
npx wrangler d1 delete DB
プロンプトを確認し、今回の実行で作成したデータベースだけを削除対象として確認します。その後、データベース一覧を表示します。
npx wrangler d1 list --json
成功したレスポンスに、記録しておいたデータベース名と UUID が含まれていないことを確認してください。他のリソースは残っている場合があります。認証エラーやネットワークエラーだけでは削除を確認できません。アクセスを解決し、続行する前に一覧の取得を繰り返してください。ログインしたまま、このステップの検証を実行します。
この VM の認証を終了する
このステップでは、独立した削除確認が成功した後にのみ認証を終了します。ログアウトすると、この VM に保存されている Wrangler の認証情報が削除されます。VM を閉じただけでは、クラウドのクリーンアップにはなりません。
npx wrangler logout
npx wrangler whoami --json
loggedIn: false と表示されることを確認してください。この未認証のクエリは終了コードが 0 以外になる場合があります。構造化されたレスポンスにログアウト済みであることが明示されている場合に限り、それは想定された動作です。検証が完了したら、ラボ環境を閉じてください。
まとめ
サポートチケットデータベースの作成を練習しました。データベースの結果を確認し、選択したアカウントとローカルの状態を明示的に管理し、ログアウトする前に使い捨てのリソースを削除しました。



