Basit Al Fath

Senin, 20 April 2026

Store Procedure

Definisi: Stored Procedure adalah sekumpulan perintah SQL yang disimpan di dalam database dan dapat dipanggil kembali kapan saja dibutuhkan.

  1. Disimpan permanen di dalam server database, bukan di aplikasi.
  2. Cukup dibuat sekali, bisa dipanggil berkali-kali dari mana saja.
  3. Dieksekusi langsung di server, mengurangi beban jaringan.


Mengapa Harus Pakai Stored Procedure?

keamanan : User tidak perlu akses langsung ke tabel. Hanya bisa akses melalui procedure yang sudah ditentukan.

Performa Lebih Cepat : SQL dicompile sekali dan disimpan. Eksekusi berikutnya jauh lebih cepat dibanding mengirim ulang query.

Mengurangi Traffic Jaringan : Hanya nama procedure dan parameter yang dikirim, bukan seluruh query panjang.


Skenario: Kasir ingin melihat semua varian & harga dari satu jenis alat musik (misal: Gitar).

DELIMITER $$

CREATE PROCEDURE

  cari_varian_alat(

    IN p_nama_alat VARCHAR(100))

BEGIN

  SELECT

    am.nama_alat,

    v.nama_varian,

    v.harga,

    v.stok

  FROM tb_varian_alat_musik v

  JOIN tb_alat_musik am

    ON v.id_alat_musik = am.id

  WHERE am.nama_alat

    LIKE CONCAT('%', p_nama_alat, '%');

END$$

DELIMITER ;



CALL cari_varian_alat('Gitar');


-------------


Skenario: Manajer ingin tahu berapa total transaksi yang sudah ditangani oleh seorang pegawai berdasarkan ID-nya

DELIMITER $$


CREATE PROCEDURE

  total_transaksi_pegawai(

    IN  p_id_pegawai INT,

    OUT p_total      INT)

BEGIN

  SELECT COUNT(*)

  INTO p_total

  FROM tb_header_transaksi

  WHERE id_pegawai = p_id_pegawai;

END$$


DELIMITER ;


-- Memanggil:

CALL total_transaksi_pegawai(2, @hasil);

SELECT @hasil AS total_transaksi;


------


Skenario: Hitung total pendapatan (harga × qty) dari semua transaksi di sebuah cabang berdasarkan ID cabang.


DELIMITER $$


CREATE PROCEDURE

  pendapatan_cabang(

    IN  p_id_cabang  INT,

    OUT p_pendapatan DECIMAL(15,2))

BEGIN

  SELECT SUM(v.harga * dt.qty)

  INTO p_pendapatan

  FROM tb_detail_transaksi dt

  JOIN tb_header_transaksi ht

    ON dt.id_transaksi = ht.id

  JOIN tb_pegawai pg

    ON ht.id_pegawai = pg.id

  JOIN tb_varian_alat_musik v

    ON dt.id_varian_alat_musik = v.id

  WHERE pg.id_cabang = p_id_cabang;

END$$


DELIMITER ;



CALL pendapatan_cabang(1, @hasil);  SELECT @hasil;



----------

Latihan


Buat SP cari_pegawai_cabang dengan parameter IN id_cabang. Tampilkan nama_pegawai dan gaji semua pegawai di cabang tersebut.


DELIMITER $$


CREATE PROCEDURE cari_pegawai_cabang(IN p_id_cabang INT)

BEGIN

    SELECT 

        nama_pegawai,

        gaji

    FROM tb_pegawai

    WHERE id_cabang = p_id_cabang;

END$$


DELIMITER ;


-- Cara memanggil:

CALL cari_pegawai_cabang(1);



-------

Buat SP stok_varian dengan parameter IN id_varian dan OUT p_stok. Kembalikan jumlah stok dari varian alat musik tersebut.


DELIMITER $$


CREATE PROCEDURE stok_varian(

    IN  p_id_varian INT,

    OUT p_stok      INT

)

BEGIN

    SELECT stok

    INTO p_stok

    FROM tb_varian_alat_musik

    WHERE id = p_id_varian;

END$$


DELIMITER ;


-- Cara memanggil:

CALL stok_varian(2, @hasil_stok);

SELECT @hasil_stok AS stok_tersedia;


-------

sp untuk insert tb_cabang

DELIMITER $$

