База D1
Серверная база SQLite для функций — миграции, SQL-запросы из кода, импорт данных и лимиты. Всё с примерами.
D1 — серверная база SQLite, встроенная в функции. Это те же таблицы, столбцы, индексы и язык SQL, что в обычном SQLite: база живёт рядом с функцией и доступна ей по имени, без строк подключения. Одна функция может иметь несколько баз.
Для данных «положил — прочитал» без связей проще KV, для объекта с собственным состоянием — Durable Objects.
Объявление
Заголовок раздела «Объявление»База объявляется в wrangler.jsonc в списке d1_databases:
{ "d1_databases": [ { "binding": "DB", "database_name": "app-db", "database_id": "00000000-0000-0000-0000-000000000001" } ]}binding— имя переменной, под которой база видна в коде:env.DB.database_name— имя, которое вы указываете в командах CLI.database_id— уникальный идентификатор базы (UUID). У каждой базы свой; задаётся при создании и больше не меняется.
Миграции
Заголовок раздела «Миграции»Схему базы ведут миграции — SQL-файлы с порядковым номером в каталоге migrations/.
Каждая миграция применяется ровно один раз, по порядку номеров.
migrations/├── 0001_users.sql└── 0002_posts.sql0001_users.sql:
CREATE TABLE users ( id INTEGER PRIMARY KEY, email TEXT NOT NULL UNIQUE, created_at TEXT NOT NULL DEFAULT (datetime('now')));0002_posts.sql:
CREATE TABLE posts ( id INTEGER PRIMARY KEY, user_id INTEGER NOT NULL REFERENCES users(id), body TEXT NOT NULL);Применить новые миграции — из каталога проекта:
webshield apps d1 migrate --app api app-dbapp-db здесь — это database_name из конфига. Команда упаковывает каталог проекта и
применяет к базе миграции, которых ещё не было. Посмотреть, какие уже применены:
webshield apps d1 migrations --app api app-dbИмя миграции (0001_users.sql) в базу не попадает — важно только содержимое и порядок.
Уже применённый файл не стоит править: правка не откатится, а рассинхронизирует историю.
Нужно изменение — добавляйте новую миграцию со следующим номером.
Запросы из кода
Заголовок раздела «Запросы из кода»В коде база доступна как env.<binding>. Запросы идут через prepare с параметрами — так
безопасно: значения подставляются как данные, а не как часть SQL.
export default { async fetch(request, env) { const url = new URL(request.url);
// Создать пользователя if (url.pathname === "/users" && request.method === "POST") { const { email } = await request.json(); const { meta } = await env.DB .prepare("INSERT INTO users (email) VALUES (?1)") .bind(email) .run(); return Response.json({ id: meta.last_row_id }, { status: 201 }); }
// Список пользователей if (url.pathname === "/users") { const { results } = await env.DB .prepare("SELECT id, email FROM users ORDER BY id") .all(); return Response.json(results); }
// Один пользователь по id const id = url.pathname.split("/")[2]; const user = await env.DB .prepare("SELECT id, email FROM users WHERE id = ?1") .bind(id) .first(); return user ? Response.json(user) : Response.json({ error: "not found" }, { status: 404 }); },};Методы:
prepare(sql).bind(...).run()— запрос, меняющий данные (INSERT,UPDATE,DELETE,CREATE). Возвращаетmetaсо сведениями вродеlast_row_id.prepare(sql).bind(...).all()— выборка; возвращает{ results }— массив строк.prepare(sql).bind(...).first()— первая строка выборки илиnull..raw()— выборка колонок как есть, без ключей-имён.
Параметры — всегда через ?1, ?2, … и .bind(...). Никогда не склеивайте SQL из строк
запроса: "SELECT * FROM users WHERE id = " + id пропустит SQL-инъекцию.
SQL вне кода
Заголовок раздела «SQL вне кода»Разовые запросы и заливку данных делают командой execute — она не требует, чтобы запрос
жил в миграции:
# Запрос одной строкойwebshield apps d1 execute --app api app-db --command "SELECT count(*) FROM users"
# Или SQL из файла (например, seed.sql)webshield apps d1 execute --app api app-db --file seed.sqlseed.sql:
INSERT INTO users (email) VALUES ('anna@example.com'), ('boris@example.com');Один запрос — до 100 КБ. Большие наборы данных оформляйте миграциями, а не одной командой
execute.
Когда что использовать
Заголовок раздела «Когда что использовать»- Миграции — схема базы: таблицы, индексы. Меняются редко, применяются по порядку и отслеживаются.
execute— разовые операции: залить стартовые данные, проверить состояние, поправить строку.prepareв коде — всё, что делает сама функция на запросах посетителей.
Тонкости
Заголовок раздела «Тонкости»- Функция должна быть уже выкачена — команды выполняются на её узлах и ходят к базе рядом с ними.
- Миграции повторяются сами, если связь с функцией оборвалась: они учитывают
применённые, повтор безопасен.
executeне повторяется — запрос мог успеть выполниться, поэтому проверьте результат и запустите снова, если нужно. - История и вывод всех операций — во вкладке Данные.
- Возврат к моменту возвращает и базу D1: вкладка Данные → Вернуть данные к моменту. Подробнее — в Функциях.