blog

Membuat Database SQLite Web Absensi dengan Node.js

Pendahuluan

Tutorial ini akan memandu Anda dalam membuat database SQLite untuk sistem absensi mahasiswa menggunakan Node.js dan library better-sqlite3. Sistem ini dirancang untuk mengelola data pengguna (admin, dosen, mahasiswa), mata kuliah, kelas, dan catatan absensi.

Daftar Isi

  1. Persiapan Project
  2. Instalasi Dependencies
  3. Struktur Database
  4. Penjelasan Kode
  5. Menjalankan Aplikasi

Persiapan Project

Sebelum memulai, pastikan Anda telah menginstall Node.js di komputer Anda. Anda dapat mengecek dengan menjalankan:

node --version
npm --version

Instalasi Dependencies

1. Inisialisasi Project

Buat folder project dan inisialisasi npm:

mkdir web-absensi
cd web-absensi
npm init -y

2. Install Dependencies

Install library yang dibutuhkan:

npm install better-sqlite3 express
npm install --save-dev nodemon

Penjelasan Dependencies:

3. Konfigurasi package.json

File package.json Anda akan terlihat seperti ini:

{
  "name": "web-absensi",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "nodemon index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "type": "commonjs",
  "dependencies": {
    "better-sqlite3": "^12.8.0",
    "express": "^5.2.1"
  },
  "devDependencies": {
    "nodemon": "^3.1.14"
  }
}

Penjelasan Konfigurasi:

Struktur Database

Database ini terdiri dari 8 tabel utama yang saling berelasi:

Diagram Relasi

pengguna (users)
├── mahasiswa (students)
├── dosen (lecturers)

mata_kuliah (courses)

kelas (classes)
├── Foreign Key: mata_kuliah_id
├── Foreign Key: dosen_id

peserta_kelas (class participants)
├── Foreign Key: mahasiswa_id
├── Foreign Key: kelas_id

sesi_absensi (attendance sessions)
├── Foreign Key: kelas_id

absensi (attendance records)
├── Foreign Key: sesi_id
├── Foreign Key: mahasiswa_id

Penjelasan Tabel

  1. pengguna: Menyimpan data semua pengguna sistem (admin, dosen, mahasiswa)
  2. mahasiswa: Data khusus mahasiswa (NIM, program studi, dll)
  3. dosen: Data khusus dosen (NIDN, departemen)
  4. mata_kuliah: Data mata kuliah yang tersedia
  5. kelas: Data kelas perkuliahan
  6. peserta_kelas: Relasi many-to-many antara mahasiswa dan kelas
  7. sesi_absensi: Sesi pertemuan untuk setiap kelas
  8. absensi: Record absensi mahasiswa per sesi

Penjelasan Kode

Berikut adalah penjelasan lengkap untuk setiap bagian kode dalam file index.js:

1. Import Library

const Database = require("better-sqlite3");

Penjelasan:

2. Inisialisasi Database

const db = new Database("absensi.db", { verbose: console.log });

Penjelasan:

3. Mengaktifkan Foreign Keys

db.pragma("foreign_keys = ON");

Penjelasan:

4. Membuat Tabel

Tabel Pengguna

db.exec(`
  CREATE TABLE IF NOT EXISTS pengguna (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    nama TEXT NOT NULL,
    email TEXT UNIQUE NOT NULL,
    password TEXT NOT NULL,
    peran TEXT NOT NULL CHECK(peran IN ('admin', 'dosen', 'mahasiswa')),
    dibuat_pada DATETIME DEFAULT CURRENT_TIMESTAMP,
    diperbarui_pada DATETIME DEFAULT CURRENT_TIMESTAMP
  );
`);

Penjelasan Detail:

Tabel Mahasiswa

db.exec(`
  CREATE TABLE IF NOT EXISTS mahasiswa (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    pengguna_id INTEGER NOT NULL,
    nim TEXT UNIQUE NOT NULL,
    program_studi TEXT,
    angkatan INTEGER,
    FOREIGN KEY (pengguna_id) REFERENCES pengguna(id) ON DELETE CASCADE
  );
`);

Penjelasan Detail:

Tabel Dosen

db.exec(`
  CREATE TABLE IF NOT EXISTS dosen (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    pengguna_id INTEGER NOT NULL,
    nidn TEXT UNIQUE NOT NULL,
    departemen TEXT,
    FOREIGN KEY (pengguna_id) REFERENCES pengguna(id) ON DELETE CASCADE
  );
`);