CREATE PROCEDURE insert_cabang(
    IN p_nama_cabang VARCHAR(100),
    IN p_alamat      TEXT,
    IN p_telepon     VARCHAR(20)
)
BEGIN
    INSERT INTO tb_cabang (
        nama_cabang,
        alamat,
        telepon
    )
    VALUES (
        p_nama_cabang,
        p_alamat,
        p_telepon
    );
END$$

DELIMITER ;

-- Cara memanggil:
CALL insert_cabang(
    'Cabang Cirebon',       -- nama_cabang
    'Jl. Asia Afrika No.20', -- alamat
    '022-12345678'          -- telepon
);






Jumat, 17 April 2026

Cara Menginstal dan Menggunakan Tailwind CSS v4 dengan CLI (Step by Step)


Tailwind CSS versi 4 hadir dengan berbagai peningkatan, salah satunya adalah Tailwind CLI yang lebih cepat dan ringan. Pada tutorial ini, kamu akan belajar cara mengintegrasikan Tailwind CSS ke dalam proyek statis (HTML/CSS) hanya dengan beberapa langkah. Cocok untuk pemula yang ingin mencoba utility-first CSS framework tanpa konfigurasi rumit.

Prasyarat

  • Node.js dan npm sudah terinstal di komputer (download di sini)
  • Text editor (VS Code, Sublime, dll.)
  • Terminal/Command Prompt (bawaan OS

Langkah 1: Buat Folder Project

Buka terminal, lalu buat folder baru untuk proyek dan masuk ke dalamnya.

mkdir tailwind-project
cd tailwind-project

Langkah 2: Inisialisasi package.json

Jalankan perintah berikut untuk membuat file package.json. Gunakan opsi -y agar jawaban otomatis default.

npm init -y

File package.json akan terbuat. Nanti kita akan menambahkan script di dalamnya.

Langkah 3: Instal Tailwind CSS dan CLI

Tailwind CSS v4 menyediakan paket @tailwindcss/cli untuk memproses file CSS. Jalankan perintah instalasi berikut:

npm install tailwindcss @tailwindcss/cli

Proses ini akan membuat folder node_modules dan file package-lock.json. Tunggu hingga selesai.

Langkah 4: Buat Struktur Folder dan File CSS Input

Buat folder src (tempat file CSS mentah) dan di dalamnya buat file input.css.

mkdir src

Buat file src/input.css dan isi dengan kode berikut:

@import "tailwindcss";

Baris ini akan mengimpor semua utilitas Tailwind CSS ke dalam file CSS kamu.

Langkah 5: Buat Folder dist dan File index.html

Folder dist akan menjadi tempat hasil akhir (file CSS yang sudah diproses dan HTML kamu). Buat folder dist dan file index.html di dalamnya.

mkdir dist

Buat file dist/index.html dengan kode awal berikut:

<!doctype html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link href="./style.css" rel="stylesheet">
</head>
<body>
  <h1 class="text-3xl font-bold underline">
    Hello world!
  </h1>
</body>
</html>

Perhatikan tag <link> menunjuk ke style.css – ini adalah file CSS output yang akan dihasilkan oleh Tailwind CLI nanti.

Langkah 6: Tambahkan Script "dev" di package.json

Buka file package.json. Di dalam objek "scripts", tambahkan baris berikut:

"dev": "npx @tailwindcss/cli -i ./src/input.css -o ./dist/style.css --watch"

Penjelasan:

-i ./src/input.css : file CSS sumber.

-o ./dist/style.css : file CSS output (yang akan di-link di HTML).

--watch : mode watch, otomatis memproses ulang setiap kali ada perubahan.

Langkah 7: Jalankan Tailwind CLI (Mode Development)

Kembali ke terminal, jalankan perintah:

npm run dev

Setelah dijalankan, secara otomatis akan terbentuk file dist/style.css yang sudah berisi semua utilitas Tailwind. Terminal akan tetap berjalan (watch mode) – setiap kali kamu mengubah input.css atau menambah class baru di HTML, file CSS akan diperbarui.

Langkah 8: Lihat Hasilnya di Browser

Buka file dist/index.html menggunakan browser (klik kanan file → Open with browser, atau drag ke browser). Kamu akan melihat teks "Hello world!" dengan gaya:

Ukuran teks text-3xl

Tebal font-bold

Garis bawah underline

Langkah 9: Mulai Mengembangkan

Sekarang kamu bisa mengedit dist/index.html dan menambahkan class Tailwind lainnya. Contoh:

<div class="max-w-md mx-auto bg-white rounded-xl shadow-md overflow-hidden md:max-w-2xl">
  <div class="p-8">
    <p class="text-sm text-gray-500">Tailwind CSS v4</p>
    <p class="text-lg font-medium text-black">Belajar jadi lebih mudah!</p>
  </div>
</div>

Setiap kali menyimpan file HTML, kamu tidak perlu menjalankan ulang CLI karena --watch akan terus memantau perubahan. Cukup refresh browser.

Struktur Folder Akhir

Setelah semua langkah selesai, proyek kamu akan terlihat seperti ini:

tailwind-project/
├── node_modules/
├── src/
│   └── input.css
├── dist/
│   ├── index.html
│   └── style.css        (dihasilkan otomatis)
├── package.json
└── package-lock.json

Tips Penting

Jangan edit file dist/style.css secara manual – file ini akan ditimpa setiap kali Tailwind CLI berjalan.

Untuk production, kamu perlu meminifikasi CSS. Gunakan perintah:

npx @tailwindcss/cli -i ./src/input.css -o ./dist/style.css --minify

Tambahkan script "build" di package.json untuk memudahkan.

Pastikan dist/style.css sudah di-link dengan benar di HTML. Jika ingin mengubah letak file output, sesuaikan path di tag <link> dan opsi -o.

Kesimpulan

Dengan Tailwind CSS v4 dan CLI, kamu bisa langsung menulis kelas utilitas di HTML tanpa perlu konfigurasi Webpack atau PostCSS. Cara ini sangat cocok untuk proyek kecil, landing page, atau prototyping. Selamat mencoba!

Rabu, 15 April 2026

Membuat Login sederhana dengan JS

 Login sederhana


Struktur Folder :



siswa.json :


[
  {
    "username": "admin",
    "nama": "bintang",
    "password": 12345
  },
  {
    "username": "superadmin",
    "nama": "asep",
    "password": 12345
  }
]


file app.js


let siswa = [];
fetch("siswa.json")
  .then(response => response.json())
  .then(data => {
    siswa = data;
    console.log("Data loaded:", siswa);
  });

// membuat login
function login() {
  let username = document.getElementById("u").value;
  let password = document.getElementById("p").value;

  if (siswa.length === 0) {
    document.getElementById("hasil").innerHTML =
      "Data belum siap, tunggu sebentar...";
    return;
  }

  let ditemukan = false;

  for (let i = 0; i < siswa.length; i++) {
    if (
      siswa[i].username === username &&
      siswa[i].password == password
    ) {
      // document.getElementById("hasil").innerHTML =
      //   "Login berhasil! Selamat datang " + siswa[i].nama;
      sessionStorage.setItem("nama", siswa[i].nama)
      window.location.href = "app/dashboard.html"
      ditemukan = true;
      break;
    }
  }

  if (!ditemukan) {
    document.getElementById("hasil").innerHTML =
      "Username atau password salah!";
  }
}


index.html


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <input type="text" id="u" placeholder="Username">
<input type="password" id="p" placeholder="Password">
<button onclick="login()">Login</button>

<p id="hasil"></p>
<script src="app.js"> </script>
</body>
</html>


app/dashboard.html


<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1 id="judul"></h1>
    <button onclick="logout()">Logout</button>

    <script>
      let namaUser = sessionStorage.getItem("nama");
      if (namaUser) {
        document.getElementById("judul").innerText =
          `Selamat datang ${namaUser} di dashboard`;
      } else {
        window.location.href = "../index.html";
      }
      function logout() {
        sessionStorage.removeItem("nama"); // Hapus item tertentu
        // sessionStorage.clear();         // Atau hapus SEMUA session sekaligus
        window.location.href = "../index.html";
      }
    </script>
  </body>
</html>








Rabu, 04 Maret 2026

DOM pada JavaScript

dom adalah singkatan dari ( document object model )
dimana document html kita dan root document nya itu si html kemudian child nya itu head sama body
, kemudian element element berikutnya itu adalah child dari element berikutnya

jadi dom itu kurang lebih adalah html kita

document.getElementById(id)
document.getElementsByTagName(tagname)
document.getElementsByClassName(classname)
document.querySelector(id|tagname|classname)

outerHTML = untukmenampilkan tag nya
textContent = untuk menampilkan isi text nya

 
// mendapatkan html - finding HTML Element
<section>
<div></div>
<div id="div-2"></div>
<div class="div-1"></div>
</section>
// let el = document.getElementById("div-2");
// let el = document.getElementsByTagName("div")
// console.log(el[0]);
// let el = document.getElementsByClassName("div-1")
// console.log(el[0]);

// let el = document.querySelector("#div-2");
// let el = document.querySelector(".div-1");
// let el = document.querySelector("div");
// document.querySelectorAll(".divClass").forEach(el => {
  el.innerHTML = "isi baru";
});

 

