এই পর্বে যা শিখবেন
- ফাইল-ভিত্তিক পদ্ধতির সমস্যা, DBMS-এর সুবিধা-অসুবিধা আর কোন DBMS কোথায় ব্যবহৃত হয়
- field, record, table, schema, data type আর পাঁচ ধরনের key — HSC ICT-র ভাষায়
- 1:1, 1:N, M:N সম্পর্ক, ER diagram আঁকা আর foreign key দিয়ে টেবিল জোড়া
- redundancy আর anomaly কেন বিপজ্জনক, আর একটি এলোমেলো টেবিলকে ধাপে ধাপে 3NF-এ আনা
- index, query-form-report, data integrity, নিরাপত্তা, বাংলাদেশের বড় ডেটাবেস — আর AI-এর বানানো নকশা যাচাইয়ের নিয়ম
১ · খাতা থেকে ডেটাবেস — DBMS কেন দরকার
পর্ব ০১-এ দেখেছেন, ডেটা হলো কাঁচা তথ্য — “১২”, “সুমি”, “৮৮”. আলাদাভাবে এদের তেমন অর্থ নেই। সাজিয়ে প্রক্রিয়া করলে হয় ইনফরমেশন: “রোল ১২-এর সুমি গণিতে ৮৮ পেয়েছে, A+”. একটি স্কুলে প্রতিদিন এমন হাজার হাজার ডেটা জমে — ভর্তি, বেতন, উপস্থিতি, নম্বর। এগুলো রাখার একটি সুশৃঙ্খল ব্যবস্থা দরকার।
ডেটাবেস হলো পরস্পর-সম্পর্কিত ডেটার একটি সুসংগঠিত সংগ্রহ। আর DBMS (Database Management System) হলো সেই সফটওয়্যার, যা ডেটাবেস তৈরি করে, ডেটা নিরাপদে রাখে, একসাথে অনেক মানুষকে ব্যবহার করতে দেয় আর প্রশ্নের উত্তর দ্রুত খুঁজে দেয়। Relational ডেটাবেসে ডেটা থাকে কয়েকটি জোড়া-লাগানো টেবিলে — প্রতিটি তথ্য একবারই লেখা, আর টেবিলগুলো key দিয়ে যুক্ত।
একটি স্কুলের অফিস ভাবুন। ভর্তির খাতায় ছাত্রের নাম-ঠিকানা, হিসাবরক্ষকের খাতায় আবার নাম-ঠিকানা আর বেতন, পরীক্ষা কমিটির খাতায় আবার নাম আর নম্বর। একজন ছাত্রের বাসা বদলালে তিনটি খাতায় তিনজনকে বদলাতে হয় — কেউ ভুলে গেলে তিন খাতায় তিন ঠিকানা। এখন ভাবুন, অফিসে একজন দক্ষ রেজিস্ট্রার আছেন। সব তথ্য তাঁর একটি আলমারিতে, প্রতিটি তথ্য একবার লেখা। যে-ই জানতে চান, তাঁকে জিজ্ঞেস করেন; কে কোন ফাইল দেখতে পারবেন, তিনি ঠিক করেন; প্রতি রাতে একটি কপি নিরাপদ জায়গায় রাখেন। ডেটাবেস হলো সেই আলমারি, DBMS হলো সেই রেজিস্ট্রার।
ফাইল-ভিত্তিক পদ্ধতি বনাম DBMS
DBMS আসার আগে প্রতিটি বিভাগ বা প্রতিটি প্রোগ্রাম নিজের আলাদা ফাইলে ডেটা রাখত — আজকের দিনে আলাদা আলাদা Excel ফাইলের মতো। এর সমস্যাগুলোর নাম HSC ICT-তে বারবার আসে:
| সমস্যা | ফাইল-ভিত্তিক পদ্ধতিতে | DBMS-এ |
|---|---|---|
| Redundancy (অপ্রয়োজনীয় পুনরাবৃত্তি) | একই নাম-ঠিকানা তিন ফাইলে | প্রতিটি তথ্য এক জায়গায়, বাকিরা key দিয়ে নির্দেশ করে |
| Inconsistency (অসঙ্গতি) | এক ফাইলে নতুন ঠিকানা, অন্যটিতে পুরোনো | এক জায়গায় বদলালেই সবখানে নতুন |
| Isolation (বিচ্ছিন্নতা) | ডেটা ছড়ানো, ভিন্ন ভিন্ন ফরম্যাটে; একসাথে প্রশ্ন করা কঠিন | সব টেবিল এক ব্যবস্থায়, এক ভাষায় (SQL) প্রশ্ন |
| Security (নিরাপত্তা) | ফাইল যার হাতে, সব তথ্য তার হাতে | ব্যবহারকারী অনুযায়ী অনুমতি — শিক্ষক নম্বর লেখেন, ছাত্র শুধু নিজেরটা দেখে |
| Concurrency (একসাথে ব্যবহার) | দুজন একই ফাইল খুললে একজনের কাজ মুছে যেতে পারে | হাজারো মানুষ একসাথে পড়ে-লেখে, কারও কাজ হারায় না |
| Integrity (শুদ্ধতা) | নম্বরের ঘরে “১৫০” বা নামের ঘরে সংখ্যা ঢুকে যায় | নিয়ম (validation rule, key) ভাঙলে DBMS ডেটা নেয়ই না |
DBMS-এর সুবিধা তাই সংক্ষেপে: redundancy নিয়ন্ত্রণ, তথ্যের সঙ্গতি, সহজে ভাগাভাগি, নিরাপত্তা, শুদ্ধতা, backup ও recovery, একসাথে বহু ব্যবহারকারী আর দ্রুত খোঁজা। অসুবিধাও আছে: সফটওয়্যার, শক্তিশালী কম্পিউটার আর প্রশিক্ষিত লোকের খরচ; নকশা জটিল; খুব ছোট কাজে (দশ জনের ফোন নম্বর) একটু ভারী; আর মূল সার্ভার নষ্ট হলে সবার কাজ একসাথে থামে — তাই backup জরুরি।
পরিচিত কয়েকটি DBMS
MS Access
Microsoft Office-এর অংশ, ডেস্কটপের ছোট ডেটাবেস — অফিসের স্টক, লাইব্রেরি, ছোট স্কুলের হিসাব। টেবিল, ফর্ম, রিপোর্ট সব মাউসে। HSC ICT-র ব্যবহারিকে এটিই চলে।
এক ফাইলে পুরো ডেটাবেস (.accdb)MySQL · PostgreSQL
ওপেন সোর্স, সার্ভারে চলে — বেশিরভাগ ওয়েবসাইট আর ই-কমার্সের পেছনে। পর্ব ৩৪-এর shared hosting-এ সাধারণত MySQL বা তার শাখা MariaDB থাকে।
ওয়েবের পেছনেOracle · SQL Server
বড় প্রতিষ্ঠানের বাণিজ্যিক DBMS — ব্যাংকের core banking, টেলিকম, বড় সরকারি ব্যবস্থা। দামি, কিন্তু বিপুল লেনদেন আর কঠোর নিরাপত্তার জন্য তৈরি।
ব্যাংক আর বড় কোম্পানিSQLite
সার্ভার ছাড়া, একটি ফাইলেই পুরো ডেটাবেস। প্রায় প্রতিটি Android ফোন আর iPhone-এর ভেতরে — আপনার কন্টাক্ট, মেসেজ, ব্রাউজারের ইতিহাস অনেক অ্যাপে এভাবেই থাকে।
আপনার পকেটে২ · টেবিলের ভাষা — entity, field, record, schema আর data type
Relational ডেটাবেসের প্রতিটি টেবিল একটি entity-র কথা বলে — এমন কোনো জিনিস বা ব্যক্তি, যার তথ্য রাখতে চাই: ছাত্র, বিষয়, শিক্ষক, বই। entity-র প্রতিটি বৈশিষ্ট্য (রোল, নাম, জন্মতারিখ) হলো attribute. নিচের ছোট টেবিলটি দেখুন:
Students টেবিল ← table / relation
+------+-------+-------+------------+
| Roll | Name | Class | BirthDate | ← field (column / attribute)
+------+-------+-------+------------+
| 11 | Rahim | Ten | 2010-03-14 | ← record (row / tuple)
| 12 | Sumi | Ten | 2010-07-02 |
| 13 | Joy | Ten | 2009-12-25 |
+------+-------+-------+------------+
| শব্দ | অন্য নাম | মানে | উদাহরণ |
|---|---|---|---|
| Field | column, attribute | একটি নির্দিষ্ট ধরনের তথ্যের ঘর, সব record-এ একই | Name |
| Record | row, tuple | একটি entity-র সব field মিলিয়ে একটি পূর্ণ তথ্য | 11, Rahim, Ten, 2010-03-14 |
| Table | relation | একই ধরনের record-গুলোর সংগ্রহ | Students |
| File (ডেটাবেস ফাইল) | — | পাঠ্যবইয়ে: সম্পর্কিত record-এর সংগ্রহ; Access-এ সব টেবিল মিলে একটি .accdb ফাইল | school.accdb |
| Schema | কাঠামো | কোন টেবিলে কোন field, কোন ধরনের ডেটা, কোনটি key — ডেটা ছাড়া শুধু নকশা | Students(Roll, Name, Class, BirthDate) |
ডেটার স্তরগুলো ছোট থেকে বড়: বর্ণ (character) → field → record → table/file → ডেটাবেস. কয়েকটি বর্ণ মিলে “Sumi” — একটি field-এর মান; কয়েকটি field মিলে সুমির record; সব ছাত্রের record মিলে Students টেবিল; Students, Subjects, Results মিলে স্কুলের ডেটাবেস। পরীক্ষায় এই ক্রমটি প্রায়ই জিজ্ঞেস করা হয়।
Data type — প্রতিটি field-এর ধরন
স্প্রেডশিটে একটি সেলে যা খুশি লেখা যায়। ডেটাবেসে প্রতিটি field-এর data type আগে থেকে ঠিক করা থাকে — তাই জন্মতারিখের ঘরে “আগামীকাল” লেখা যায় না। Access আর SQL-এ নামগুলো একটু আলাদা:
| কী রাখবে | Access-এ নাম | SQL-এ সাধারণ নাম | উদাহরণ |
|---|---|---|---|
| ছোট লেখা (২৫৫ অক্ষর পর্যন্ত) | Short Text (পুরোনো নাম Text) | VARCHAR(n), CHAR(n) | নাম, মোবাইল নম্বর |
| লম্বা লেখা | Long Text (পুরোনো নাম Memo) | TEXT | ঠিকানা, মন্তব্য |
| সংখ্যা | Number | INT, DECIMAL | নম্বর, বয়স |
| তারিখ ও সময় | Date/Time | DATE, DATETIME | জন্মতারিখ |
| টাকা | Currency | DECIMAL(10,2) | মাসিক বেতন |
| হ্যাঁ/না | Yes/No | BOOLEAN | বেতন পরিশোধিত? |
| নিজে নিজে বাড়া ক্রমিক নম্বর | AutoNumber | AUTO_INCREMENT, SERIAL | রসিদ নম্বর |
| ছবি, ফাইল | OLE Object, Attachment | BLOB | ছাত্রের ছবি |
মোবাইল নম্বর সংখ্যা নয়, লেখা। 01712345678-কে Number হিসেবে রাখলে শুরুর 0 মুছে যায়, আর এর ওপর যোগ-বিয়োগের কোনো মানে নেই। একই কথা রোল নম্বর “০০৭”, পোস্ট কোড বা NID নম্বরের ক্ষেত্রেও — যে সংখ্যা দিয়ে হিসাব হয় না, তাকে Text রাখুন।
৩ · Key — প্রতিটি record-কে আলাদা করে চেনা
একই শ্রেণিতে দুজন “Md. Rahim” থাকতেই পারে। তাহলে “রহিমের নম্বর বদলাও” বললে কোন রহিম? ডেটাবেসে প্রতিটি record-কে নিশ্চিতভাবে আলাদা করে চেনার জন্য একটি বা কয়েকটি field বেছে নেওয়া হয় — এর নাম primary key. ট্রেনের টিকিটের PNR নম্বর বা আপনার NID নম্বর যেমন একজনকেই নির্দেশ করে, ঠিক তেমন।
ফাঁকা নয় (NOT NULL) — প্রতিটি record-এ মান থাকতেই হবে
| Key | মানে | স্কুলের উদাহরণ |
|---|---|---|
| Candidate key | যেসব field (বা field-এর জোড়া) primary key হওয়ার যোগ্য — অনন্য আর ন্যূনতম | বোর্ডের রেজিস্ট্রেশন নম্বর, জন্মনিবন্ধন নম্বর — দুটিই একজন ছাত্রকে চেনায় |
| Primary key | candidate key-গুলোর মধ্যে যেটিকে বেছে নেওয়া হলো | রেজিস্ট্রেশন নম্বর |
| Alternate key | বাছাই না হওয়া candidate key | জন্মনিবন্ধন নম্বর |
| Composite key | একটি field যথেষ্ট নয়, কয়েকটি মিলে অনন্য | (Class, Section, Roll) — রোল ১২ নবম-ক, দশম-ক, দশম-খ সবখানে আছে, কিন্তু তিনটি মিলে একজনই |
| Foreign key | এক টেবিলের field, যা অন্য টেবিলের primary key-কে নির্দেশ করে | Results টেবিলের Roll, যা Students টেবিলের Roll-কে দেখায় |
পাঠ্যবইয়ে আরেকটি নাম আছে — super key: যেকোনো field-সমষ্টি, যা অনন্য, বাড়তি field থাকলেও। যেমন (রেজিস্ট্রেশন নম্বর, নাম) অনন্য, কিন্তু নাম বাড়তি — তাই এটি super key, candidate key নয়। মনে রাখার সহজ পথ: super key-র মধ্য থেকে যারা ন্যূনতম, তারা candidate; candidate-দের মধ্যে একজন primary, বাকিরা alternate.
নাম কেন primary key নয়? নাম অনন্য নয়, বানানে ভুল হয় (“Rahim”/“Rohim”), আর বদলাতেও পারে। মোবাইল নম্বরও খারাপ পছন্দ — মানুষ নম্বর বদলায়, পরিবারে ভাগ করে। ভালো primary key এমন, যা কখনো বদলায় না। তাই অনেক ডেটাবেস কোনো বাস্তব তথ্য না নিয়ে একটি AutoNumber ID বানায় — একে বলে surrogate key.
৪ · Relationship, ER diagram আর টেবিল জোড়া
টেবিলগুলো আলাদা থাকলেও তাদের মধ্যে সম্পর্ক আছে — একজন ছাত্র কয়েকটি বিষয় নেয়, একজন শিক্ষক কয়েকটি বিষয় পড়ান। ডেটাবেসে এই সম্পর্কের নাম relationship, আর এর ধরন তিনটি:
| ধরন | মানে | উদাহরণ | টেবিলে যেভাবে |
|---|---|---|---|
| One-to-one (1:1) | এক পাশের একটি record-এর সাথে অন্য পাশের ঠিক একটি | নাগরিক — NID কার্ড; দেশ — রাজধানী | যেকোনো এক টেবিলে অন্যটির key, UNIQUE শর্তসহ |
| One-to-many (1:N) | এক পাশের একটির সাথে অন্য পাশের অনেকগুলো | এক শ্রেণিতে অনেক ছাত্র; এক গ্রাহকের অনেক bKash লেনদেন | “অনেক” পাশের টেবিলে foreign key |
| Many-to-many (M:N) | দুই পাশেই অনেক | এক ছাত্র অনেক বিষয় নেয়, এক বিষয়ে অনেক ছাত্র | মাঝে একটি সংযোগ-টেবিল (Results/Enrollment), যেখানে দুই পাশের foreign key |
M:N সম্পর্ক সরাসরি দুই টেবিলে রাখা যায় না — ছাত্রের সারিতে “বিষয়১, বিষয়২, বিষয়৩” কলাম বানালে কেউ চারটি বিষয় নিলে কী হবে? সমাধান হলো মাঝের টেবিল: Results(Roll, SubCode, Marks). এতে একটি M:N দুটি 1:N হয়ে যায় — এক ছাত্রের অনেক Results সারি, এক বিষয়ের অনেক Results সারি। আর মাঝের টেবিলটি এমন তথ্যও রাখে, যা কোনো একক পাশের নয় — যেমন নম্বর।
ER diagram — নকশার ছবি
টেবিল বানানোর আগে নকশাটা কাগজে আঁকা হয়। ১৯৭৬ সালে Peter Chen যে পদ্ধতি প্রস্তাব করেন, তাকে বলে ER diagram (Entity-Relationship diagram): আয়তক্ষেত্রে entity, ডিম্বাকৃতিতে attribute (primary key-র নিচে দাগ), হীরা আকৃতিতে relationship, আর রেখার পাশে 1, M, N লিখে সম্পর্কের ধরন। একটি স্কুলের ছোট ডেটাবেস:
একটি স্কুল ডেটাবেসের ER diagram
Student M — নেয় — N Subject · Teacher 1 — পড়ান — N Subject
ছবি থেকে টেবিল বানানোর নিয়ম সহজ: প্রতিটি entity একটি টেবিল; 1:N সম্পর্কে “1” পাশের primary key “N” পাশের টেবিলে foreign key হয়ে বসে (Subject টেবিলে TeacherID); M:N সম্পর্ক নিজেই একটি টেবিল হয়, যার মধ্যে দুই পাশের key আর সম্পর্কের attribute (Results টেবিলে Roll, SubCode, Marks). আর একটি relational ডেটাবেসের শক্তি এই যে, আলাদা টেবিল থেকে মিলিয়ে প্রশ্নের উত্তর বানানো যায় — একে বলে join. দেখুন:
Roll Name
11 Rahim
12 Sumi
13 Joy
Roll SubCode Marks 11 MAT 75 11 BAN 81 12 MAT 88 12 ICT 92 12 BAN 79 13 ICT 67
SubCode SubName TeacherID MAT Math T2 ICT ICT T2 BAN Bangla T1
Name SubName Marks Sumi Math 88 Sumi ICT 92 Sumi Bangla 79 (কোনো তথ্য দুবার লেখা নেই — তবু উত্তর পূর্ণ)
- শুরু Students থেকে। প্রশ্ন: “রোল ১২ কোন কোন বিষয় নিয়েছে, কত পেয়েছে?” Students টেবিলে Roll হলো primary key, তাই রোল ১২-এর একটিই সারি — নাম Sumi. কিন্তু এখানে বিষয়ের কোনো তথ্য নেই, থাকার কথাও নয়।
- foreign key ধরে Results-এ। Results টেবিলের Roll একটি foreign key — প্রতিটি মান Students-এর কোনো একটি Roll-কে নির্দেশ করে। Roll = 12 এমন তিনটি সারি পাওয়া গেল: MAT, ICT, BAN, আর প্রতিটির নম্বর। এটাই 1:N — এক ছাত্রের অনেক ফল।
- আরেকটি foreign key ধরে Subjects-এ। Results-এ বিষয়ের শুধু কোড আছে। SubCode দিয়ে Subjects টেবিল থেকে পুরো নাম আনা হলো — পর্ব ১১-এর XLOOKUP যে কাজ হাতে হাতে করত, DBMS তা নিজেই করে।
- মিলিয়ে উত্তর। তিন টেবিলের মিলিত সারি: Sumi — Math 88, ICT 92, Bangla 79. লক্ষ করুন, সুমির নাম কোথাও তিনবার লেখা নেই, “Math” নামটিও একবার। তথ্য আলাদা জায়গায় একবার করে, প্রশ্নের সময় জোড়া — এটাই relational ডেটাবেসের মূল কৌশল।
এই একই প্রশ্ন পর্ব ৪২-এ শিখবেন এমন SQL ভাষায় লিখলে দেখতে এমন (এখন শুধু চোখ বুলিয়ে নিন):
SELECT s.Name, sub.SubName, r.Marks
FROM Results r
JOIN Students s ON r.Roll = s.Roll
JOIN Subjects sub ON r.SubCode = sub.SubCode
WHERE r.Roll = 12;প্রত্যাশিত আউটপুট: তিনটি সারি — Sumi | Math | 88, Sumi | ICT | 92, Sumi | Bangla | 79. ON r.Roll = s.Roll অংশটিই foreign key ধরে জোড়া দেওয়ার নির্দেশ।
নিজে চালিয়ে দেখুন — একটি ছোট্ট relational ডেটাবেস
DBMS ভেতরে কী পাহারা দেয়? নিচের প্রোগ্রামে দুটি অ্যারে দুটি টেবিল। এটি তিনটি কাজ করে: primary key ভাঙে এমন নতুন record আটকায়, এমন ফল খুঁজে বের করে যার রোল Students-এ নেই (foreign key ভাঙা), আর রোল ১২-এর জন্য join করে। “চালান” চাপুন।
const students = [{ roll: 11, sname: "Rahim" }, { roll: 12, sname: "Sumi" }, { roll: 13, sname: "Joy" }];
const results = [
{ roll: 11, sub: "Math", marks: 75 }, { roll: 12, sub: "Math", marks: 88 },
{ roll: 12, sub: "ICT", marks: 92 }, { roll: 12, sub: "Bangla", marks: 79 },
{ roll: 15, sub: "ICT", marks: 60 } // roll 15 is not in students!
];
function insertStudent(s) { // primary key: roll must be unique
if (students.some(x => x.roll === s.roll)) {
console.log(`REJECTED: roll ${s.roll} already exists (primary key)`); return;
}
students.push(s); console.log(`OK: roll ${s.roll} added`);
}
insertStudent({ roll: 14, sname: "Mitu" });
insertStudent({ roll: 12, sname: "Karim" });
const rolls = new Set(students.map(s => s.roll));
for (const r of results) // foreign key: roll must exist in students
if (!rolls.has(r.roll)) console.log(`FK VIOLATION: result for roll ${r.roll} has no student`);
const who = students.find(s => s.roll === 12); // join on roll
console.log(`Roll 12 (${who.sname}) took:`);
for (const r of results.filter(x => x.roll === 12)) console.log(` ${r.sub}: ${r.marks}`);আউটপুট আসে: OK: roll 14 added, তারপর REJECTED: roll 12 already exists (primary key) — রোল ১২-তে সুমি আগেই আছেন, তাই করিমকে একই রোলে ঢুকতে দেওয়া হলো না। তারপর FK VIOLATION: result for roll 15 has no student — এমন একটি ফল, যার মালিক ছাত্রই নেই (“অনাথ” record). শেষে Roll 12 (Sumi) took: আর তিনটি লাইন — Math: 88, ICT: 92, Bangla: 79. Set হলো সব রোলের একটি দ্রুত খোঁজার তালিকা — আসল DBMS এই কাজে index ব্যবহার করে (অংশ ৬)। আসল DBMS-এ পার্থক্য হলো, এই পাহারা আপনাকে লিখতে হয় না — key ঘোষণা করলেই নিয়ম ভাঙা ডেটা ঢোকার সময়েই আটকে যায়, আর রোল ১৫-এর মতো ফল কখনো তৈরিই হতে পারে না।
৫ · Redundancy, anomaly আর normalization
অনেক অফিসে ডেটা শুরু হয় একটি বড় স্প্রেডশিট দিয়ে — সব তথ্য এক টেবিলে। দেখতে সুবিধাজনক, কিন্তু একই তথ্য বারবার লেখা হয়। এই redundancy থেকে তিন ধরনের সমস্যা জন্মায়, যাদের একসাথে বলে anomaly:
- Update anomaly: একটি তথ্য বদলাতে অনেক সারি বদলাতে হয়; একটি বাদ পড়লেই অসঙ্গতি।
- Insertion anomaly: নতুন শিক্ষক যোগ দিয়েছেন, কিন্তু এখনো কোনো ছাত্র তাঁর বিষয় নেয়নি — ছাত্র ছাড়া সারিই বানানো যায় না, তাই শিক্ষকের তথ্য রাখার জায়গা নেই।
- Deletion anomaly: জয় স্কুল ছেড়ে গেল, তার সারিগুলো মোছা হলো — আর ICT বিষয়টি একমাত্র সে-ই নিয়ে থাকলে ICT-র শিক্ষকের তথ্যও হারিয়ে গেল।
Update anomaly চোখের সামনে দেখুন। একটি টেবিলে শিক্ষক কামালের ফোন নম্বর চার সারিতে আছে; নম্বরটি বদলেছে:
111 Rahim MAT Kamal 01800-000002211 Rahim BAN Rina 01700-000001312 Sumi MAT Kamal 01800-000002412 Sumi ICT Kamal 01800-000002512 Sumi BAN Rina 01700-000001613 Joy ICT Kamal 01800-000002
| কামালের সারি | |
| বদলানো হয়েছে | |
| সারি ৬-এর নম্বর |
- একই তথ্য চার জায়গায়। কামাল স্যার গণিত আর ICT পড়ান, তাই যতবার কোনো ছাত্র এই দুই বিষয়ের একটি নেয়, ততবার তাঁর নম্বর আবার লেখা হয় — সারি ১, ৩, ৪, ৬. স্কুলে ৫০০ ছাত্র হলে নম্বরটি কয়েকশো বার।
- বদলানো শুরু। অফিস সহকারী সারি ১ আর ৩ বদলালেন। কাজটি একঘেয়ে আর সময়সাপেক্ষ — আর যত বেশি কপি, ভুলের সুযোগ তত বেশি।
- একটি বাদ পড়ল। সারি ৪ বদলানো হলো, কিন্তু সারি ৬ চোখ এড়িয়ে গেল (হয়তো অন্য পাতায় ছিল)। কোনো ত্রুটি-বার্তা আসেনি — টেবিল দেখতে স্বাভাবিক।
- অসঙ্গতি ধরা পড়ে দেরিতে। জয়ের অভিভাবক ICT শিক্ষকের নম্বর চাইলেন — টেবিল দিল পুরোনো নম্বর। এখন ডেটাবেসে একই মানুষের দুটি ভিন্ন নম্বর; কোনটি ঠিক, ডেটা দেখে বলার উপায় নেই। এটাই update anomaly.
- normalized নকশায়। কামালের নম্বর আছে শুধু Teachers টেবিলের এক সারিতে; বাকি সব টেবিলে শুধু তাঁর ID (T2). একবার বদলালেই সব প্রশ্নের উত্তরে নতুন নম্বর — ভুলের সুযোগই নেই।
Normalization — ধাপে ধাপে ভাঙা
Normalization হলো টেবিলকে নিয়ম মেনে ছোট ছোট টেবিলে ভাঙার পদ্ধতি, যাতে প্রতিটি তথ্য এক জায়গায় থাকে আর anomaly দূর হয়। প্রতিটি ধাপকে বলে একটি “normal form”; HSC আর চাকরির পরীক্ষায় প্রথম তিনটি আসে। মূল ভাবনা একটিই — প্রতিটি field নির্ভর করবে key-র ওপর, পুরো key-র ওপর, আর key ছাড়া অন্য কিছুর ওপর নয়। নিচে একটি এলোমেলো শিটকে ধাপে ধাপে বদলান:
Roll Name Subjects Teachers (Phone) Marks 11 Rahim MAT, BAN Kamal (01800..), Rina (01700..) 75, 81 12 Sumi MAT, ICT, BAN Kamal, Kamal, Rina ... 88, 92, 79 13 Joy ICT Kamal (01800..) 67
Roll Name SubCode SubName TeacherID Teacher TPhone Marks
11 Rahim MAT Math T2 Kamal 01800-000002 75
11 Rahim BAN Bangla T1 Rina 01700-000001 81
12 Sumi MAT Math T2 Kamal 01800-000002 88
12 Sumi ICT ICT T2 Kamal 01800-000002 92
12 Sumi BAN Bangla T1 Rina 01700-000001 79
13 Joy ICT ICT T2 Kamal 01800-000002 67
Name বারবার, SubName বারবার, Kamal-এর নম্বর ৪ বার
Students(Roll, Name) 11 Rahim · 12 Sumi · 13 Joy Subjects(SubCode, SubName, TeacherID, Teacher, TPhone) MAT Math T2 Kamal 01800-000002 ICT ICT T2 Kamal 01800-000002 ← এখনো ২ বার BAN Bangla T1 Rina 01700-000001 Results(Roll, SubCode, Marks) ৬টি সারি
Students(Roll, Name) Results(Roll, SubCode, Marks) Subjects(SubCode, SubName, TeacherID) MAT Math T2 · ICT ICT T2 · BAN Bangla T1 Teachers(TeacherID, Teacher, TPhone) T1 Rina 01700-000001 T2 Kamal 01800-000002 ← একবারই
Results ⋈ Students ⋈ Subjects ⋈ Teachers = ঠিক 1NF-এর ৬টি সারি, একটিও কম-বেশি নয় নতুন শিক্ষক T3? → Teachers-এ এক সারি (insertion ✔) জয় চলে গেল? → Students + Results থেকে মোছা, Kamal-এর তথ্য অক্ষত (deletion ✔) নম্বর বদল? → এক সারি (update ✔)
- UNF — এলোমেলো শিট। এক ঘরে কয়েকটি বিষয়, কয়েকটি নম্বর, কমা দিয়ে আলাদা। “গণিতে কে কত পেয়েছে?” — এ প্রশ্নের উত্তর দিতে প্রতিটি ঘরের লেখা ভেঙে পড়তে হবে; কোন নম্বর কোন বিষয়ের, তা নির্ভর করছে কমার ক্রমের ওপর। এটি unnormalized form.
- 1NF — প্রতি ঘরে একটি মান। প্রথম normal form-এর শর্ত: প্রতিটি ঘরে একটিমাত্র অবিভাজ্য (atomic) মান, আর কোনো পুনরাবৃত্ত কলাম-দল নয়। তাই প্রতিটি (ছাত্র, বিষয়) জোড়ার জন্য আলাদা সারি। এখন কোনো একক field সারিকে অনন্য করে না — key হলো composite: (Roll, SubCode). কিন্তু redundancy বেড়ে গেল: “Sumi” তিনবার, কামালের নম্বর চারবার।
- 2NF — পুরো key-র ওপর নির্ভর। দ্বিতীয় normal form: 1NF, আর কোনো non-key field যেন key-র শুধু একটি অংশের ওপর নির্ভর না করে (partial dependency). Name নির্ভর করে শুধু Roll-এর ওপর; SubName, Teacher নির্ভর করে শুধু SubCode-এর ওপর। এদের আলাদা টেবিলে সরানো হলো। শুধু Marks পুরো (Roll, SubCode)-এর ওপর নির্ভর — সে থাকল Results-এ।
- 3NF — key ছাড়া অন্য কিছুর ওপর নয়। তৃতীয় normal form: 2NF, আর কোনো non-key field যেন অন্য non-key field-এর মাধ্যমে key-র ওপর নির্ভর না করে (transitive dependency). Subjects-এ SubCode → TeacherID → TPhone: ফোন নম্বর আসলে শিক্ষকের তথ্য, বিষয়ের নয়। তাই Teachers আলাদা টেবিল। এখন কামালের নম্বর এক জায়গায়।
- কিছু হারায়নি তো? চারটি টেবিল join করলে ঠিক আগের ছয়টি সারি ফিরে আসে — তাই ভাঙাটা “ক্ষতিহীন”. আর তিনটি anomaly-ই দূর: ছাত্র ছাড়া শিক্ষক যোগ করা যায়, ছাত্র মুছলে শিক্ষকের তথ্য থাকে, নম্বর বদলাতে এক সারি।
এক লাইনে মনে রাখার কৌশল: ইংরেজিতে প্রচলিত একটি বাক্য আছে — প্রতিটি non-key field নির্ভর করবে “the key (1NF), the whole key (2NF), and nothing but the key (3NF)”-এর ওপর। লক্ষ করুন, key যদি একটিমাত্র field হয় (composite না হয়), তবে partial dependency হতেই পারে না — এমন 1NF টেবিল আপনা থেকেই 2NF.
৬ · Sorting, indexing আর query-form-report
Sorting মানে record-গুলোকে কোনো field অনুযায়ী ক্রমে সাজিয়ে দেখানো — নাম বর্ণানুক্রমে, নম্বর বড় থেকে ছোট (ascending/descending). কিন্তু একটি বড় টেবিলে বারবার সাজানো ব্যয়বহুল, আর টেবিলকে একসাথে দুই ক্রমে (রোল আর নাম) সাজিয়ে রাখা যায় না। এর সমাধান index — বইয়ের শেষের নির্ঘণ্টের মতো: মূল পাতাগুলো যেমন আছে তেমনই থাকে, আলাদা একটি সাজানো তালিকা বলে দেয় কোন শব্দ কোন পাতায়।
# Roll Name
1 17 Nila
2 05 Tanvir
3 21 Mim
4 09 Arif
5 12 Sumi
6 30 Rafi
7 02 Lima
8 14 Sakib
17? না → 05? না → 21? না → 09? না → 12? হ্যাঁ ৫টি তুলনা। রোল 14 হলে ৮টি। না থাকলে (রোল 40)? সব ৮টি পড়ে তবে বোঝা যায়। ১০ লাখ সারি → সবচেয়ে খারাপ ক্ষেত্রে ১০ লাখ তুলনা
Roll → # 02 → 7 05 → 2 09 → 4 12 → 5 14 → 8 17 → 1 21 → 3 30 → 6 মূল টেবিল অপরিবর্তিত; index আলাদা জায়গায়
মাঝখানে 14 → 12 ছোট, বাঁয়ের অর্ধেক: 02 05 09 12 মাঝখানে 09 → 12 বড়, বাকি শুধু: 12 12 = 12 → সারি 5, Sumi ৩টি তুলনা; ১০ লাখ সারিতেও মাত্র ২০টির মতো
+ খোঁজা, সাজানো আর join অনেক দ্রুত
− বাড়তি জায়গা লাগে
− প্রতিটি INSERT/UPDATE-এ index-ও বদলাতে হয়
→ যে field দিয়ে প্রায়ই খোঁজা হয়, শুধু সেগুলোতে index
primary key-তে DBMS নিজেই index বানায়
- ভর্তির ক্রমে রাখা টেবিল। record-গুলো যে ক্রমে ঢুকেছে, সেভাবেই আছে — রোলের কোনো ক্রম নেই। খুঁজছি রোল ১২.
- index ছাড়া: এক এক করে। DBMS-কে প্রথম সারি থেকে প্রতিটি পড়ে মেলাতে হয় — একে বলে full table scan. ৮ সারিতে সমস্যা নেই; NID ডেটাবেসের মতো কোটি সারিতে একটি খোঁজেই অনেকটা সময় যাবে, আর একসাথে হাজার মানুষ খুঁজলে সার্ভার আটকে যাবে।
- index বানানো। Roll অনুযায়ী সাজানো একটি আলাদা তালিকা, প্রতিটি রোলের পাশে মূল সারির ঠিকানা। মূল টেবিল নড়ল না — তাই অন্য field-এর (যেমন Name) আরেকটি index-ও রাখা যায়।
- index দিয়ে: অর্ধেক অর্ধেক বাদ। সাজানো তালিকায় মাঝখান দেখে প্রতিবার অর্ধেক বাদ দেওয়া যায় — অভিধানে শব্দ খোঁজার মতো। প্রতি ধাপে অর্ধেক কমে বলে ১০ লাখ সারিতেও ২০টির মতো তুলনা যথেষ্ট (২-এর ২০ ঘাত প্রায় ১০ লাখ)। আসল DBMS এর জন্য B-tree নামের একটি গাছ-কাঠামো ব্যবহার করে, ধারণা একই।
- index-এর দাম। index জায়গা নেয়, আর নতুন record ঢোকালে বা বদলালে index-ও হালনাগাদ করতে হয় — তাই লেখা একটু ধীর হয়। নিয়ম: যে field দিয়ে প্রায়ই খোঁজা বা join হয় (primary key, foreign key, NID নম্বর), সেখানে index; বাকিগুলোতে নয়।
Query, Form আর Report — Access-এর চার স্তম্ভ
MS Access খুললে বাঁ দিকে কয়েক ধরনের object দেখবেন। HSC ICT-তে এদের কাজ জিজ্ঞেস করা হয়:
| Object | কাজ | উদাহরণ |
|---|---|---|
| Table | ডেটা আসলে যেখানে জমা থাকে | Students, Results |
| Query | ডেটাবেসকে প্রশ্ন — শর্ত মিলিয়ে record বাছাই, সাজানো, হিসাব, কয়েক টেবিল জোড়া | “ICT-তে ৮০-র বেশি পাওয়া ছাত্রদের তালিকা” |
| Form | ডেটা ঢোকানো আর দেখার সুন্দর পর্দা — ব্যবহারকারী টেবিল সরাসরি দেখেন না | ভর্তির ফর্ম, ড্রপডাউনসহ |
| Report | ছাপার উপযোগী সাজানো ফল, যোগফল আর দলসহ | শ্রেণিভিত্তিক মার্কশিট, মাসিক বেতনের রিপোর্ট |
ওয়েবসাইটেও একই ভাগ: পর্ব ৩৭-এর HTML form হলো Form-এর কাজ, সার্ভারের কোড পাঠায় query, আর ফল দেখানো পাতাটি Report. Access-এ Create → Query Design দিয়ে মাউসে query বানানো যায়; ভেতরে Access আসলে SQL-ই লেখে — View → SQL View দিলে দেখা যায়।
৭ · Data integrity, validation আর ডেটাবেসের নিরাপত্তা
Data integrity মানে ডেটা সঠিক, সম্পূর্ণ আর সঙ্গতিপূর্ণ থাকা। পর্ব ১১-এর data validation স্প্রেডশিটে “পাহারাদার” ছিল — কপি-পেস্টে এড়ানো যেত। ডেটাবেসে নিয়মগুলো DBMS নিজে প্রয়োগ করে, কোনো পথেই এড়ানো যায় না। তিন ধরনের integrity:
- Entity integrity: primary key কখনো ফাঁকা বা দ্বৈত নয়।
- Referential integrity: foreign key-র প্রতিটি মান অন্য টেবিলে সত্যিই আছে — রোল ১৫-র মতো “অনাথ” ফল ঢুকতে পারে না, আর যে ছাত্রের ফল আছে তাকে সরাসরি মোছা যায় না। Access-এ Database Tools → Relationships → দুই টেবিল জুড়ে Enforce Referential Integrity-তে টিক।
- Domain integrity: প্রতিটি field-এ শুধু বৈধ মান — সঠিক data type, আর validation rule. Access-এ field-এর Properties → Validation Rule:
Between 0 And 100, আর Validation Text: “নম্বর ০ থেকে ১০০-এর মধ্যে হবে”.
নিরাপত্তার স্তর
🔑 অনুমতি (access control)
প্রত্যেকে শুধু ততটুকু, যতটুকু তাঁর কাজের জন্য দরকার। শিক্ষক নিজের বিষয়ের নম্বর লেখেন, হিসাবরক্ষক বেতন দেখেন, ছাত্র শুধু নিজের ফল। একে বলে least privilege.
লগইন + ভূমিকা অনুযায়ী অধিকার💾 Backup
নিয়মিত কপি, অন্তত একটি অন্য জায়গায় — আগুন, হার্ডডিস্ক নষ্ট বা ransomware হলেও ফেরা যায়। আর মাঝে মাঝে backup থেকে ফিরিয়ে পরীক্ষা করুন — না খোলা backup আসলে backup নয়।
পর্ব ০৪-এর 3-2-1 নিয়ম🔒 এনক্রিপশন
ডেটাকে একটি key দিয়ে এমনভাবে বদলানো, যাতে key ছাড়া পড়া না যায়। যেমন প্রতিটি অক্ষর ৩ ঘর সরালে DATA হয় GDWD (Caesar cipher). আসল DBMS অনেক শক্তিশালী পদ্ধতি ব্যবহার করে; পাসওয়ার্ড তো এনক্রিপ্ট নয়, hash করে রাখা হয়।
📜 Audit log
কে, কখন, কোন record দেখল বা বদলাল — তার লিখিত হিসাব। ফলাফল বদলানো বা তথ্য পাচারের মতো ঘটনায় এটিই প্রমাণ।
সন্দেহজনক আচরণ ধরাবাস্তব আক্রমণের একটি পরিচিত ধরনের নাম জেনে রাখুন — SQL injection. দুর্বলভাবে লেখা ওয়েবসাইট যদি ব্যবহারকারীর লেখা ইনপুটকে সরাসরি query-র লেখার সাথে জুড়ে দেয়, তাহলে চতুর ইনপুট query-র মানেই বদলে দিতে পারে, আর অন্যের ডেটা বেরিয়ে যেতে পারে। প্রতিরোধ সহজ ও প্রমাণিত: ইনপুট কখনো query-র লেখায় জোড়া নয়, সবসময় parameterized query (আলাদা ঘরে মান পাঠানো), সাথে ইনপুট যাচাই আর ন্যূনতম অনুমতি। পর্ব ৪২-এ SQL শেখার সময় এর নিরাপদ রূপটি দেখবেন; সাইবার নিরাপত্তার বড় ছবি পর্ব ৪৩-এ।
৮ · বাংলাদেশের বড় ডেটাবেস, গোপনীয়তা আর NoSQL
আপনি প্রতিদিন না জেনেই বহু ডেটাবেস ব্যবহার করেন:
- NID ডেটাবেস: নির্বাচন কমিশনের কাছে কোটি কোটি নাগরিকের নাম, ঠিকানা, ছবি, আঙুলের ছাপ। ব্যাংক, মোবাইল অপারেটর আর বিভিন্ন সংস্থা অনুমতি নিয়ে এখান থেকে পরিচয় যাচাই করে — SIM কেনার সময় আঙুলের ছাপ মেলানো এর উদাহরণ।
- শিক্ষা বোর্ডের ফল: ফল প্রকাশের দিন লাখ লাখ শিক্ষার্থী একসাথে রোল আর রেজিস্ট্রেশন নম্বর দিয়ে খোঁজে — index ছাড়া এটি অসম্ভব হতো।
- BRTA: গাড়ির নিবন্ধন আর ড্রাইভিং লাইসেন্সের রেকর্ড — গাড়ির নম্বর দিয়ে মালিক, লাইসেন্স নম্বর দিয়ে চালক।
- ব্যাংক আর MFS: প্রতিটি লেনদেন একটি record; টাকা এক হিসাব থেকে কাটা আর অন্যটিতে যোগ — দুটি কাজ হয় একসাথে, নয়তো একটিও নয়। এই “সব বা কিছুই না” নিশ্চয়তার নাম transaction.
যত বড় ডেটাবেস, তত বড় দায়িত্ব। কোটি মানুষের ব্যক্তিগত তথ্য এক জায়গায় থাকলে একটি দুর্বলতাই কোটি মানুষকে ঝুঁকিতে ফেলে — প্রতারণা, ভুয়া SIM, ভুয়া ঋণ। তাই নকশার শুরুতেই প্রশ্ন: এই তথ্য কি আসলেই দরকার? একে বলে data minimization — যে তথ্য রাখেননি, তা কখনো ফাঁস হতে পারে না। ব্যক্তিগত তথ্য, গোপনীয়তা আর এ-সংক্রান্ত আইনের আলোচনা পর্ব ৪৫-এ।
NoSQL — এক লাইনে
সব ডেটা টেবিলে সুন্দর বসে না — সোশ্যাল মিডিয়ার পোস্ট, সেন্সরের অবিরাম মাপজোখ, অ্যাপের ক্যাশ। এদের জন্য NoSQL ডেটাবেস (MongoDB, Redis, Cassandra ইত্যাদি) ডেটা রাখে document, key-value বা অন্য কাঠামোয়, কঠোর schema ছাড়া, বহু সার্ভারে ছড়িয়ে — তবে বেশিরভাগ ব্যবসার মূল হিসাব আজও relational ডেটাবেসেই থাকে।
আরও গভীরে: transaction-এর চার গুণ (ACID), BCNF আর উচ্চতর normal form, functional dependency-র গাণিতিক নিয়ম, B-tree index-এর গঠন আর query optimizer কীভাবে join-এর ক্রম বাছে — এগুলো একজন ডেটাবেস প্রকৌশলীর দৈনন্দিন বিষয়। ধাপে ধাপে শিখতে দেখুন ABCL TECH-এর DBMS ও SQL কোর্স.
পরীক্ষা ও ইন্টারভিউতে: HSC ICT-র MCQ ও সৃজনশীল অংশে, আর ব্যাংক ও সরকারি চাকরির কম্পিউটার অংশে এ ধরনের প্রশ্ন প্রায়ই আসে —
- Primary key আর foreign key-র পার্থক্য? — primary key নিজের টেবিলের প্রতিটি record-কে অনন্যভাবে চেনায়; foreign key অন্য টেবিলের primary key-কে নির্দেশ করে দুই টেবিল জোড়ে।
- কয়েকটি DBMS-এর নাম লিখুন। — MS Access, MySQL, Oracle, Microsoft SQL Server, PostgreSQL, SQLite.
- One-to-many সম্পর্কের উদাহরণ? — এক শ্রেণিতে অনেক ছাত্র; এক গ্রাহকের অনেক লেনদেন।
- Normalization কী? — redundancy আর anomaly দূর করতে টেবিলকে নিয়ম মেনে (1NF, 2NF, 3NF) ছোট সম্পর্কিত টেবিলে ভাঙার পদ্ধতি।
- Field আর record-এর পার্থক্য? — field হলো একটি কলাম (যেমন Name); record হলো একটি সারি — একজনের সব field মিলিয়ে।
৯ · AI-এর যুগে — schema বানায় AI, যাচাই করেন আপনি
ChatGPT, Gemini বা Claude-এর মতো চ্যাটবটকে “একটি কোচিং সেন্টারের ডেটাবেসের টেবিল বানিয়ে দাও” বললে কয়েক সেকেন্ডে টেবিল, field, data type আর SQL লিখে দেয়। শুরু হিসেবে চমৎকার। কিন্তু AI-এর নকশায় যে ভুলগুলো প্রায়ই থাকে, তা কোনো ত্রুটি-বার্তা দেয় না — মাস কয়েক পরে anomaly হয়ে দেখা দেয়: মোবাইল নম্বর Number হিসেবে, M:N সম্পর্কে কমা দিয়ে লেখা তালিকা, নামকে primary key, foreign key ঘোষণাই নেই, আর “পরে কাজে লাগতে পারে” ভেবে NID, জন্মতারিখ, বাবা-মায়ের পেশা — সব রাখা।
ভালো প্রশ্নে থাকে: প্রতিষ্ঠানের কাজ, কোন প্রশ্নের উত্তর ডেটাবেস দেবে, কোন তথ্য একেবারেই রাখা যাবে না — আর নকশা ব্যাখ্যা করার অনুরোধ:
AI-এর নকশা ব্যবহারের আগে — চেকলিস্ট
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন। ডেটাবেসের ইতিহাস গণিত, ব্যবসা আর নিরাপত্তার শিক্ষায় ভরা।
প্র ০১১৯৭০ সালে IBM-এর গবেষক E. F. Codd relational model প্রস্তাব করেন। তবু IBM নিজেই কেন এটি বাজারে আনতে দেরি করল?
১৯৬০-এর দশকের ডেটাবেসগুলো ছিল hierarchical বা network ধরনের। ডেটা থাকত পয়েন্টার দিয়ে জোড়া রেকর্ডের গাছ বা জালে, আর প্রোগ্রামারকে জানতে হতো কোন রেকর্ড থেকে কোন পথে হেঁটে গেলে কাঙ্ক্ষিত ডেটা মেলে। IBM-এর নিজের পণ্য IMS ছিল এমন একটি hierarchical ব্যবস্থা — Apollo চন্দ্রাভিযানের যন্ত্রাংশের হিসাব রাখার প্রকল্প থেকে জন্ম, আর বড় বড় কোম্পানিতে বিক্রি হয়ে IBM-কে ভালো আয় দিত। ডেটার গঠন বদলালে প্রোগ্রামও নতুন করে লিখতে হতো।
ইংল্যান্ডে জন্ম নেওয়া গণিতবিদ Edgar F. Codd তখন IBM-এর San Jose গবেষণাগারে কাজ করতেন। ১৯৭০ সালের জুনে Communications of the ACM-এ প্রকাশিত হয় তাঁর প্রবন্ধ “A Relational Model of Data for Large Shared Data Banks”. মূল কথা: ডেটাকে গণিতের relation — অর্থাৎ সারি আর কলামের টেবিল — হিসেবে ভাবুন; ব্যবহারকারী বলবেন কী চান, কীভাবে খুঁজতে হবে তা ঠিক করবে সিস্টেম। ডেটা কীভাবে ডিস্কে রাখা আছে, প্রোগ্রামকে তা জানতেই হবে না।
IBM-এর দ্বিধার কারণ ছিল কয়েকটি। এক, IMS থেকে আয় — নিজের সফল পণ্যকে নিজেই পুরোনো করে দেওয়ার ঝুঁকি। দুই, অনেক প্রকৌশলীর সন্দেহ: টেবিল জোড়া দেওয়ার কাজ যন্ত্র নিজে করলে সেকালের ধীর কম্পিউটারে গতি পাওয়া যাবে কি? তবু ১৯৭০-এর দশকের মাঝামাঝি IBM-এর System R প্রকল্প প্রমাণ করে যে এটি সম্ভব; সেখানেই Donald Chamberlin আর Raymond Boyce তৈরি করেন SEQUEL ভাষা, যা পরে নাম বদলে হয় SQL. একই সময়ে Berkeley বিশ্ববিদ্যালয়ে Michael Stonebraker-এর Ingres প্রকল্পও relational ধারণা বাস্তবে দেখায়। কিন্তু IBM-এর প্রথম বাণিজ্যিক relational পণ্য SQL/DS আসে ১৯৮১ সালে, আর DB2 ১৯৮৩ সালে — ততদিনে একটি ছোট কোম্পানি বাজারে ঢুকে পড়েছে (পরের প্রশ্ন)। ১৯৮১ সালে Codd কম্পিউটার বিজ্ঞানের সর্বোচ্চ সম্মান Turing Award পান।
মূল উপলব্ধি: ভালো ধারণা যথেষ্ট নয় — প্রতিষ্ঠিত প্রতিষ্ঠান প্রায়ই নিজের লাভজনক পুরোনো পণ্য বাঁচাতে নতুনকে ধীর করে, আর সেই ফাঁকে অন্যরা এগিয়ে যায়। আর “কী চাই তা বলুন, কীভাবে তা যন্ত্র ঠিক করুক” — এই বিমূর্ততাই relational ডেটাবেসকে পঞ্চাশ বছর টিকিয়ে রেখেছে।
প্র ০২১৯৭৯ সালে Oracle কীভাবে প্রথম দিকের বাণিজ্যিক SQL ডেটাবেস হয়ে উঠল, আর এর পর ডেটাবেস শিল্প কীভাবে গড়ে উঠল?
১৯৭৭ সালে ক্যালিফোর্নিয়ায় Larry Ellison, Bob Miner আর Ed Oates মিলে একটি ছোট সফটওয়্যার কোম্পানি খোলেন — নাম Software Development Laboratories. তাঁরা IBM-এর System R নিয়ে প্রকাশিত গবেষণাপত্রগুলো পড়ে বুঝেছিলেন, relational ডেটাবেস আর SQL-ই ভবিষ্যৎ, অথচ IBM তখনো এটি বিক্রি করছে না। তাঁরা IBM-এর SQL-এর সাথে মিল রেখে নিজেদের ডেটাবেস লেখেন, যাতে পরে IBM বাজারে এলে গ্রাহকেরা সহজে মানিয়ে নিতে পারেন।
১৯৭৯ সালে কোম্পানি (তখন নাম Relational Software, Inc.) বাজারে আনে Oracle Version 2 — প্রথম দিকের বাণিজ্যিকভাবে পাওয়া SQL-ভিত্তিক relational ডেটাবেসগুলোর একটি। মজার তথ্য: “Version 1” কখনো ছিলই না; প্রথম সংস্করণে কেউ ভরসা করবে না ভেবে সরাসরি ২ নাম দেওয়া হয়। “Oracle” নামটি এসেছিল প্রতিষ্ঠাতাদের আগের একটি সরকারি প্রকল্পের সাংকেতিক নাম থেকে, পরে কোম্পানির নামও তাই হয়।
এরপর আশি আর নব্বইয়ের দশকে ডেটাবেস হয়ে ওঠে বিশাল শিল্প। IBM আনে DB2; Microsoft ১৯৮৯ সালে SQL Server আনে (শুরুতে Sybase-এর সাথে মিলে); Informix, Sybase-এর মতো প্রতিদ্বন্দ্বীরাও ছিল। ব্যাংক, এয়ারলাইন, টেলিকম — যেখানে প্রতিটি লেনদেনের নির্ভুল হিসাব জরুরি — সেখানে Oracle শক্ত অবস্থান নেয়; বাংলাদেশেরও অনেক ব্যাংকের core banking ব্যবস্থার পেছনে এমন বাণিজ্যিক ডেটাবেস। নব্বইয়ের মাঝামাঝি এলো ওপেন সোর্স ধারা — ১৯৯৫ সালে MySQL, আর Berkeley-র Postgres প্রকল্প থেকে PostgreSQL. বিনামূল্যের এই ডেটাবেসগুলোই ইন্টারনেট যুগের লাখো ওয়েবসাইট চালু রাখে। পরে Oracle নিজেই Sun Microsystems কিনে নেওয়ার মধ্য দিয়ে MySQL-এর মালিক হয়, আর MySQL-এর মূল নির্মাতাদের একজন MariaDB নামে আলাদা শাখা শুরু করেন।
মূল উপলব্ধি: গবেষণা প্রকাশিত হলে তা সবার। যে প্রতিষ্ঠান গবেষণাকে দ্রুত ব্যবহারযোগ্য পণ্যে বদলায়, বাজার প্রায়ই তার হয় — আর মানদণ্ড (SQL) মেনে চলা ছোট কোম্পানিকেও বড়দের পাশে দাঁড়াতে দেয়।
প্র ০৩২০২৩ সালে বাংলাদেশে নাগরিকদের ব্যক্তিগত তথ্য উন্মুক্ত হওয়ার খবর ব্যাপক আলোচনা তোলে। ডেটাবেসের নিরাপত্তা নিয়ে এ ধরনের ঘটনা কী শেখায়?
২০২৩ সালের জুলাইয়ে আন্তর্জাতিক প্রযুক্তি-সংবাদমাধ্যমে খবর আসে, একটি সরকারি ওয়েবসাইটের দুর্বলতার কারণে বহু নাগরিকের নাম, ফোন নম্বর, ইমেইল ঠিকানা আর NID নম্বরের মতো ব্যক্তিগত তথ্য ইন্টারনেটে খোলা অবস্থায় পাওয়া যাচ্ছিল। একজন নিরাপত্তা গবেষক ঘটনাক্রমে বিষয়টি খুঁজে পান। সরকারি পর্যায় থেকে বলা হয়, এটি হ্যাকিং নয়, ওয়েবসাইটের কারিগরি দুর্বলতা। একই বছরের পরের দিকে Telegram-এর একটি বটের মাধ্যমে NID-সংক্রান্ত তথ্য পাওয়া যাওয়ার খবরও আসে, আর আলোচনায় উঠে আসে — NID ডেটাবেস থেকে যাচাইয়ের অনুমতি পাওয়া কোনো অংশীদার প্রতিষ্ঠানের অ্যাক্সেসের অপব্যবহার হয়ে থাকতে পারে।
খুঁটিনাটি যা-ই হোক, ডেটাবেস নিরাপত্তার কয়েকটি সাধারণ শিক্ষা এখান থেকে স্পষ্ট। এক, দুর্বলতম প্রবেশপথই পুরো ব্যবস্থার নিরাপত্তা। মূল ডেটাবেস যত সুরক্ষিতই হোক, তার সাথে যুক্ত একটি দুর্বল ওয়েবসাইট বা একটি অসাবধান অংশীদারই যথেষ্ট। দুই, least privilege. যে প্রতিষ্ঠানের শুধু “এই নাম আর এই NID কি মেলে — হ্যাঁ/না” জানা দরকার, তাকে পুরো record দেখানো উচিত নয়। তিন, নজরদারি। একটি অ্যাকাউন্ট থেকে অস্বাভাবিক সংখ্যক অনুসন্ধান হলে audit log আর সীমা (rate limit) সেটা দ্রুত ধরতে পারে। চার, data minimization আর এনক্রিপশন — যে তথ্য রাখা হয়নি, তা ফাঁস হয় না; আর এনক্রিপ্ট করা কপি চুরি হলেও পড়া কঠিন। পাঁচ, দায়িত্বশীল প্রকাশ। কোনো গবেষক দুর্বলতা জানালে দ্রুত সাড়া দেওয়ার একটি প্রক্রিয়া থাকা জরুরি।
সাধারণ নাগরিকের জন্যও শিক্ষা আছে: NID নম্বর আর জন্মতারিখ ফাঁস হলে কেউ আপনার নামে প্রতারণার চেষ্টা করতে পারে, তাই অপরিচিত কলে বা লিংকে OTP বা ব্যক্তিগত তথ্য দেবেন না (পর্ব ৪৩), আর কোনো অ্যাপ অপ্রয়োজনে NID-র ছবি চাইলে প্রশ্ন করুন।
মূল উপলব্ধি: বড় ডেটাবেসের নিরাপত্তা শুধু কারিগরি বিষয় নয় — কে কতটুকু দেখবে, কতটুকু রাখা হবে, আর ভুল হলে কত দ্রুত ধরা পড়বে, এই তিন নীতির বিষয়। কোটি মানুষের তথ্য এক জায়গায় রাখার সিদ্ধান্তের সাথে সমান মাপের দায়িত্বও আসে।
প্র ০৪Normalization যদি এত ভালো হয়, বড় বড় সিস্টেম কেন ইচ্ছা করে denormalization করে — একই তথ্য একাধিক জায়গায় রাখে?
Normalization-এর লক্ষ্য সঠিকতা: প্রতিটি তথ্য এক জায়গায়, তাই update anomaly অসম্ভব। কিন্তু এর একটি দাম আছে — প্রশ্নের উত্তর দিতে কয়েকটি টেবিল join করতে হয়। চারটি টেবিল জোড়া দেওয়া মানে চারটি index খোঁজা, আর কোটি সারির টেবিলে সেটা সময়সাপেক্ষ। যে সিস্টেমে লেখা কম, কিন্তু পড়া খুব বেশি, সেখানে এই খরচ বারবার দিতে হয়।
তাই প্রকৌশলীরা কখনো কখনো জেনেশুনে denormalization করেন — নিয়ন্ত্রিতভাবে কিছু তথ্যের কপি রাখেন। উদাহরণ: একটি ই-কমার্স সাইটে প্রতিটি অর্ডারের মোট দাম আলাদা করে লিখে রাখা, যদিও তা অর্ডারের পণ্যগুলো থেকে হিসাব করা যায়; বা একটি পোস্টের পাশে “লাইক সংখ্যা” রেখে দেওয়া, প্রতিবার গোনার বদলে। ডেটা বিশ্লেষণের জন্য তৈরি data warehouse-এ (Ralph Kimball-এর জনপ্রিয় “star schema” নকশা) ইচ্ছা করেই কম টেবিলে বেশি তথ্য রাখা হয়, কারণ সেখানে ডেটা প্রায় শুধু পড়া হয়, আর লাখ সারির সারাংশ দ্রুত চাই। অনেক NoSQL ডেটাবেসও একটি document-এর ভেতরেই সম্পর্কিত তথ্য রাখে, যাতে এক খোঁজেই সব পাওয়া যায়।
লক্ষ করুন, এখানে একটি দ্বিতীয় সমস্যাও আছে: “অর্ডারের সময়ের দাম” আসলে আলাদা তথ্য — পণ্যের দাম পরে বদলালেও পুরোনো অর্ডারের দাম বদলানো উচিত নয়। তাই কিছু “কপি” আসলে redundancy-ই নয়, ইতিহাস। ভালো নকশাকার এই পার্থক্য বোঝেন।
denormalization-এর দাম হলো ফিরে আসা ঝুঁকি — কপিগুলো মেলানো রাখতে হয়। এর জন্য trigger, পটভূমিতে চলা হালনাগাদ, বা materialized view-এর মতো কৌশল লাগে, আর কোনটি “মূল সত্য”, তা স্পষ্ট লেখা থাকতে হয়। প্রচলিত নিয়ম: আগে normalize করুন, মেপে দেখুন কোথায় সত্যিই ধীর, তারপর শুধু সেখানে ভেবেচিন্তে denormalize করুন।
মূল উপলব্ধি: নকশায় “সবসময় সঠিক” নিয়ম খুব কম — প্রায় সবই আপস। normalization সঠিকতা কেনে গতির বিনিময়ে, denormalization গতি কেনে জটিলতার বিনিময়ে। কোনটি বেছে নিচ্ছেন আর কেন, তা জানাটাই দক্ষতা।
প্র ০৫পৃথিবীতে সবচেয়ে বেশি চলা ডেটাবেস কোনটি? SQLite কেন প্রায় প্রতিটি ফোনে আছে, অথচ বেশিরভাগ মানুষ নামই শোনেনি?
MySQL, Oracle, PostgreSQL — এরা সবাই client-server ডেটাবেস: একটি আলাদা সার্ভার প্রোগ্রাম সবসময় চলে, অন্য প্রোগ্রামগুলো নেটওয়ার্কে তার কাছে প্রশ্ন পাঠায়। ২০০০ সালে মার্কিন প্রোগ্রামার D. Richard Hipp মার্কিন নৌবাহিনীর একটি জাহাজের সফটওয়্যারের কাজ করতে গিয়ে বিরক্ত হন — ডেটাবেস সার্ভার বন্ধ থাকলে পুরো প্রোগ্রামই অচল। তিনি এমন ডেটাবেস বানাতে চাইলেন, যার কোনো সার্ভার নেই: একটি ছোট লাইব্রেরি, যা প্রোগ্রামের ভেতরেই থাকে, আর পুরো ডেটাবেস একটি সাধারণ ফাইলে। নাম দেন SQLite, আর কোডটি দিয়ে দেন public domain-এ — যে কেউ বিনামূল্যে, কোনো শর্ত ছাড়াই ব্যবহার করতে পারে।
এই তিনটি গুণ — সার্ভার নেই, এক ফাইল, কোনো লাইসেন্সের ঝামেলা নেই — একে প্রায় সর্বত্র পৌঁছে দেয়। প্রতিটি Android ফোন আর iPhone-এ এটি আছে; কন্টাক্ট, মেসেজ, অনেক অ্যাপের সেটিংস আর চ্যাটের ইতিহাস প্রায়ই SQLite ফাইলে থাকে। Chrome, Firefox আর Safari ব্রাউজার ইতিহাস ও বুকমার্ক রাখে এতে; অনেক টিভি, গাড়ির ড্যাশবোর্ড, এমনকি বিমানের সফটওয়্যারেও এটি চলে। SQLite-এর নিজের ওয়েবসাইটের হিসাবে সক্রিয় SQLite ডেটাবেসের সংখ্যা এক ট্রিলিয়নের (১ লক্ষ কোটি) বেশি — অন্য সব ডেটাবেস মিলিয়েও এর কাছাকাছি নয়।
এত জায়গায় চলে বলে এর পরীক্ষাও অসাধারণ কঠোর। SQLite-এর পরীক্ষার কোড মূল কোডের চেয়ে বহুগুণ বড়, আর বিমান-সফটওয়্যারের মানদণ্ডে প্রতিটি শাখা পরীক্ষিত। তবে এর সীমাও আছে: একসাথে অনেক লেখক থাকলে (যেমন হাজার মানুষের একটি ওয়েবসাইট) client-server ডেটাবেস ভালো। SQLite-এর নির্মাতারাই বলেন — এটি Oracle-এর বিকল্প নয়, fopen()-এর বিকল্প, অর্থাৎ সাধারণ ফাইলে ডেটা লেখার বদলে একটি নির্ভরযোগ্য ছোট ডেটাবেস।
মূল উপলব্ধি: সবচেয়ে সফল প্রযুক্তি প্রায়ই অদৃশ্য — সে চুপচাপ অন্য পণ্যের ভেতরে কাজ করে। আর সরলতা (সার্ভার নেই, এক ফাইল) কখনো কখনো শক্তিশালী বৈশিষ্ট্যের চেয়েও বেশি দূর যায়।
অনুশীলন
কাগজে-কলমে বা Access/Excel খুলে করুন। প্রতিটির শেষে উত্তর মিলিয়ে নিন।
-
পরিভাষা চেনা: একটি লাইব্রেরির
Books(BookID, Title, Author, Price)টেবিলে ২০০টি বই আছে। এখানে field কয়টি, record কয়টি? কোনটি primary key হওয়া উচিত, আর Title কেন নয়?field ৪টি (BookID, Title, Author, Price), record ২০০টি — প্রতিটি বই একটি সারি। primary key হবে BookID, কারণ এটি প্রতিটি বইকে অনন্যভাবে চেনায় আর কখনো ফাঁকা থাকে না। Title অনন্য নয় — একই বইয়ের একাধিক কপি বা একই নামের ভিন্ন লেখকের বই থাকতে পারে। লাইব্রেরিতে একই বইয়ের তিনটি কপি থাকলে আসলে প্রতিটি কপির জন্য আলাদা ID লাগে — এটাই কারণ যে লাইব্রেরি প্রতিটি বইয়ে আলাদা Accession নম্বর লাগায়।
-
সম্পর্ক চেনা: নিচের প্রতিটি জোড়া 1:1, 1:N না M:N? (ক) জেলা — উপজেলা, (খ) ডাক্তার — রোগী (একজন রোগী কয়েকজন ডাক্তার দেখান), (গ) নাগরিক — পাসপোর্ট (একসময়ে একটি সক্রিয়), (ঘ) bKash অ্যাকাউন্ট — লেনদেন।
(ক) 1:N — এক জেলায় অনেক উপজেলা, কিন্তু প্রতিটি উপজেলা একটি জেলারই। উপজেলা টেবিলে DistrictID foreign key. (খ) M:N — মাঝে Appointments টেবিল (DoctorID, PatientID, তারিখ)। (গ) 1:1 — একজন নাগরিকের একসময়ে একটি সক্রিয় পাসপোর্ট, প্রতিটি পাসপোর্ট একজনের। (ঘ) 1:N — এক অ্যাকাউন্টের অনেক লেনদেন; Transactions টেবিলে AccountNo foreign key. (বাস্তবে প্রতিটি লেনদেনে দুটি অ্যাকাউন্ট থাকে — প্রেরক আর প্রাপক — তাই দুটি foreign key.)
-
Normalization: একটি দোকানের শিট:
Orders(OrderNo, Date, CustomerName, CustomerPhone, ProductCode, ProductName, Price, Qty). এক অর্ডারে কয়েকটি পণ্য থাকে। 3NF পর্যন্ত টেবিলগুলো লিখুন।1NF-এ key (OrderNo, ProductCode). 2NF: Date আর গ্রাহকের তথ্য নির্ভর করে শুধু OrderNo-র ওপর; ProductName, Price শুধু ProductCode-এর ওপর — আলাদা। 3NF: অর্ডারের মধ্যে OrderNo → গ্রাহক → CustomerPhone একটি transitive dependency, তাই গ্রাহক আলাদা টেবিল। ফল:
Customers(CustomerID, Name, Phone),Orders(OrderNo, Date, CustomerID),Products(ProductCode, ProductName, Price),OrderItems(OrderNo, ProductCode, Qty, UnitPrice). শেষের UnitPrice ইচ্ছা করে রাখা — বিক্রির দিনের দাম, যা পরে পণ্যের দাম বদলালেও বদলাবে না (ভাবনার প্রশ্ন ০৪)। -
Access-এ হাতে-কলমে: Access-এ Students আর Results দুটি টেবিল বানান (data type সহ), Relationships থেকে Roll দিয়ে জুড়ে Enforce Referential Integrity দিন। তারপর Results-এ এমন একটি রোল লিখে দেখুন, যা Students-এ নেই। (Access না থাকলে ওপরের JS প্রোগ্রামে
results-এ নতুন একটি সারি যোগ করুন।)Access বার্তা দেবে যে সম্পর্কিত record না থাকায় এটি যোগ বা বদলানো যাবে না — referential integrity কাজ করছে। Students থেকে এমন ছাত্রকে মুছতে চাইলেও আটকাবে, যার ফল আছে (যদি না Cascade Delete চালু করেন — তখন ছাত্রের সাথে তার ফলও মুছে যায়, তাই সাবধানে)। JS প্রোগ্রামে যেমন
{ roll: 20, sub: "Math", marks: 50 }যোগ করলে নতুন একটিFK VIOLATIONলাইন আসবে। Roll field-এর data type দুই টেবিলে একই হতে হবে — নইলে Access সম্পর্কই বানাতে দেবে না।
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমডেটাবেসের ডেটার স্তরগুলো ছোট থেকে বড় ক্রমে সাজান (▲▼ চেপে সরান)
- 🔤 Character (বর্ণ)
- 🏷️ Field
- 📄 Record
- 🗂️ Table / File
- 🗄️ Database
Results টেবিলের Roll field, Students টেবিলের Roll (primary key)-কে নির্দেশ করে। Results টেবিলের Roll-কে কী বলে?
- Primary key
- Foreign key
- Candidate key
- Alternate key
একটি স্কুলে প্রতিটি শ্রেণির প্রতিটি শাখায় রোল ১ থেকে শুরু হয়। একজন ছাত্রকে অনন্যভাবে চিনতে কোনটি উপযুক্ত?
- শুধু Roll
- Name
- (Class, Roll)
- (Class, Section, Roll) — composite key
একজন ছাত্র অনেক বিষয় নেয়, আর একটি বিষয় অনেক ছাত্র নেয়। relational ডেটাবেসে এই সম্পর্ক রাখার সঠিক উপায় কোনটি?
- Students টেবিলের একটি ঘরে সব বিষয় কমা দিয়ে লেখা
- Students টেবিলে Subject1, Subject2, Subject3 কলাম
- মাঝে একটি Enrollment টেবিল (Roll, SubCode), দুটিই foreign key
- Subjects টেবিলে একটি Roll কলাম
key (Roll, SubCode)-বিশিষ্ট একটি টেবিলে Name field শুধু Roll-এর ওপর নির্ভর করে। এই সমস্যা দূর হলে টেবিলটি কোন normal form-এর শর্ত পূরণ করবে?
- 2NF
- 1NF
- 3NF
- Denormalized form
একটি শিক্ষকের ফোন নম্বর টেবিলের ৪০০টি সারিতে লেখা আছে। নম্বর বদলানোর সময় কয়েকটি সারি বাদ পড়ায় একই শিক্ষকের দুটি নম্বর দেখা যাচ্ছে। এই সমস্যার নাম কী?
- Insertion anomaly
- Deletion anomaly
- Update anomaly
- Referential integrity
কোটি সারির একটি টেবিলে NID নম্বর দিয়ে প্রায়ই খোঁজা হয়, আর খোঁজা খুব ধীর। কোনটি সবচেয়ে কার্যকর সমাধান?
- প্রতিটি খোঁজার আগে পুরো টেবিল sort করা
- NID field-এ index তৈরি করা
- টেবিলটি অনেকগুলো Excel ফাইলে ভাগ করা
- একটি Report তৈরি করা
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- ডেটাবেস = সম্পর্কিত ডেটার সুশৃঙ্খল ভান্ডার; DBMS = যে সফটওয়্যার তা নিরাপদে রাখে, ভাগ করে আর প্রশ্নের উত্তর দেয় — Access, MySQL, Oracle, SQL Server, PostgreSQL, SQLite.
- field = কলাম, record = সারি, table = relation; স্তর: character → field → record → table → database.
- Primary key অনন্য ও NOT NULL; candidate থেকে বাছাই, বাকিরা alternate; কয়েক field মিলে composite; foreign key অন্য টেবিলের primary key-কে নির্দেশ করে।
- 1:1, 1:N, M:N — M:N ভাঙে মাঝের টেবিলে; ER diagram-এ আয়তক্ষেত্র, ডিম্বাকৃতি, হীরা।
- 1NF atomic মান, 2NF partial dependency নয়, 3NF transitive dependency নয় — প্রতিটি তথ্য একবার; index খোঁজা দ্রুত করে; নিরাপত্তা = অনুমতি, backup, এনক্রিপশন, ন্যূনতম ডেটা।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ৪২ · SQL — খোঁজা, সাজানো আর ছাঁকাপরবর্তী পর্বএই পর্বের টেবিলগুলোকে SQL দিয়ে প্রশ্ন করা।
- কম্পিউটার ফান্ডামেন্টালস ও ICT · কোর্স হোম৫৫টি পর্বপুরো কোর্সের রোডম্যাপ — কোন পর্ব কখন।
- DBMS ও SQLগভীরে যানER মডেল, normalization, transaction আর index — ডেটাবেসের পূর্ণাঙ্গ কোর্স।
- Data Scienceপাশের ট্র্যাকডেটাবেস থেকে তোলা ডেটার বিশ্লেষণ আর পরিসংখ্যান।