Keys & Constraints (ডেটাবেসের রক্ষাকবচ)
একটি ডেটাবেস শুধু ডেটা জমিয়ে রাখার জায়গা নয়; এটি ডেটার Integrity (সততা) এবং Accuracy (সঠিকতা) নিশ্চিত করে। ধরুন, একজন ইউজার ডিলিট হয়ে গেল, কিন্তু তার অর্ডারগুলো রয়ে গেল—একে বলে "এতিম ডেটা" (Orphan Data)। অথবা একই ইমেইল দিয়ে দুজন রেজিস্ট্রেশন করে ফেলল।
এই সমস্যাগুলো কোড দিয়ে আটকানো যায়, কিন্তু সেরা উপায় হলো ডেটাবেস লেভেলে আটকানো। আর এর জন্যই আমাদের দরকার Keys এবং Constraints।
৬.১ Primary Key (PK) — আইডেন্টিটি কার্ড
Primary Key হলো এমন একটি কলাম যা টেবিলের প্রতিটি রো-কে (Row) অনন্য বা ইউনিক করে। ক্লাসে যেমন রোল নম্বর থাকে, টেবিলে তেমনি প্রাইমারি কি থাকে।
বৈশিষ্ট্য:
- এর ভ্যালু কখনো NULL হতে পারবে না।
- পুরো টেবিলে এটি ইউনিক হতে হবে।
- MySQL অটোমেটিক্যালি এর ওপর Clustered Index তৈরি করে, যা ডেটা খুঁজতে সুপার ফাস্ট।
Example:
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT, -- এটিই প্রাইমারি কি
name VARCHAR(100)
);
কেন জরুরি? JOIN, UPDATE, DELETE—সব অপারেশন প্রাইমারি কি ধরে করলে মিলি-সেকেন্ডে কাজ হয়। এটি ছাড়া টেবিল ম্যানেজ করা অসম্ভব।
৬.২ Auto Increment এবং ডেটা টাইপ সিলেকশন
প্রতিবার ম্যানুয়ালি id দেওয়া কঠিন। তাই আমরা AUTO_INCREMENT ব্যবহার করি।
Flow: ১ → ২ → ৩ → ৪...
⚠️ Senior Level Warning (INT vs BIGINT)
জুনিয়ররা সবসময় INT ব্যবহার করে। INT এর লিমিট প্রায় ২ বিলিয়ন (2,147,483,647)।
বড় অ্যাপ্লিকেশনে (যেমন: লগ টেবিল, পেমেন্ট হিস্ট্রি) ২ বিলিয়ন ডেটা খুব দ্রুত শেষ হয়ে যেতে পারে। তখন INT Overflow এরর খাবেন এবং সাইট ডাউন হয়ে যাবে।
Best Practice:
সবসময় BIGINT ব্যবহার করুন। এটি নিরাপদ এবং ভবিষ্যতের টেনশন থাকে না।
id BIGINT AUTO_INCREMENT PRIMARY KEY
৬.৩ Surrogate Key vs Natural Key (Interview Question)
ডিজাইন করার সময় একটি বড় প্রশ্ন আসে: প্রাইমারি কি হিসেবে কী ব্যবহার করব?
১. Natural Key
বাস্তব জীবনের কোনো ইউনিক তথ্য। যেমন: Email, Phone Number, NID Card।
২. Surrogate Key (Recommended)
সিস্টেম জেনারেটেড কোনো অর্থহীন সংখ্যা। যেমন: id (1, 2, 3...) বা UUID।
✅ কেন Surrogate Key সেরা?
- Stability: মানুষের ইমেইল বা ফোন নম্বর পরিবর্তন হতে পারে। কিন্তু user_id = 501 কখনো বদলাবে না।
- Performance: INT বা BIGINT ইনডেক্স করা VARCHAR (ইমেইল) এর চেয়ে অনেক দ্রুত।
- Space: সংখ্যা স্ট্রিংয়ের চেয়ে কম জায়গা নেয়।
৬.৪ Unique Constraint — ডুপ্লিকেট নো এন্ট্রি
Primary Key ছাড়াও অন্য কলাম ইউনিক হতে পারে। যেমন: ইমেইল বা ফোন।
CREATE TABLE users (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
email VARCHAR(150) UNIQUE, -- একই ইমেইল দুইবার নেওয়া যাবে না
phone VARCHAR(20) UNIQUE
);
Composite Unique (একাধিক কলাম মিলে ইউনিক):
ধরুন, একটি ক্লাসে একজন ছাত্র একবারই এন্ট্রি নিতে পারবে।
UNIQUE (student_id, class_id)
৬.৫ Foreign Key (FK) — সম্পর্কের সেতু
রিলেশনাল ডেটাবেসের আসল শক্তি। এটি প্যারেন্ট টেবিল এবং চাইল্ড টেবিলের মধ্যে সম্পর্ক তৈরি করে।
উদাহরণ: orders টেবিলের user_id অবশ্যই users টেবিলের id-কে রেফার করবে। এমন কোনো user_id অর্ডারে বসানো যাবে না যা ইউজার টেবিলে নেই।
CREATE TABLE orders (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT,
amount DECIMAL(10,2),
-- Foreign Key ঘোষণা
CONSTRAINT fk_user
FOREIGN KEY (user_id)
REFERENCES users(id)
);
৬.৬ CASCADE Actions (Most Important Logic)
প্যারেন্ট (User) ডিলিট হলে চাইল্ডের (Order) কী হবে? এটি ON DELETE বা ON UPDATE দিয়ে ঠিক করা হয়।
১. ON DELETE CASCADE (অটো ডিলিট)
বাবা নাই, তো ছেলেও নাই। ইউজার ডিলিট করলে তার সব অর্ডার অটোমেটিক ডিলিট হয়ে যাবে।
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
ব্যবহার: ইউজার প্রোফাইল, উইশলিস্ট, টেম্পোরারি ডেটা।
২. ON DELETE SET NULL (অনাথ করে দেওয়া)
ইউজার ডিলিট হবে, কিন্তু অর্ডার থাকবে। শুধু user_id এর জায়গায় NULL বসে যাবে।
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
ব্যবহার: ব্লগ পোস্ট (লেখক চলে গেলেও পোস্ট থাকুক), লগ ডেটা।
৩. ON DELETE RESTRICT (ডিফল্ট - ডিলিট বারণ)
অর্ডার আছে এমন ইউজারকে ডিলিট করাই যাবে না। আগে অর্ডার ডিলিট করতে হবে, তারপর ইউজার।
ব্যবহার: ব্যাংকিং ট্রানজেকশন, ইনভয়েস। (ভুলবশত ডেটা ডিলিট হওয়া ঠেকায়)।
৬.৭ CHECK Constraint (ভ্যালিডেশন)
ডেটাবেসেই লজিক চেক করা। MySQL 8.0+ এ এটি সাপোর্ট করে।
CREATE TABLE products (
id INT PRIMARY KEY,
price INT,
CHECK (price > 0) -- দাম কখনো ০ বা নেগেটিভ হতে পারবে না
);
CHECK (age >= 18) -- ১৮ বছরের নিচে এন্ট্রি নেই
৬.৮ DEFAULT Constraint
ভ্যালু না দিলে ডিফল্ট কী বসবে?
status VARCHAR(20) DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
৬.৯ Composite Key (Many-to-Many সম্পর্কের বস)
অনেক সময় একটি কলাম দিয়ে ইউনিক করা যায় না, দুটি কলাম মিলে ইউনিক আইডি বা প্রাইমারি কি হয়।
উদাহরণ (Wishlist): একজন ইউজার (User A) একটি প্রোডাক্ট (Product X) একবারই উইশলিস্টে রাখতে পারবে।
CREATE TABLE wishlist (
user_id BIGINT,
product_id BIGINT,
-- এই দুইটা মিলে প্রাইমারি কি
PRIMARY KEY (user_id, product_id),
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (product_id) REFERENCES products(id)
);
সুবিধা:
- আলাদা করে id কলাম লাগে না।
- অটোমেটিক ডুপ্লিকেট এন্ট্রি আটকায় (একই ইউজার একই প্রোডাক্ট দুবার অ্যাড করতে গেলে এরর খাবে)।
৬.১০ Real-World Mistakes & Solutions (Senior Level)
ডেটাবেস ডিজাইন করার সময় জুনিয়ররা যে ভুলগুলো করে:
| ভুল (Mistake) | কেন খারাপ? | সমাধান |
|---|---|---|
| No Primary Key | টেবিল স্লো হয়, ডুপ্লিকেট রো তৈরি হয়। | প্রতিটি টেবিলে id রাখুন। |
| VARCHAR as PK | স্ট্রিং ইনডেক্সিং স্লো এবং মেমোরি বেশি খায়। | BIGINT ব্যবহার করুন। |
| No Foreign Key | ভুতুড়ে ডেটা (Orphan rows) তৈরি হয়। জয়েন ভুল রেজাল্ট দেয়। | রিলেশন থাকলে অবশ্যই FK দিন। |
| Overusing ENUM | ভবিষ্যতে নতুন অপশন যোগ করতে হলে টেবিল লক হয়ে যায়। | লুকআপ টেবিল (Lookup Table) বা স্ট্রিং ব্যবহার করুন। |
| Wrong Data Type | যেমন Phone এর জন্য INT নেওয়া (0 দিয়ে শুরু হলে সমস্যা)। | ফোনের জন্য VARCHAR ব্যবহার করুন। |
🟢 Senior-Level Best Practices Summary
একজন অভিজ্ঞ ইঞ্জিনিয়ার হিসেবে এই চেকলিস্ট ফলো করবেন:
- ✓ Use BIGINT: আইডির জন্য চোখ বন্ধ করে BIGINT ব্যবহার করুন।
- ✓ Index FK: যেই কলামগুলো ফরেইন কি (Foreign Key), সেগুলোতে ইনডেক্স আছে কি না নিশ্চিত করুন (MySQL অটো করে, তবুও চেক করা ভালো)।
- ✓ Think about DELETE: ON DELETE CASCADE দেওয়ার আগে ১০ বার ভাবুন। গুরুত্বপূর্ণ ডেটা (টাকা বা ইনভয়েস) হলে কখনোই ক্যাসকেড দেবেন না, RESTRICT ব্যবহার করুন।
- ✓ Date vs Datetime: জন্মদিনের জন্য DATE এবং ট্রানজেকশনের জন্য DATETIME বা TIMESTAMP সঠিক ভাবে ব্যবহার করুন।
- ✓ Constraints over Code: কোডে ভ্যালিডেশন থাকলেও ডেটাবেসে CHECK বা UNIQUE কনস্ট্রেইন্ট অবশ্যই রাখবেন। কোড ফেইল করতে পারে, ডেটাবেস শেষ ভরসা।
❓ Interview Q&A
Q: Primary Key এবং Unique Key এর মধ্যে পার্থক্য কী?
Ans: Primary Key টেবিলে একটাই থাকে এবং NULL এলাউ করে না। Unique Key একাধিক থাকতে পারে এবং NULL এলাউ করতে পারে (ইঞ্জিন ভেদে)।
Q: Composite Key কখন ব্যবহার করবেন?
Ans: মূলত Many-to-Many রিলেশনশিপ বা ম্যাপিং টেবিলে (যেমন: student_course, user_roles) যেখানে দুটি ফরেন কি মিলে ইউনিক আইডেন্টিটি তৈরি করে।
🎯 অধ্যায় ৬ এর সারাংশ (Summary)
এই অধ্যায়ে আমরা শিখলাম:
- ✓ Primary Key: প্রতিটি রো-এর অনন্য শনাক্তকারী।
- ✓ Foreign Key: টেবিলের মধ্যে সম্পর্ক তৈরি এবং ডেটা ইন্টিগ্রিটি নিশ্চিত করে।
- ✓ CASCADE Actions: ON DELETE CASCADE, SET NULL, RESTRICT - ডিলিট পলিসি নির্ধারণ।
- ✓ Constraints: UNIQUE, CHECK, DEFAULT - ডেটা ভ্যালিডেশন।
- ✓ Best Practices: BIGINT ব্যবহার, Surrogate Key প্রাধান্য, এবং সঠিক CASCADE সিলেকশন।
✨ এই নলেজ দিয়ে আপনি এখন শুধু টেবিল বানাবেন না, বরং একটি Secure এবং Scalable Database Architecture ডিজাইন করতে পারবেন।
পরবর্তী অধ্যায়ে আমরা শিখব Database Design & Normalization—যেখানে আমরা শিখব ডেটাকে কীভাবে সাজালে ডুপ্লিকেট কমবে এবং এফিসিয়েন্সি বাড়বে। প্রস্তুত তো? 🚀