// merubah html

// let el = document.querySelector(".div-1");
// console.log(el);
// el.innerHTML = "<p> Hello World </p>"

// let input = document.getElementById("input");
// console.log(input);

// input.setAttribute("type", "checkbox")

// let input = document.getElementById("input");
// console.log(input);
// input.style.borderColor = 'red'
// input.style.color = 'red'

adding and deleting element

// membuat dan menghapus element
//buat element
// const pElement = document.createElement("p");
// const divEl = document.getElementById("div-2");

// // menambah element child
// divEl.appendChild(pElement);
// pElement.innerHTML = "hello world";

// // hapus element child
// divEl.removeChild(pElement);

DOM EVENT


// DOM EVENT
// ketika kejadian terjadi apa yang terjadi

// const hello = document.getElementById("hello");
// hello.addEventListener("mouseenter", function () {
//   // console.log("hallo dari mouse enter");
//   hello.style.border = "1px solid blue"
// });


<p id="p">hallo sorot saya</p>
    <button onclick="btnclick()">Ini Button</button>
    <p id="boom" style="display: none;">BOOM</p>
    <p onmouseenter="addborder(this)">enter</p>


let sorot = document.getElementById("p")
sorot.addEventListener("mouseenter", function () {
  sorot.style.border = "1px solid blue"
})