Penjelasan Detail:

Tabel Mata Kuliah

db.exec(`
  CREATE TABLE IF NOT EXISTS mata_kuliah (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    kode TEXT UNIQUE NOT NULL,
    nama TEXT NOT NULL,
    sks INTEGER NOT NULL
  );
`);

Penjelasan Detail:

Tabel Kelas

db.exec(`
  CREATE TABLE IF NOT EXISTS kelas (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    mata_kuliah_id INTEGER NOT NULL,
    dosen_id INTEGER NOT NULL,
    nama_kelas TEXT NOT NULL,
    semester TEXT NOT NULL,
    tahun_akademik TEXT NOT NULL,
    FOREIGN KEY (mata_kuliah_id) REFERENCES mata_kuliah(id) ON DELETE CASCADE,
    FOREIGN KEY (dosen_id) REFERENCES dosen(id) ON DELETE CASCADE
  );
`);

Penjelasan Detail:

Tabel Peserta Kelas

db.exec(`
  CREATE TABLE IF NOT EXISTS peserta_kelas (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    mahasiswa_id INTEGER NOT NULL,
    kelas_id INTEGER NOT NULL,
    FOREIGN KEY (mahasiswa_id) REFERENCES mahasiswa(id) ON DELETE CASCADE,
    FOREIGN KEY (kelas_id) REFERENCES kelas(id) ON DELETE CASCADE
  );
`);

Penjelasan Detail:

Tabel Sesi Absensi

db.exec(`
  CREATE TABLE IF NOT EXISTS sesi_absensi (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    kelas_id INTEGER NOT NULL,
    pertemuan_ke INTEGER NOT NULL,
    topik TEXT,
    tanggal DATE NOT NULL,
    jam_mulai TIME NOT NULL,
    jam_selesai TIME NOT NULL,
    FOREIGN KEY (kelas_id) REFERENCES kelas(id) ON DELETE CASCADE
  );
`);

Penjelasan Detail:

Tabel Absensi

db.exec(`
  CREATE TABLE IF NOT EXISTS absensi (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    sesi_id INTEGER NOT NULL,
    mahasiswa_id INTEGER NOT NULL,
    status TEXT NOT NULL CHECK(status IN ('hadir', 'izin', 'sakit', 'alpha')),
    waktu_absen DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (sesi_id) REFERENCES sesi_absensi(id) ON DELETE CASCADE,
    FOREIGN KEY (mahasiswa_id) REFERENCES mahasiswa(id) ON DELETE CASCADE
  );
`);

Penjelasan Detail:

5. Membuat Indexes

db.exec(`
  CREATE INDEX IF NOT EXISTS idx_mahasiswa_pengguna ON mahasiswa(pengguna_id);
  CREATE INDEX IF NOT EXISTS idx_dosen_pengguna ON dosen(pengguna_id);
  CREATE INDEX IF NOT EXISTS idx_kelas_mata_kuliah ON kelas(mata_kuliah_id);
  CREATE INDEX IF NOT EXISTS idx_kelas_dosen ON kelas(dosen_id);
  CREATE INDEX IF NOT EXISTS idx_peserta_mahasiswa ON peserta_kelas(mahasiswa_id);
  CREATE INDEX IF NOT EXISTS idx_peserta_kelas ON peserta_kelas(kelas_id);
  CREATE INDEX IF NOT EXISTS idx_sesi_kelas ON sesi_absensi(kelas_id);
  CREATE INDEX IF NOT EXISTS idx_absensi_sesi ON absensi(sesi_id);
  CREATE INDEX IF NOT EXISTS idx_absensi_mahasiswa ON absensi(mahasiswa_id);
`);

Penjelasan Detail:

Index adalah struktur data yang mempercepat pencarian data dalam database. Tanpa index, database harus melakukan full table scan (memeriksa setiap baris).

Mengapa Index Penting?

