Skip to content

İlk Veritabanını Oluşturma

Bu dersi tamamladıktan sonra:

  • D1’de ilk veritabanınızı oluşturabileceksiniz
  • Tablo oluşturma ve schema tasarımı yapabileceksiniz
  • Veri ekleme ve temel CRUD işlemlerini yapabileceksiniz
  • Wrangler ile D1 yönetimini öğreneceksiniz
  1. Proje Kurulumu
  2. Veritabanı Oluşturma
  3. Tablo Tasarımı ve Oluşturma
  4. Veri Ekleme
  5. Temel Sorgular
  6. Pratik Proje

İlk olarak, yeni bir Workers projesi oluşturalım:

Terminal window
# Yeni proje oluştur
npm create cloudflare@latest my-d1-app
# Proje dizinine git
cd my-d1-app
# Bağımlılıkları yükle
npm install

Proje oluşturma sırasında size birkaç soru sorulacak:

  • Project type: “Hello World” Worker seçin
  • TypeScript: Evet seçin (önerilir)
  • Deploy: Hayır seçin (önce yerel test edeceğiz)

wrangler.toml dosyası oluşturulacak. Bu dosya projenizin yapılandırmasını içerir:

name = "my-d1-app"
main = "src/index.ts"
compatibility_date = "2024-01-01"

Yeni bir D1 veritabanı oluşturalım:

Terminal window
npx wrangler d1 create users-db

Çıktı:

✅ Successfully created DB 'users-db' in region WEUR
Created your new D1 database.
[[d1_databases]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "users-db"
database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

wrangler.toml dosyasına D1 binding ekleyelim:

name = "my-d1-app"
main = "src/index.ts"
compatibility_date = "2024-01-01"
[[d1_databases]]
binding = "DB"
database_name = "users-db"
database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

Binding Nedir? Binding, Worker kodunuzda D1 veritabanına erişmek için kullandığınız bir referanstır. env.DB ile erişebilirsiniz.


Basit bir kullanıcı yönetim sistemi için şu tabloları oluşturalım:

CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT NOT NULL UNIQUE,
username TEXT NOT NULL UNIQUE,
first_name TEXT,
last_name TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE posts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
title TEXT NOT NULL,
content TEXT,
published BOOLEAN DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);

Projenizde schema klasörü oluşturalım ve schema SQL dosyamızı ekleyelim:

Terminal window
mkdir schema

schema/001_initial.sql dosyası oluşturalım:

-- schema/001_initial.sql
-- Users tablosu
DROP TABLE IF EXISTS users;
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT NOT NULL UNIQUE,
username TEXT NOT NULL UNIQUE,
first_name TEXT,
last_name TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- Posts tablosu
DROP TABLE IF EXISTS posts;
CREATE TABLE posts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
title TEXT NOT NULL,
content TEXT,
published BOOLEAN DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);
-- Indexler
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_username ON users(username);
CREATE INDEX idx_posts_user_id ON posts(user_id);

Schema’yı local ve remote D1 veritabanına uygulayalım:

Terminal window
# Local veritabanına uygula
npx wrangler d1 execute users-db --local --file=./schema/001_initial.sql
# Remote (production) veritabanına uygula
npx wrangler d1 execute users-db --remote --file=./schema/001_initial.sql

Komut satırından veri ekleyelim:

Terminal window
# Users tablosuna veri ekle
npx wrangler d1 execute users-db --local --command \
"INSERT INTO users (email, username, first_name, last_name) VALUES \
('[email protected]', 'ahmet', 'Ahmet', 'Yılmaz'), \
('[email protected]', 'ayse', 'Ayşe', 'Demir'), \
('[email protected]', 'mehmet', 'Mehmet', 'Kaya')"
# Posts tablosuna veri ekle
npx wrangler d1 execute users-db --local --command \
"INSERT INTO posts (user_id, title, content, published) VALUES \
(1, 'İlk Blog Yazım', 'Merhaba dünya! Bu ilk blog yazım.', 1), \
(2, 'TypeScript Tips', 'TypeScript kullanmanın avantajları...', 1), \
(1, 'Cloudflare Workers', 'Workers ile serverless development...', 0)"

data/seed.sql dosyası oluşturalım:

-- data/seed.sql
INSERT INTO users (email, username, first_name, last_name) VALUES
('[email protected]', 'ahmet', 'Ahmet', 'Yılmaz'),
('[email protected]', 'ayse', 'Ayşe', 'Demir'),
('[email protected]', 'mehmet', 'Mehmet', 'Kaya'),
('[email protected]', 'zeynep', 'Zeynep', 'Çelik'),
('[email protected]', 'can', 'Can', 'Yıldız');
INSERT INTO posts (user_id, title, content, published) VALUES
(1, 'İlk Blog Yazım', 'Merhaba dünya! Bu ilk blog yazım.', 1),
(2, 'TypeScript Tips', 'TypeScript kullanmanın avantajları...', 1),
(1, 'Cloudflare Workers', 'Workers ile serverless development...', 0),
(3, 'React Hooks', 'React Hooks kullanımı hakkında her şey...', 1),
(2, 'CSS Grid', 'CSS Grid ile modern layoutlar...', 1);

Verileri içe aktaralım:

Terminal window
npx wrangler d1 execute users-db --local --file=./data/seed.sql