function btnclick() {
  const boom = document.getElementById("boom")
  boom.style.display = "block"
}

function addborder(el) {
  el.style.border = "1px solid black"
}



<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Data JSON</title>
</head>

<body>

<h1>Data Crypto Trending</h1>
<div id="output"></div>
<div id="detail"></div>
<script src="app.js"></script>

</body>
</html>


let hasil = "";
let api = "https://api.coingecko.com/api/v3/search/trending";
fetch(api) // ambil data
  .then((response) => response.json()) // membuka datanya
  .then((data) => {
    // simpan datanya untuk di tampilkan
    data.coins.forEach((element, index) => {
      const item = element.item;
      hasil += `
    <img src="${item.thumb}" alt="thumb">
    <p>
      nama :  ${element.item.name} <br>
      simbol :  ${element.item.symbol} <br>
      rank :  ${element.item.market_cap_rank}
    </p>
          <button onclick="showDetail(${index})">
            Lihat Detail
          </button>
    <hr>
    `;
    });

    document.getElementById("output").innerHTML = hasil;

    // simpan data global
    window.cryptoData = data.coins;
  });

function showDetail(index) {
  document.getElementById("output").innerHTML = "";
  const coin = cryptoData[index].item;

  let detail = `
  <button onclick="backToList()">⬅ Kembali</button>
    <h3>${coin.name}</h3>
    <img src="${coin.large}" width="100">

    <p>Symbol : ${coin.symbol}</p>
    <p>Rank : ${coin.market_cap_rank}</p>
    <p>Harga USD : $${coin.data.price}</p>
    <p>Market Cap : ${coin.data.market_cap}</p>
  `;

  document.getElementById("detail").innerHTML = detail;
}

function backToList(){

  document.getElementById("detail").innerHTML = "";

  document.getElementById("output").innerHTML = hasil;

}

Minggu, 01 Maret 2026

TRIGGER Pada SQL


BEFORE INSERT



// Nama pegawai tidak boleh kosong

DELIMITER //

CREATE TRIGGER before_insert_pegawai_nama
BEFORE INSERT ON tb_pegawai
FOR EACH ROW
BEGIN
    IF NEW.nama_pegawai = '' THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'Nama pegawai tidak boleh kosong!';
    END IF;
END //
DELIMITER ;


Gaji minimal 1.000.000

DELIMITER //

CREATE TRIGGER before_insert_pegawai_gaji
BEFORE INSERT ON tb_pegawai
FOR EACH ROW
BEGIN
    IF NEW.gaji < 1000000 THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'Gaji minimal 1 juta!';
    END IF;
END //

DELIMITER ;


Tidak boleh beli jika stok kurang


DELIMITER //