Index yang Dibuat:

  1. idx_mahasiswa_pengguna: Mempercepat pencarian mahasiswa berdasarkan pengguna_id
  2. idx_dosen_pengguna: Mempercepat pencarian dosen berdasarkan pengguna_id
  3. idx_kelas_mata_kuliah: Mempercepat pencarian kelas berdasarkan mata kuliah
  4. idx_kelas_dosen: Mempercepat pencarian kelas berdasarkan dosen
  5. idx_peserta_mahasiswa: Mempercepat pencarian kelas yang diambil mahasiswa
  6. idx_peserta_kelas: Mempercepat pencarian mahasiswa dalam satu kelas
  7. idx_sesi_kelas: Mempercepat pencarian sesi absensi untuk kelas tertentu
  8. idx_absensi_sesi: Mempercepat pencarian absensi per sesi
  9. idx_absensi_mahasiswa: Mempercepat pencarian riwayat absensi mahasiswa

Best Practice:

6. Menjalankan Query dengan db.exec()

Method db.exec():

Contoh Penggunaan:

// Membuat satu tabel
db.exec(`
  CREATE TABLE IF NOT EXISTS pengguna (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    nama TEXT NOT NULL,
    email TEXT UNIQUE NOT NULL
  );
`);

// Membuat beberapa tabel sekaligus
db.exec(`
  CREATE TABLE IF NOT EXISTS tabel1 (id INTEGER PRIMARY KEY);
  CREATE TABLE IF NOT EXISTS tabel2 (id INTEGER PRIMARY KEY);
  CREATE INDEX IF NOT EXISTS idx_tabel1 ON tabel1(id);
`);

Catatan Penting:

7. Pesan Sukses

console.log("Database tables created successfully!");

Penjelasan:

8. Kode Lengkap File index.js

Berikut adalah kode lengkap yang menggabungkan semua langkah di atas. Anda dapat menyalin kode ini ke file index.js:

const Database = require("better-sqlite3");

// Inisialisasi database dengan opsi verbose untuk melihat query yang dijalankan
const db = new Database("absensi.db", { verbose: console.log });

// Aktifkan foreign keys
db.pragma("foreign_keys = ON");

// Buat semua tabel sekaligus
db.exec(`
  -- Tabel Pengguna
  CREATE TABLE IF NOT EXISTS pengguna (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    nama TEXT NOT NULL,
    email TEXT UNIQUE NOT NULL,
    password TEXT NOT NULL,
    peran TEXT NOT NULL CHECK(peran IN ('admin', 'dosen', 'mahasiswa')),
    dibuat_pada DATETIME DEFAULT CURRENT_TIMESTAMP,
    diperbarui_pada DATETIME DEFAULT CURRENT_TIMESTAMP
  );

  -- Tabel Mahasiswa
  CREATE TABLE IF NOT EXISTS mahasiswa (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    pengguna_id INTEGER NOT NULL,
    nim TEXT UNIQUE NOT NULL,
    program_studi TEXT,
    angkatan INTEGER,
    FOREIGN KEY (pengguna_id) REFERENCES pengguna(id) ON DELETE CASCADE
  );

  -- Tabel Dosen
  CREATE TABLE IF NOT EXISTS dosen (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    pengguna_id INTEGER NOT NULL,
    nidn TEXT UNIQUE NOT NULL,
    departemen TEXT,
    FOREIGN KEY (pengguna_id) REFERENCES pengguna(id) ON DELETE CASCADE
  );

  -- Tabel Mata Kuliah
  CREATE TABLE IF NOT EXISTS mata_kuliah (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    kode TEXT UNIQUE NOT NULL,
    nama TEXT NOT NULL,
    sks INTEGER NOT NULL
  );

  -- Tabel Kelas
  CREATE TABLE IF NOT EXISTS kelas (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    mata_kuliah_id INTEGER NOT NULL,
    dosen_id INTEGER NOT NULL,
    nama_kelas TEXT NOT NULL,
    semester TEXT NOT NULL,
    tahun_akademik TEXT NOT NULL,
    FOREIGN KEY (mata_kuliah_id) REFERENCES mata_kuliah(id) ON DELETE CASCADE,
    FOREIGN KEY (dosen_id) REFERENCES dosen(id) ON DELETE CASCADE
  );

  -- Tabel Peserta Kelas
  CREATE TABLE IF NOT EXISTS peserta_kelas (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    mahasiswa_id INTEGER NOT NULL,
    kelas_id INTEGER NOT NULL,
    FOREIGN KEY (mahasiswa_id) REFERENCES mahasiswa(id) ON DELETE CASCADE,
    FOREIGN KEY (kelas_id) REFERENCES kelas(id) ON DELETE CASCADE
  );

  -- Tabel Sesi Absensi
  CREATE TABLE IF NOT EXISTS sesi_absensi (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    kelas_id INTEGER NOT NULL,
    pertemuan_ke INTEGER NOT NULL,
    topik TEXT,
    tanggal DATE NOT NULL,
    jam_mulai TIME NOT NULL,
    jam_selesai TIME NOT NULL,
    FOREIGN KEY (kelas_id) REFERENCES kelas(id) ON DELETE CASCADE
  );

  -- Tabel Absensi
  CREATE TABLE IF NOT EXISTS absensi (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    sesi_id INTEGER NOT NULL,
    mahasiswa_id INTEGER NOT NULL,
    status TEXT NOT NULL CHECK(status IN ('hadir', 'izin', 'sakit', 'alpha')),
    waktu_absen DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (sesi_id) REFERENCES sesi_absensi(id) ON DELETE CASCADE,
    FOREIGN KEY (mahasiswa_id) REFERENCES mahasiswa(id) ON DELETE CASCADE
  );

  -- Buat indexes untuk performa
  CREATE INDEX IF NOT EXISTS idx_mahasiswa_pengguna ON mahasiswa(pengguna_id);
  CREATE INDEX IF NOT EXISTS idx_dosen_pengguna ON dosen(pengguna_id);
  CREATE INDEX IF NOT EXISTS idx_kelas_mata_kuliah ON kelas(mata_kuliah_id);
  CREATE INDEX IF NOT EXISTS idx_kelas_dosen ON kelas(dosen_id);
  CREATE INDEX IF NOT EXISTS idx_peserta_mahasiswa ON peserta_kelas(mahasiswa_id);
  CREATE INDEX IF NOT EXISTS idx_peserta_kelas ON peserta_kelas(kelas_id);
  CREATE INDEX IF NOT EXISTS idx_sesi_kelas ON sesi_absensi(kelas_id);
  CREATE INDEX IF NOT EXISTS idx_absensi_sesi ON absensi(sesi_id);
  CREATE INDEX IF NOT EXISTS idx_absensi_mahasiswa ON absensi(mahasiswa_id);
`);

