Stored Procedures, Functions, Triggers & Events

এতদিন আমরা ডেটাবেসকে শুধু ডেটা রাখার স্টোর হিসেবে ব্যবহার করেছি। লজিক সব ছিল আমাদের ব্যাকএন্ড কোডে (PHP/Node.js)। কিন্তু MySQL নিজেই একটি শক্তিশালী প্রোগ্রামিং ল্যাঙ্গুয়েজ সাপোর্ট করে। আপনি চাইলে লুপিং, কন্ডিশন এবং অটোমেশন সরাসরি ডেটাবেসের ভেতরেই করতে পারেন।

এই অধ্যায়ে আমরা শিখব কীভাবে ডেটাবেসকে দিয়ে অটোমেটিক কাজ করানো যায়

১০.১ Stored Procedure (SP) — ডেটাবেসের নিজস্ব ফাংশন

Stored Procedure হলো অনেকগুলো SQL কুয়েরির একটি বান্ডিল, যা ডেটাবেসে সেভ করা থাকে। আপনি বারবার ১০টা কুয়েরি না লিখে শুধু এই প্রসিডিউরটিকে কল করবেন।

কেন ব্যবহার করবেন?

  • Network Traffic কমায়: অ্যাপ থেকে ১০ বার রিকোয়েস্ট না পাঠিয়ে একবার কল করলেই হয়।
  • Security: ইউজারকে টেবিল এক্সেস না দিয়ে শুধু প্রসিডিউর এক্সেস দেওয়া যায়।
  • Performance: এটি সার্ভারে প্রি-কম্পাইলড অবস্থায় থাকে, তাই দ্রুত রান করে।

১০.২ প্রসিডিউর তৈরির নিয়ম (Syntax)

এখানে DELIMITER খুব গুরুত্বপূর্ণ। সাধারণত ; দেখলে MySQL ভাবে কুয়েরি শেষ। কিন্তু প্রসিডিউরের ভেতরেও ; থাকে। তাই আমরা সাময়িকভাবে DELIMITER চেঞ্জ করে $$ বা // দিই, যাতে MySQL কনফিউজড না হয়।

Basic Structure:

DELIMITER $$

CREATE PROCEDURE getUsers()
BEGIN
  SELECT * FROM users;
END $$

DELIMITER ;

Run করা:

CALL getUsers();

১০.৩ Stored Procedure with Parameters

ফাংশনের মতো এখানেও প্যারামিটার পাস করা যায়। ৩ ধরণের প্যারামিটার আছে:

১. IN (ইনপুট নেওয়া)

বাইরে থেকে ডেটা নিয়ে ভেতরে কাজ করবে।

DELIMITER $$
CREATE PROCEDURE getUserByCity(IN cityName VARCHAR(50))
BEGIN
  SELECT * FROM users WHERE city = cityName;
END $$
DELIMITER ;

-- কল করা
CALL getUserByCity('Dhaka');

২. OUT (আউটপুট বা রিটার্ন করা)

এটি কোনো ডেটা রিটার্ন করে ভেরিয়েবলে রাখে।

DELIMITER $$
CREATE PROCEDURE getUserCount(OUT total INT)
BEGIN
  SELECT COUNT(*) INTO total FROM users;
END $$
DELIMITER ;

-- কল করা এবং ভ্যালু দেখা
CALL getUserCount(@myTotal);
SELECT @myTotal;

৩. INOUT (উভমুখী)

এটি ভ্যালু নিয়ে কাজ করে আবার আপডেট করে ফেরত দেয়।

DELIMITER $$
CREATE PROCEDURE addValue(INOUT x INT)
BEGIN
  SET x = x + 10;
END $$
DELIMITER ;

SET @num = 5;
CALL addValue(@num);
SELECT @num; -- আউটপুট হবে 15

১০.৪ Control Flow (Logic inside Database)

ডেটাবেসের ভেতরেই প্রোগ্রামিং লজিক লেখা যায়।

IF-ELSE:

IF price > 1000 THEN
   SET category = 'Premium';
ELSE
   SET category = 'Regular';
END IF;

WHILE Loop:

WHILE counter < 10 DO
  INSERT INTO logs (message) VALUES ('Looping...');
  SET counter = counter + 1;
END WHILE;

১০.৫ User-Defined Function (UDF)

প্রসিডিউর কোনো ভ্যালু রিটার্ন করতেও পারে, নাও পারে। কিন্তু Function অবশ্যই একটি ভ্যালু রিটার্ন করবে

Syntax:

DELIMITER $$
CREATE FUNCTION calculateTax(price DECIMAL(10,2))
RETURNS DECIMAL(10,2)
DETERMINISTIC
BEGIN
  RETURN price * 0.15;
END $$
DELIMITER ;

ব্যবহার (SELECT এর মধ্যে):

SELECT product_name, calculateTax(price) FROM products;

Procedure vs Function (Interview Chart)

FeatureStored ProcedureUser-Defined Function
Returnভ্যালু রিটার্ন করতে বাধ্য নয় (OUT দিয়ে পারে)অবশ্যই একটি ভ্যালু রিটার্ন করবে
CallCALL কিওয়ার্ড দিয়ে রান হয়SELECT বা কুয়েরির ভেতরে ব্যবহার হয়
Usageবিজনেস লজিক হ্যান্ডেল করতেছোটখাটো ক্যালকুলেশন করতে
SQL SupportINSERT, UPDATE, DELETE সব করা যায়মূলত READ বা ক্যালকুলেশনের জন্য ভালো

১০.৬ Triggers — অটোমেটিক একশন

ট্রিগার হলো বন্দুকের ট্রিগারের মতো। গুলি বের হলে (Insert/Update/Delete হলে) শব্দ হবেই (Action হবেই)।

ট্রিগারের দুটি গুরুত্বপূর্ণ কিওয়ার্ড আছে (সিনিয়রিটির লক্ষণ):

  • NEW: যে ডেটাটি ইনসার্ট বা আপডেট হতে যাচ্ছে।
  • OLD: আপডেটের আগে বা ডিলিট করার সময় যে ডেটাটি ছিল।

Example: BEFORE INSERT (অটো টাইমস্ট্যাম্প বা ভ্যালিডেশন)

DELIMITER $$
CREATE TRIGGER before_user_insert
BEFORE INSERT ON users
FOR EACH ROW
BEGIN
  -- যদি ইউজার created_at না দেয়, অটো সেট হবে
  IF NEW.created_at IS NULL THEN
    SET NEW.created_at = NOW();
  END IF;
END $$
DELIMITER ;

Example: AFTER UPDATE (অডিট লগ রাখা - কে কী চেঞ্জ করল)

DELIMITER $$
CREATE TRIGGER audit_log_update
AFTER UPDATE ON products
FOR EACH ROW
BEGIN
  INSERT INTO product_logs (product_id, old_price, new_price, changed_at)
  VALUES (OLD.id, OLD.price, NEW.price, NOW());
END $$
DELIMITER ;

১০.৭ Events — MySQL এর নিজস্ব Cron Job

আপনার সার্ভারে লিনাক্স ক্রন জব সেট করার দরকার নেই। MySQL নিজেই নির্দিষ্ট সময়ে কাজ করতে পারে।

Scheduler অন করা:

SET GLOBAL event_scheduler = ON;

Example: ৩০ দিনের পুরোনো লগ ডিলিট করা (প্রতিদিন একবার)

CREATE EVENT clean_old_logs
ON SCHEDULE EVERY 1 DAY
STARTS '2025-01-01 00:00:00'
DO
  DELETE FROM activity_logs WHERE created_at < NOW() - INTERVAL 30 DAY;

১০.৮ Real-World Use Cases (Senior Developer Perspective)