CREATE TRIGGER before_insert_detail_stok
BEFORE INSERT ON tb_detail_transaksi
FOR EACH ROW
BEGIN
    DECLARE sisa_stok INT;

    SELECT stok INTO sisa_stok
    FROM tb_varian_alat_musik
    WHERE id = NEW.id_varian_alat_musik;

    IF sisa_stok < NEW.qty THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'Stok tidak mencukupi!';
    END IF;
END //

DELIMITER ;


Nama cabang tidak boleh sama

DELIMITER //

CREATE TRIGGER before_insert_cabang_unik
BEFORE INSERT ON tb_cabang
FOR EACH ROW
BEGIN
    DECLARE jumlah INT;

    SELECT COUNT(*) INTO jumlah
    FROM tb_cabang
    WHERE nama_cabang = NEW.nama_cabang;

    IF jumlah > 0 THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'Nama cabang sudah ada!';
    END IF;
END //

DELIMITER ;

AFTER INSERT


AFTER INSERT Membuat Log Otomatis

Setiap ada pegawai baru, sistem mencatat ke tabel log.

buat dulu table baru log :

CREATE TABLE tb_log_pegawai (
    id INT AUTO_INCREMENT PRIMARY KEY,
    id_pegawai INT,
    keterangan VARCHAR(255),
    waktu DATETIME
);

buat triger after insert nya :
DELIMITER //

CREATE TRIGGER after_insert_pegawai_log
AFTER INSERT ON tb_pegawai
FOR EACH ROW
BEGIN
    INSERT INTO tb_log_pegawai (id_pegawai, keterangan, waktu)
    VALUES (NEW.id, 'Pegawai baru ditambahkan', NOW());
END //

DELIMITER ;


AFTER INSERT Mengurangi Stok (Real Case)

Setiap detail transaksi ditambahkan → stok langsung berkurang.

DELIMITER //

CREATE TRIGGER after_insert_detail_kurangi_stok
AFTER INSERT ON tb_detail_transaksi
FOR EACH ROW
BEGIN
    UPDATE tb_varian_alat_musik
    SET stok = stok - NEW.qty
    WHERE id = NEW.id_varian_alat_musik;
END //

DELIMITER ;



BEFORE UPDATE

Nama pegawai tidak boleh diubah menjadi kosong

DELIMITER //

CREATE TRIGGER before_update_pegawai_nama
BEFORE UPDATE ON tb_pegawai
FOR EACH ROW
BEGIN
    IF NEW.nama_pegawai = '' THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'Nama pegawai tidak boleh kosong!';
    END IF;
END //

DELIMITER ;


📌 Konsep yang dipelajari

  • NEW = data yang akan diubah

  • BEFORE UPDATE = dijalankan sebelum perubahan terjadi



Gaji tidak boleh diupdate kurang dari 1 juta

DELIMITER //

CREATE TRIGGER before_update_gaji
BEFORE UPDATE ON tb_pegawai
FOR EACH ROW
BEGIN
    IF NEW.gaji < 1000000 THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'Gaji tidak boleh kurang dari 1 juta!';
    END IF;
END //

DELIMITER ;




Membandingkan OLD dan NEW

Gaji tidak boleh diturunkan.

DELIMITER //

CREATE TRIGGER before_update_gaji_turun
BEFORE UPDATE ON tb_pegawai
FOR EACH ROW
BEGIN
    IF NEW.gaji < OLD.gaji THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'Gaji tidak boleh diturunkan!';
    END IF;
END //

DELIMITER ;


📌 Konsep Penting

KeywordArtinya
OLD.gajigaji sebelum diubah
NEW.gajigaji setelah diubah



Tanggal lahir tidak boleh lebih dari hari ini.


DELIMITER //

CREATE TRIGGER before_update_tgllahir
BEFORE UPDATE ON tb_pegawai
FOR EACH ROW
BEGIN
    IF NEW.tanggal_lahir > CURDATE() THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'Tanggal lahir tidak valid!';
    END IF;
END //

DELIMITER ;

Konsep yang dipelajari
Function CURDATE().




Validasi Stok Saat Update Transaksi (Menengah)

Jika qty diubah, stok harus tetap mencukupi.

DELIMITER //

CREATE TRIGGER before_update_qty_transaksi
BEFORE UPDATE ON tb_detail_transaksi
FOR EACH ROW
BEGIN
    DECLARE stok_barang INT;

    SELECT stok INTO stok_barang
    FROM tb_varian_alat_musik
    WHERE id = NEW.id_varian_alat_musik;

    IF stok_barang < NEW.qty THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'Stok tidak mencukupi untuk update!';
    END IF;