console.log("Database tables created successfully!");

// Tutup koneksi database
db.close();

Penjelasan Struktur Kode:

  1. Import Library: Menggunakan require() untuk mengimport better-sqlite3
  2. Inisialisasi Database: Membuat koneksi dengan opsi verbose untuk debugging
  3. Aktifkan Foreign Keys: Menggunakan PRAGMA untuk mengaktifkan constraint
  4. Eksekusi SQL: Menjalankan semua perintah CREATE TABLE dan CREATE INDEX dalam satu db.exec()
  5. Pesan Sukses: Menampilkan konfirmasi setelah selesai
  6. Tutup Koneksi: Menutup koneksi database setelah selesai (opsional untuk script one-time)

Menjalankan Aplikasi

1. Jalankan Script Inisialisasi

node index.js

Atau gunakan nodemon untuk development:

npm run dev

2. Output yang Diharapkan

Anda akan melihat output berupa query SQL yang dijalankan (karena opsi verbose), diikuti dengan pesan:

Database tables created successfully!

3. Verifikasi Database

Setelah script dijalankan, file absensi.db akan dibuat di folder project. Anda bisa membukanya menggunakan:

Struktur File Project

Setelah setup selesai, struktur project Anda:

web-absensi/
├── node_modules/
├── absensi.db           # Database SQLite (dibuat otomatis)
├── diagram.dbml         # Diagram database
├── index.js             # Script inisialisasi database
├── package.json         # Konfigurasi npm
└── package-lock.json    # Lock file dependencies

Kesimpulan

Anda telah berhasil membuat database SQLite untuk sistem absensi mahasiswa dengan:

✅ 8 tabel yang saling berelasi
✅ Foreign key constraints untuk integritas data
✅ Indexes untuk performa optimal
✅ Constraint validasi (CHECK) untuk data yang valid
✅ Auto-increment primary keys
✅ Timestamp otomatis untuk audit trail

Database ini siap digunakan sebagai fondasi untuk aplikasi web absensi yang lebih lengkap!

Referensi

Lisensi

ISC


Dibuat dengan ❤️ untuk pembelajaran Database SQLite dan Node.js