Terminal window
# Tüm kullanıcıları getir
npx wrangler d1 execute users-db --local --command "SELECT * FROM users"
# Sadece email ve username getir
npx wrangler d1 execute users-db --local --command \
"SELECT email, username FROM users"
# Belirli bir koşula göre filtrele
npx wrangler d1 execute users-db --local --command \
"SELECT * FROM users WHERE username = 'ahmet'"
# Sıralama
npx wrangler d1 execute users-db --local --command \
"SELECT * FROM users ORDER BY created_at DESC"
# Limit ve Offset
npx wrangler d1 execute users-db --local --command \
"SELECT * FROM users LIMIT 5 OFFSET 2"
Terminal window
# Users ve Posts tablolarını birleştir
npx wrangler d1 execute users-db --local --command \
"SELECT users.username, posts.title FROM posts
JOIN users ON posts.user_id = users.id"
# LEFT JOIN
npx wrangler d1 execute users-db --local --command \
"SELECT users.username, COUNT(posts.id) as post_count
FROM users
LEFT JOIN posts ON users.id = posts.user_id
GROUP BY users.id"
Terminal window
# Bir kullanıcıyı güncelle
npx wrangler d1 execute users-db --local --command \
"UPDATE users SET first_name = 'Ahmet Can' WHERE username = 'ahmet'"
# Birden fazla alanı güncelle
npx wrangler d1 execute users-db --local --command \
"UPDATE posts SET published = 1, updated_at = CURRENT_TIMESTAMP
WHERE id = 3"
Terminal window
# Bir post'u sil
npx wrangler d1 execute users-db --local --command \
"DELETE FROM posts WHERE id = 4"
# Belirli bir koşula göre sil
npx wrangler d1 execute users-db --local --command \
"DELETE FROM posts WHERE published = 0"

src/index.ts dosyasını oluşturalım:

export interface Env {
DB: D1Database;
}
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
const url = new URL(request.url);
const path = url.pathname;
// Tüm kullanıcıları listele
if (path === "/users") {
const { results } = await env.DB.prepare(
"SELECT * FROM users ORDER BY created_at DESC"
).all();
return Response.json(results);
}
// Belirli bir kullanıcıyı getir
if (path.startsWith("/users/")) {
const username = path.split("/")[2];
const { results } = await env.DB.prepare(
"SELECT * FROM users WHERE username = ?"
)
.bind(username)
.all();
if (results.length === 0) {
return Response.json({ error: "User not found" }, { status: 404 });
}
return Response.json(results[0]);
}
// Yeni kullanıcı oluştur
if (path === "/users" && request.method === "POST") {
const body = await request.json();
const result = await env.DB.prepare(
"INSERT INTO users (email, username, first_name, last_name) VALUES (?, ?, ?, ?)"
)
.bind(body.email, body.username, body.first_name, body.last_name)
.run();
return Response.json({
success: result.success,
id: result.meta.last_row_id
}, { status: 201 });
}
// Tüm post'ları listele
if (path === "/posts") {
const { results } = await env.DB.prepare(`
SELECT posts.*, users.username
FROM posts
JOIN users ON posts.user_id = users.id
ORDER BY posts.created_at DESC
`).all();
return Response.json(results);
}
return Response.json({
message: "D1 API",
endpoints: ["/users", "/users/:username", "/posts"]
});
},
};
Terminal window
# Local development server'ı başlat
npm run dev
# Başka bir terminal'de test et
curl http://localhost:8787/users
curl http://localhost:8787/users/ahmet
curl http://localhost:8787/posts
# POST isteği
curl -X POST http://localhost:8787/users \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","username":"test","first_name":"Test","last_name":"User"}'

  • ✅ Migration dosyalarını versiyon kontrolüne alın
  • ✅ Her değişikliği ayrı bir migration dosyasında tutun
  • ✅ Local ve remote’da aynı schema’yı kullanın
  • ✅ Sık sorgulanan sütunlara index ekleyin
  • ✅ Foreign key’lere index ekleyin
  • ❌ Gereksiz indexlerden kaçının (write performance etkiler)
  • ✅ Uygun veri tiplerini kullanın (TEXT, INTEGER, REAL)
  • ✅ NULL constraints kullanın
  • ✅ UNIQUE constraints ile veri bütünlüğünü sağlayın
  • ❌ Asla SQL injection’e açık kod yazmayın
  • ✅ Her zaman prepared statements kullanın
  • ✅ Param binding kullanın

Bu derste aşağıdaki konuları öğrendiniz:

✅ Workers projesi kurulumu ✅ D1 veritabanı oluşturma ✅ Tablo tasarımı ve schema oluşturma ✅ Veri ekleme ve temel CRUD işlemleri ✅ Worker ile D1 entegrasyonu ✅ Local development ve test

Bir sonraki dersimizde “Temel SQL Komutları” başlığı altında:

  • Detaylı SELECT sorguları
  • JOIN çeşitleri ve kullanımı
  • Aggregation fonksiyonları
  • Subquery’ler konularını inceleyeceğiz.
  1. D1 binding nedir ve neden kullanılır?
  2. Schema tasarımı yaparken nelere dikkat etmelisiniz?
  3. Foreign key constraint nedir ve nasıl kullanılır?
  4. Local ve remote veritabanı arasındaki fark nedir?
  5. Worker kodunda D1’e nasıl erişirsiniz?

Ders Süresi: 60 dakika Zorluk Seviyesi: Başlangıç Ön Koşullar: Ders 2: D1’e Giriş