END //

DELIMITER ;



AFTER UPDATE = dijalankan setelah data berhasil diubah


Jika gaji pegawai diubah, sistem otomatis menambahkan bonus 100.000.

DELIMITER //

CREATE TRIGGER after_update_gaji_bonus
AFTER UPDATE ON tb_pegawai
FOR EACH ROW
BEGIN
    UPDATE tb_pegawai
    SET gaji = gaji + 100000
    WHERE id = NEW.id;
END //

DELIMITER ;



Sekarang mulai masuk otomatisasi sistem.

🎯 Kasus

Jika data pegawai diubah, sistem mencatat ke tabel log.

Buat tabel log :

CREATE TABLE tb_log_update_pegawai (
    id INT AUTO_INCREMENT PRIMARY KEY,
    id_pegawai INT,
    keterangan VARCHAR(255),
    waktu DATETIME
);

DELIMITER //

CREATE TRIGGER after_update_pegawai_log
AFTER UPDATE ON tb_pegawai
FOR EACH ROW
BEGIN
    INSERT INTO tb_log_update_pegawai(id_pegawai, keterangan, waktu)
    VALUES (NEW.id, 'Data pegawai telah diupdate', NOW());
END //

DELIMITER ;


📌 Konsep yang dipelajari

  • INSERT ke tabel lain

  • fungsi NOW()



BEFORE DELETE = dijalankan sebelum data dihapus

"BEFORE DELETE seperti satpam yang memeriksa sebelum barang dibuang."

Misalnya:

  • barang masih ada stok

  • masih dipakai transaksi

  • masih dipakai pegawai

maka tidak boleh dihapus.


Pegawai dengan gaji lebih dari 10 juta tidak boleh dihapus.


DELIMITER //

CREATE TRIGGER before_delete_pegawai
BEFORE DELETE ON tb_pegawai
FOR EACH ROW
BEGIN
    IF OLD.gaji > 10000000 THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'Pegawai dengan gaji tinggi tidak boleh dihapus!';
    END IF;
END //

DELIMITER ;

📌 Konsep yang dipelajari

KeywordArti
OLDdata sebelum dihapus

Karena saat delete tidak ada NEW, hanya ada OLD.



Pegawai tidak boleh dihapus jika masih memiliki transaksi.

DELIMITER //

CREATE TRIGGER before_delete_pegawai_transaksi
BEFORE DELETE ON tb_pegawai
FOR EACH ROW
BEGIN
    DECLARE jumlah INT;

    SELECT COUNT(*) INTO jumlah
    FROM tb_header_transaksi
    WHERE id_pegawai = OLD.id;

    IF jumlah > 0 THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'Pegawai tidak bisa dihapus karena masih memiliki transaksi!';
    END IF;

END //

DELIMITER ;




Cabang tidak boleh dihapus jika masih memiliki pegawai.

DELIMITER //

CREATE TRIGGER before_delete_cabang
BEFORE DELETE ON tb_cabang
FOR EACH ROW
BEGIN
    DECLARE jumlah_pegawai INT;

    SELECT COUNT(*) INTO jumlah_pegawai
    FROM tb_pegawai
    WHERE id_cabang = OLD.id;

    IF jumlah_pegawai > 0 THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'Cabang tidak bisa dihapus karena masih memiliki pegawai!';
    END IF;

END //

DELIMITER ;


Varian alat musik tidak boleh dihapus jika stok masih ada.

DELIMITER //

CREATE TRIGGER before_delete_varian
BEFORE DELETE ON tb_varian_alat_musik
FOR EACH ROW
BEGIN
    IF OLD.stok > 0 THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'Varian tidak bisa dihapus karena stok masih tersedia!';
    END IF;
END //

DELIMITER ;




AFTER DELETE = dijalankan setelah data benar-benar dihapus


Biasanya dipakai untuk:

mencatat log
mengembalikan stok
membersihkan atau menyesuaikan data lain
Saat DELETE hanya tersedia OLD, karena data baru tidak ada.


Jika detail transaksi dihapus → stok barang dikembalikan.

DELIMITER //

CREATE TRIGGER after_delete_detail_transaksi
AFTER DELETE ON tb_detail_transaksi
FOR EACH ROW
BEGIN
    UPDATE tb_varian_alat_musik
    SET stok = stok + OLD.qty
    WHERE id = OLD.id_varian_alat_musik;
END //

DELIMITER ;