একজন সিনিয়র হিসেবে কখন এগুলো ব্যবহার করবেন?

  • অডিট ট্রেইল (Audit Trail): ব্যাংকিং সিস্টেমে ব্যালেন্স আপডেট হলে Trigger দিয়ে অবশ্যই হিস্ট্রি টেবিলে রেকর্ড রাখা হয়।
  • ইনভেন্টরি ম্যানেজমেন্ট: অর্ডার কনফার্ম হলে Trigger দিয়ে স্টক কমানো।
  • রিপোর্টিং সামারি: প্রতিদিন রাত ১২টায় Event চালিয়ে সারাদিনের সেলস রিপোর্ট daily_sales টেবিলে সেভ করা (যাতে ড্যাশবোর্ড ফাস্ট হয়)।
  • বাল্ক অপারেশন: ১ মিলিয়ন ডেটা প্রসেস করতে হলে ব্যাকএন্ড কোড লুপ না চালিয়ে Stored Procedure দিয়ে করা অনেক ফাস্ট।

১০.৯ When NOT to use? (Architectural Decision)

ইন্টারভিউতে যদি জিজ্ঞেস করে "আমরা কি সব লজিক প্রসিডিউরে লিখব?" উত্তর হবে "না"

⚠️ কেন প্রসিডিউর বা ট্রিগার এড়াবেন?

  • Version Control সমস্যা: গিটহাবে কোড থাকে, কিন্তু প্রসিডিউর ডেটাবেসে থাকে। ডিপ্লয়মেন্টের সময় সিঙ্ক করা কঠিন।
  • Debugging নরক: প্রসিডিউরের ভেতরে এরর হলে ডিবাগ করা খুব পেইনফুল।
  • Vendor Lock-in: আপনি যদি সব লজিক MySQL এর সিনট্যাক্সে লেখেন, পরে PostgreSQL এ শিফট করতে চাইলে পুরো সিস্টেম নতুন করে লিখতে হবে।
  • CPU Usage: ডেটাবেস সার্ভারের কাজ ডেটা রাখা, প্রসেস করা নয়। লজিক বেশি লিখলে ডেটাবেস স্লো হয়ে যেতে পারে।
  • Microservices: মাইক্রোসার্ভিস আর্কিটেকচারে বিজনেস লজিক কোডে থাকা উচিত, ডেটাবেসে নয়।

✅ Best Practice:

ছোটখাটো ক্যালকুলেশন, ব্যাচ প্রসেসিং এবং অডিট লগের জন্য এগুলো ব্যবহার করুন। মেইন বিজনেস লজিক API-তেই রাখুন।

❓ Interview Q&A

Q: Trigger কি Transaction এর অংশ?

Ans: হ্যাঁ। যদি ট্রিগারের ভেতরে এরর হয়, তাহলে মেইন INSERT/UPDATE কুয়েরিও রোলব্যাক (Rollback) হবে।

Q: Stored Procedure এবং View এর পার্থক্য কী?

Ans: View হলো ভার্চুয়াল টেবিল (সেভ করা কুয়েরি), আর Procedure হলো ফাংশন বা স্ক্রিপ্ট যা লজিক এক্সিকিউট করে।

🎯 অধ্যায় ১০ এর সারাংশ (Summary)

এই অধ্যায়ে আমরা শিখলাম:

  • Stored Procedure: একাধিক SQL কুয়েরির বান্ডিল - IN, OUT, INOUT প্যারামিটার।
  • Function: ভ্যালু রিটার্ন করে - SELECT এর ভেতরে ব্যবহার হয়।
  • Trigger: INSERT/UPDATE/DELETE এর সাথে অটোমেটিক কাজ - NEW এবং OLD values।
  • Event: MySQL এর নিজস্ব Cron Job - নির্দিষ্ট সময়ে কাজ।
  • Best Practice: অডিট লগ, ব্যাচ প্রসেসিং, রিপোর্টিং-এর জন্য ব্যবহার করুন। মেইন বিজনেস লজিক API-তে রাখুন।

✨ এখন আপনি ডেটাবেস অটোমেশন এবং ইন্টারনাল প্রোগ্রামিং জানেন। পরবর্তী অধ্যায়ে আমরা শিখব Transactions & Locking—যেখানে আমরা শিখব কীভাবে ব্যাংকিং ট্রানজেকশনের মতো ক্রিটিক্যাল ডেটা সেভ করতে হয়।

প্রস্তুত তো? 🚀

🔒 কপিরাইট সুরক্ষিত কন্টেন্ট 🔒

কপি, স্ক্রিনশট, প্রিন্ট করা সম্পূর্ণ নিষিদ্ধ।