PgPostgreSQL English
ওপেন কোর্সওয়্যার · ডেটাবেস সিস্টেম

PostgreSQL,
শূন্য থেকে অ্যাডভান্সড

তেইশটি মডিউলের এই ক্লাস ধরে নেয় আপনি কিছুই জানেন না। ডেটাবেস কী থেকে শুরু করে রিকার্সিভ কুয়েরি, PL/pgSQL, রো লেভেল সিকিউরিটি, রেপ্লিকেশন ও pgvector পর্যন্ত সব আছে, সঙ্গে ব্রাউজারেই আসল PostgreSQL-এর প্র্যাকটিস ল্যাব।

মডিউল ০১ শুরু করুন →
1N1N studentsid PKfull_nameemail UNIQUEgpa coursesid PKcode UNIQUEtitlecredits enrollmentsstudent_id FKcourse_id FKgrade
সময়
≈ ৮০ ঘণ্টা
মডিউল
২৩
পূর্বশর্ত
একেবারেই কিছু নয়
ভার্সন
PostgreSQL 16+
  1. ভিত্তিমডিউল ০১ থেকে ০৮

    ডেটাবেস কী, Windows-এ ইনস্টল, SQL-এর মূল কথা, টেবিল, CRUD, কুয়েরি ও এক্সপ্রেশন।

  2. মধ্যম স্তরমডিউল ০৯ থেকে ১৪

    কনস্ট্রেইন্ট, ALTER, সাবকুয়েরি, ইনডেক্স, ফুল টেক্সট সার্চ ও ট্রানজ্যাকশন।

  3. অ্যাডভান্সডমডিউল ১৫ থেকে ২২

    উইন্ডো ফাংশন, রিকার্সন, PL/pgSQL, ট্রিগার, পার্টিশনিং, রেপ্লিকেশন, নিরাপত্তা, RLS ও pgvector।

মডিউল 01 · প্রাথমিক

শুরু এখানে: ক্লাস জিরো

এই কোর্স ধরে নিয়েছে আপনি কখনো কোড লেখেননি এবং ডেটাবেসের নামও শোনেননি। ক্লাসের মতো একটার পর একটা মডিউল পড়ুন। প্রতিটির পর উপরের বারের প্র্যাকটিস ল্যাব খুলে উদাহরণগুলো নিজে টাইপ করুন।

ডেটা কী?

ডেটা মানে লিখে রাখা তথ্য: শিক্ষার্থীর নাম, পণ্যের দাম, আজকের তাপমাত্রা। ব্যাংকিং, সোশ্যাল মিডিয়া, অনলাইন শপিং, সব অ্যাপ সারাদিন ডেটা জমা রাখে ও পড়ে।

ডেটাবেস কী?

ডেটাবেস হলো ডেটা গুছিয়ে ও নিরাপদে রাখার জায়গা, যাতে দ্রুত খুঁজে পাওয়া যায়। স্কুলের অফিসের কথা ভাবুন। কাগজের এলোমেলো স্তূপে কিছু খোঁজা কঠিন, কিন্তু লেবেল দেওয়া আলমারিসহ ফাইলিং সিস্টেমে সহজ। এই ফাইলিং সিস্টেম চালানো, অর্থাৎ কাগজ রাখা, খোঁজা ও রক্ষা করার প্রোগ্রামকে বলে DBMS (ডেটাবেস ম্যানেজমেন্ট সিস্টেম)। PostgreSQL তেমনই একটি।

টেবিল কী?

রিলেশনাল ডেটাবেসের ডেটা থাকে টেবিলে, স্প্রেডশিটের একটি শিটের মতো। কলাম হলো শিরোনাম, আর প্রতিটি সারি একটি রেকর্ড, এখানে একজন শিক্ষার্থী।

idfull_nameemailgpa
1Ayesha Rahmanayesha@uni.edu3.80
2Tanvir Hasantanvir@uni.edu3.40

SQL কী?

SQL (স্ট্রাকচার্ড কুয়েরি ল্যাঙ্গুয়েজ) দিয়ে ডেটাবেসের সঙ্গে কথা বলা হয়। আপনি বলেন কী চান, ডেটাবেস নিজে ঠিক করে কীভাবে দেবে। SELECT full_name FROM students প্রায় ইংরেজির মতো: "students থেকে পুরো নামগুলো দেখাও"।

PostgreSQL কী?

PostgreSQL (উচ্চারণ "পোস্টগ্রেস") একটি বিনামূল্যের ওপেন সোর্স DBMS। এটি সার্ভার হিসেবে চলে। রেস্তোরাঁর মতো: আপনি (ক্লায়েন্ট) ওয়েটারকে অর্ডার (SQL) দেন, রান্নাঘর (সার্ভার) তৈরি করে ফলাফল পাঠায়।

কীভাবে পড়বেন

  • সবুজ ব্যাজ প্রাথমিক, হলুদ মধ্যম, গোলাপি অ্যাডভান্সড। লাফিয়ে এগোবেন না।
  • প্রতিটি উদাহরণ নিজে টাইপ করুন। কোড ব্লকে চেষ্টা করুন চাপলে সেটি ল্যাবে চলে যাবে।
  • ভুল হওয়া স্বাভাবিক ও কাজের। ইচ্ছা করে ভাঙুন।
মডিউল 02 · প্রাথমিক

ভূমিকা ও সেটআপ

PostgreSQL একটি ওপেন সোর্স অবজেক্ট-রিলেশনাল ডেটাবেস, ৩০ বছরের বেশি সময় ধরে উন্নয়নাধীন। সঠিকতা, কঠোর SQL স্ট্যান্ডার্ড সমর্থন এবং সম্প্রসারণযোগ্যতার জন্য এটি সুপরিচিত: JSONB, ফুল টেক্সট সার্চ, PostGIS, কাস্টম টাইপ ও এক্সটেনশন।

ডেটা কীভাবে সাজানো থাকে

  1. ক্লাস্টারএকটি চলমান সার্ভার
  2. ডেটাবেসআলাদা সংগ্রহ
  3. স্কিমানেমস্পেস, ডিফল্ট public
  4. টেবিলসারি ও কলাম
Shell
# Debian or Ubuntu
sudo apt install postgresql
sudo -u postgres psql

# macOS (Homebrew)
brew install postgresql@16
brew services start postgresql@16
psql postgres

psql দিয়ে সংযোগ করে একটি ডেটাবেস বানান এবং ঘুরে দেখুন:

SQL
CREATE DATABASE university;
-- Meta commands work only inside psql.
-- \c connect, \l list databases, \dt list tables, \d describe, \q quit
\c university
মডিউল 03 · প্রাথমিক

Windows-এ PostgreSQL ইনস্টল

অফিসিয়াল ইনস্টলার প্রায় ৩০০ MB, এতে সার্ভার, psql কমান্ড লাইন ও pgAdmin অ্যাপ থাকে।

  1. postgresql.org/download/windows খুলে Download the installer চাপুন। Windows x86 64-এর জন্য সবচেয়ে নতুন ভার্সন (১৬ বা তার বেশি) নিন।
  2. নামানো .exe চালান এবং অ্যাডমিন অনুমতি দিন।
  3. ডিফল্ট ফোল্ডার রাখুন এবং এই কম্পোনেন্টগুলো টিক দেওয়া রাখুন: PostgreSQL Server, pgAdmin 4, Command Line Tools।
  4. সুপারইউজার postgres-এর জন্য একটি পাসওয়ার্ড দিন এবং কোথাও লিখে রাখুন। হারালে ফেরত পাওয়া কঠিন।
  5. ডিফল্ট পোর্ট 5432 ও ডিফল্ট লোকেল রেখে শেষ করুন।
  6. Start মেনু থেকে SQL Shell (psql) চালান। ডিফল্ট মানতে (সার্ভার, ডেটাবেস, পোর্ট, ইউজার) চারবার Enter চাপুন, তারপর পাসওয়ার্ড লিখুন। টাইপ করার সময় পাসওয়ার্ড দেখা যায় না, এটা স্বাভাবিক।
  7. ইনস্টল ঠিক হয়েছে কি না পরীক্ষা করুন:
SQL
SELECT version();
CREATE DATABASE university;
\c university

অন্য উপায়

PowerShell থেকে winget দিয়ে ইনস্টল করা যায়, অথবা কিছু ইনস্টল না করে Docker-এ PostgreSQL চালানো যায়।

Shell
# Optional: install with winget (PowerShell as Administrator)
winget install PostgreSQL.PostgreSQL.16

# Connect from PowerShell after adding C:\Program Files\PostgreSQL\16\bin to PATH
psql -U postgres -h localhost
Shell
docker run --name pg -e POSTGRES_PASSWORD=secret -p 5432:5432 -d postgres:16
docker exec -it pg psql -U postgres

সমস্যা হলে

সমস্যাসমাধান
psql is not recognizedStart মেনু থেকে SQL Shell (psql) চালান, অথবা PostgreSQL-এর bin ফোল্ডার PATH-এ যোগ করুন
password authentication failedpostgres-এর পাসওয়ার্ড ভুল হয়েছে। ইনস্টলের সময় দেওয়াটি ব্যবহার করুন
port 5432 already in useআরেকটি PostgreSQL চলছে। সেটি বন্ধ করুন, বা ইনস্টলে অন্য পোর্ট বাছুন
পাসওয়ার্ড টাইপ করলে কিছু দেখা যায় নাএটা স্বাভাবিক, শেল তা লুকায়। টাইপ করে Enter চাপুন
মডিউল 04 · প্রাথমিক

SQL-এর মূল কথা: প্রথম স্টেটমেন্ট

আসল কুয়েরির আগে ব্যাকরণ শিখুন। SQL স্টেটমেন্ট একটি বাক্যের মতো: কিওয়ার্ড বলে কী করতে হবে, বাকিটা বলে কীসের ওপর।

  • প্রতিটি স্টেটমেন্ট সেমিকোলন ; দিয়ে শেষ হয়।
  • SELECT-এর মতো কিওয়ার্ড ছোট বা বড় হাতের, দুই-ই চলে। রীতি: কিওয়ার্ড বড় হাতের, নাম ছোট হাতের।
  • লেখা থাকে সিঙ্গেল কোটে, যেমন 'এভাবে'। ডাবল কোট অস্বাভাবিক নামের জন্য।
  • মন্তব্য: -- এক লাইন বা /* অনেক লাইন */।
  • স্পেস ও নতুন লাইন গুরুত্বপূর্ণ নয়, তাই পড়তে সুবিধা হয় এমনভাবে সাজান।
  • নাম দিন lowercase_with_underscores রীতিতে, স্পেস ছাড়া।
SQL
-- Your first statements
SELECT 'Hello, PostgreSQL!';
SELECT 2 + 3 * 4 AS answer;
SELECT current_date, now();
SELECT 'Ayesha' || ' ' || 'Rahman' AS full_name;

স্টেটমেন্টের গঠন

SQL
SELECT full_name FROM students WHERE gpa > 3.5;
অংশঅর্থ
SELECT full_nameকোন কলাম দেখাবে
FROM studentsকোন টেবিল পড়বে
WHERE gpa > 3.5কোন সারি রাখবে
;স্টেটমেন্ট শেষ

পাঁচ ধরনের কমান্ড

গ্রুপকমান্ডকাজ
DDLCREATE, ALTER, DROPকাঠামো তৈরি ও বদল
DMLINSERT, UPDATE, DELETEডেটা বদল
DQLSELECTডেটা পড়া
DCLGRANT, REVOKEঅনুমতি নিয়ন্ত্রণ
TCLBEGIN, COMMIT, ROLLBACKপরিবর্তন নিরাপদে দলবদ্ধ করা

এরর মেসেজ পড়া

  • syntax error at or near "x": x শব্দের কাছে বানান বা চিহ্নের ভুল।
  • relation "x" does not exist: টেবিলের নাম ভুল, অথবা টেবিল এখনো বানানো হয়নি।
  • column "x" does not exist: কলামের বানান ভুল।
অনুশীলনএকটি স্টেটমেন্টে আপনার নিজের নাম ও আজকের তারিখ দেখান।
SQL
SELECT 'Your Name' AS name, current_date AS today;
মডিউল 05 · প্রাথমিক

টেবিল ও ডেটা টাইপ

টেবিলে সারি জমা থাকে, আর প্রতিটি কলামের একটি টাইপ থাকে যা PostgreSQL কার্যকর করে। সঠিক টাইপ বাছাই করাই ডেটা যাচাইয়ের সবচেয়ে সস্তা উপায়।

টাইপকখন ব্যবহার করবেন
SMALLINT, INTEGER, BIGINTক্রমশ বড় আকারের পূর্ণসংখ্যা
NUMERIC(p,s)নির্ভুল দশমিক সংখ্যা, যেমন টাকার অঙ্ক
TEXTযেকোনো দৈর্ঘ্যের লেখা (সীমা ব্যবসায়িক নিয়ম হলেই কেবল VARCHAR(n))
BOOLEANtrue বা false
DATE, TIMESTAMPTZতারিখ এবং সময়ের নির্দিষ্ট মুহূর্ত
UUIDবিশ্বজুড়ে অনন্য আইডি
JSONBইনডেক্সযোগ্য আধা-কাঠামোবদ্ধ ডকুমেন্ট
type[], ENUMতালিকা এবং ছোট নির্দিষ্ট লেবেলের সেট
SQL
CREATE TABLE students (
    id          BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    full_name   TEXT         NOT NULL,
    email       TEXT         NOT NULL UNIQUE,
    gpa         NUMERIC(3,2) CHECK (gpa BETWEEN 0 AND 4),
    enrolled_at TIMESTAMPTZ  NOT NULL DEFAULT now()
);
মডিউল 06 · প্রাথমিক

CRUD: তৈরি, পড়া, হালনাগাদ, মোছা

প্রতিদিনের চারটি কাজ হলো INSERT, SELECT, UPDATE ও DELETE। RETURNING দিয়ে দ্বিতীয় কুয়েরি ছাড়াই প্রভাবিত সারি ফেরত পাওয়া যায়, আর ON CONFLICT ইনসার্টকে আপসার্টে পরিণত করে।

SQL
INSERT INTO students (full_name, email, gpa)
VALUES ('Ayesha Rahman', 'ayesha@uni.edu', 3.80),
       ('Tanvir Hasan',  'tanvir@uni.edu', 3.40)
RETURNING id;

UPDATE students SET gpa = 3.90
WHERE email = 'ayesha@uni.edu'
RETURNING id, gpa;

DELETE FROM students WHERE gpa < 1.0;

-- Upsert: insert, or update when the key already exists
INSERT INTO courses (code, title, credits)
VALUES ('CS101', 'Intro to CS', 3)
ON CONFLICT (code) DO UPDATE SET title = EXCLUDED.title;
মডিউল 07 · প্রাথমিক

কুয়েরি: ফিল্টার, জয়েন, অ্যাগ্রিগেট

SQL যে ক্রমে লেখা হয়, সেই ক্রমে চলে না। আসল ক্রম জানলে নতুনদের বেশিরভাগ ভুলের কারণ বোঝা যায়, যেমন WHERE-এ কলামের alias কেন কাজ করে না।

FROM, JOIN তারপর WHERE তারপর GROUP BY তারপর HAVING তারপর SELECT তারপর ORDER BY তারপর LIMIT।

SQL
SELECT c.code,
       count(*)              AS enrolled,
       round(avg(e.grade),2) AS avg_grade
FROM courses c
JOIN enrollments e ON e.course_id = c.id
GROUP BY c.code
HAVING count(*) >= 5
ORDER BY enrolled DESC
LIMIT 3;
ফলাফল
codeenrolledavg_grade
CS101423.12
MA201372.88
PH110293.41

জয়েনের ধরন

  • INNER JOIN: দুই পাশেই মিলে যাওয়া সারি শুধু।
  • LEFT JOIN: বাঁ পাশের সব সারি, না মিললে ডান পাশে NULL।
  • FULL JOIN: দুই পাশের সবকিছু।
SQL
-- Students who have not enrolled in anything
SELECT s.full_name
FROM students s
LEFT JOIN enrollments e ON e.student_id = s.id
WHERE e.student_id IS NULL;
অনুশীলনযেসব কোর্সে কোনো শিক্ষার্থী ভর্তি নেই, সেগুলোর তালিকা বের করুন।
SQL
SELECT c.code
FROM courses c
LEFT JOIN enrollments e ON e.course_id = c.id
WHERE e.course_id IS NULL;
মডিউল 08 · প্রাথমিক

ফাংশন ও এক্সপ্রেশন

PostgreSQL-এ কয়েকশো বিল্ট-ইন ফাংশন আছে। প্রতিদিনের কাজের বেশিরভাগ চার ধরনে পড়ে: লেখা, সংখ্যা, তারিখ ও NULL সামলানো।

দলপ্রচলিত টুল
লেখাlower(), upper(), trim(), replace(), split_part(), format(), ||, ILIKE
সংখ্যাround(), ceil(), floor(), abs(), mod(), random()
তারিখ ও সময়now(), current_date, interval, date_trunc(), extract(), age(), to_char()
NULL ও রূপান্তরCOALESCE(), NULLIF(), IS DISTINCT FROM, ::type, CAST()
SQL
SELECT lower(email)                        AS email,
       full_name || ' <' || email || '>'   AS display,
       COALESCE(gpa, 0)                    AS gpa_or_zero,
       date_trunc('month', enrolled_at)    AS month,
       now() - enrolled_at                 AS time_enrolled,
       to_char(enrolled_at, 'DD Mon YYYY') AS pretty_date,
       gpa::int                            AS gpa_rounded
FROM students
WHERE full_name ILIKE 'a%'
  AND enrolled_at >= now() - interval '1 year';
মডিউল 09 · মধ্যম

কনস্ট্রেইন্ট, রিলেশনশিপ, নরমালাইজেশন

কনস্ট্রেইন্ট ডেটাবেসকে নিজের ডেটা রক্ষা করতে দেয়: PRIMARY KEY, FOREIGN KEY, UNIQUE, NOT NULL ও CHECK। অ্যাপ্লিকেশন কোডে বাগ থাকে, কনস্ট্রেইন্ট ভোলে না।

  • এক থেকে অনেক: "অনেক" দিকের টেবিলে ফরেন কী।
  • অনেক থেকে অনেক: কম্পোজিট কী সহ জাংশন টেবিল, নিচের মতো।
  • এক থেকে এক: এমন ফরেন কী যা একইসঙ্গে UNIQUE।
SQL
CREATE TABLE courses (
    id      BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    code    TEXT     NOT NULL UNIQUE,
    title   TEXT     NOT NULL,
    credits SMALLINT NOT NULL CHECK (credits > 0)
);

-- Junction table for the many to many relationship
CREATE TABLE enrollments (
    student_id BIGINT NOT NULL REFERENCES students(id) ON DELETE CASCADE,
    course_id  BIGINT NOT NULL REFERENCES courses(id)  ON DELETE RESTRICT,
    grade      NUMERIC(3,2),
    PRIMARY KEY (student_id, course_id)
);

তিন লাইনে নরমালাইজেশন

  • 1NF: প্রতি ঘরে একটি মান, পুনরাবৃত্ত গ্রুপ নয়।
  • 2NF: প্রতিটি কলাম পুরো কী-এর ওপর নির্ভরশীল।
  • 3NF: কোনো কলাম অন্য নন-কী কলামের ওপর নির্ভরশীল নয়।
মডিউল 10 · মধ্যম

কাঠামো বদল: ALTER, স্কিমা, সিকোয়েন্স

বাস্তব প্রজেক্ট বদলায়। ALTER TABLE টেবিল নতুন করে না বানিয়েই কলাম যোগ, নাম বদল বা মোছে। স্কিমা হলো ডেটাবেসের ভেতরের ফোল্ডার, যা টেবিলকে দলবদ্ধ করে। সিকোয়েন্স একটি কাউন্টার যা একের পর এক সংখ্যা দেয় (identity কলাম ভেতরে একটি সিকোয়েন্সই ব্যবহার করে)।

SQL
-- Add, rename, default and remove a column
ALTER TABLE students ADD COLUMN phone TEXT;
ALTER TABLE students RENAME COLUMN phone TO mobile;
ALTER TABLE students ALTER COLUMN mobile SET DEFAULT '';
ALTER TABLE students DROP COLUMN mobile;

-- A schema groups tables like a folder
CREATE SCHEMA library;
CREATE TABLE library.books (id INT PRIMARY KEY, title TEXT NOT NULL);
SET search_path TO library, public;

-- A sequence is a counter
CREATE SEQUENCE ticket_no START 1000;
SELECT nextval('ticket_no');
মডিউল 11 · মধ্যম

সাবকুয়েরি, সেট অপারেশন, CASE

সাবকুয়েরি মানে কুয়েরির ভেতরে কুয়েরি: scalar (একটি মান), IN (তালিকা) বা EXISTS (মিল আছে কি না)। EXISTS প্রথম মিল পেলেই থামে, তাই বড় ডেটায় প্রায়ই IN-এর চেয়ে ভালো চলে।

  • UNION: মিলিয়ে ডুপ্লিকেট বাদ দেয়। UNION ALL: ডুপ্লিকেট সহ মেলায় (দ্রুত)।
  • INTERSECT: দুই পাশেই আছে এমন সারি। EXCEPT: শুধু প্রথম পাশে আছে এমন সারি।
SQL
-- Scalar subquery: students above the average GPA
SELECT full_name, gpa
FROM students
WHERE gpa > (SELECT avg(gpa) FROM students);

-- EXISTS stops at the first match
SELECT c.code
FROM courses c
WHERE EXISTS (SELECT 1 FROM enrollments e WHERE e.course_id = c.id);

-- Set operation (assumes an alumni table with the same email column)
SELECT email FROM students
EXCEPT
SELECT email FROM alumni;

-- CASE is a conditional expression
SELECT full_name,
       CASE WHEN gpa >= 3.7 THEN 'honours'
            WHEN gpa >= 2.0 THEN 'pass'
            ELSE 'probation' END AS standing
FROM students;
মডিউল 12 · মধ্যম

ইনডেক্স ও কুয়েরি প্ল্যান

ইনডেক্স ছাড়া PostgreSQL পুরো টেবিল পড়ে (Seq Scan)। ডিফল্ট B-tree ইনডেক্স লগারিদমিক সময়ে সারি খুঁজে পায় এবং সর্টিং ও রেঞ্জ ফিল্টারেও কাজে লাগে।

ইনডেক্সকিসের জন্য সেরা
B-treeসমতা, রেঞ্জ, ORDER BY (ডিফল্ট)
GINJSONB, অ্যারে, ফুল টেক্সট সার্চ
GiSTজ্যামিতি, রেঞ্জ, নিকটতম প্রতিবেশী
BRINসময় অনুযায়ী সাজানো বিশাল append-only টেবিল
Hashশুধু সমতা (B-tree-র চেয়ে কমই ভালো)
SQL
-- Index foreign keys and columns used in WHERE, JOIN and ORDER BY
CREATE INDEX idx_enroll_course ON enrollments (course_id);

-- Partial index: smaller and faster for a common filter
CREATE INDEX idx_students_top ON students (gpa DESC) WHERE gpa >= 3.5;

EXPLAIN (ANALYZE, BUFFERS)
SELECT student_id, grade FROM enrollments WHERE course_id = 42;

প্ল্যান ভেতরের লাইন থেকে বাইরের দিকে পড়ুন। Seq Scan ও Index Scan, আনুমানিক ও প্রকৃত সারির সংখ্যা এবং প্রকৃত সময় তুলনা করুন। অনুমান ও বাস্তবের বড় ফারাক সাধারণত পুরোনো পরিসংখ্যানের লক্ষণ, তখন ANALYZE চালান।

মডিউল 13 · মধ্যম

প্যাটার্ন ম্যাচিং ও ফুল টেক্সট সার্চ

তিন স্তর আছে: % ওয়াইল্ডকার্ডসহ LIKE ও ILIKE, ~ দিয়ে রেগুলার এক্সপ্রেশন, এবং ফুল টেক্সট সার্চ, যা শব্দ, স্টেমিং (indexes লিখলে index-ও মেলে) ও র‍্যাংকিং বোঝে।

টুলকখনইনডেক্স
LIKE, ILIKEসরল প্যাটার্নB-tree শুধু 'abc%'-এ সাহায্য করে; '%abc%'-এর জন্য pg_trgm
~ (regex)জটিল প্যাটার্নpg_trgm
tsvector @@ tsqueryর‍্যাংকিংসহ শব্দ খোঁজাGIN
SQL
-- Simple pattern and regular expression matching
SELECT full_name FROM students WHERE full_name ILIKE '%rahman%';
SELECT email FROM students WHERE email ~ '^[a-z]+@uni\.edu$';

-- Full text search with a generated column and a GIN index
CREATE TABLE articles (
    id    SERIAL PRIMARY KEY,
    title TEXT NOT NULL,
    body  TEXT NOT NULL,
    tsv   tsvector GENERATED ALWAYS AS (to_tsvector('english', title || ' ' || body)) STORED
);
CREATE INDEX idx_articles_tsv ON articles USING GIN (tsv);
INSERT INTO articles (title, body) VALUES
    ('Indexes', 'A B-tree index speeds up lookups'),
    ('Joins', 'Combine rows from two tables');

SELECT title, ts_rank(tsv, q) AS score
FROM articles, websearch_to_tsquery('english', 'index lookup') AS q
WHERE tsv @@ q
ORDER BY score DESC;
মডিউল 14 · মধ্যম

ট্রানজ্যাকশন, MVCC ও লকিং

ট্রানজ্যাকশন কয়েকটি স্টেটমেন্টকে একসঙ্গে সফল বা ব্যর্থ করে (ACID: অ্যাটমিসিটি, কনসিস্টেন্সি, আইসোলেশন, ডিউরেবিলিটি)। PostgreSQL MVCC ব্যবহার করে: প্রতিটি ট্রানজ্যাকশন একটি সামঞ্জস্যপূর্ণ স্ন্যাপশট দেখে, তাই পাঠক কখনো লেখককে আটকায় না।

আইসোলেশন লেভেলআচরণ
READ COMMITTED (ডিফল্ট)প্রতিটি স্টেটমেন্ট শুরুর আগে কমিট হওয়া ডেটা দেখে
REPEATABLE READপুরো ট্রানজ্যাকশন একটিই স্ন্যাপশট দেখে
SERIALIZABLEযেন ট্রানজ্যাকশনগুলো একটির পর একটি চলেছে; ব্যর্থ হলে আবার চেষ্টা করুন
SQL
BEGIN;
UPDATE accounts SET balance = balance - 500 WHERE id = 1;
UPDATE accounts SET balance = balance + 500 WHERE id = 2;
COMMIT;  -- or ROLLBACK to undo everything since BEGIN

-- Lock a row while you decide what to do with it
BEGIN ISOLATION LEVEL REPEATABLE READ;
SELECT balance FROM accounts WHERE id = 1 FOR UPDATE;
COMMIT;
মডিউল 15 · উন্নত

অ্যাডভান্সড SQL: CTE, উইন্ডো, JSONB, ভিউ

CTE (WITH) মাঝের ফলাফলকে নাম দেয় এবং জটিল কুয়েরি পাঠযোগ্য রাখে। উইন্ডো ফাংশন সম্পর্কিত সারির ওপর হিসাব করে, কিন্তু GROUP BY-এর মতো সারি গুটিয়ে ফেলে না: rank(), row_number(), lag(), ক্রমবর্ধমান যোগফল।

SQL
-- CTE plus window function: top 3 grades per course
WITH ranked AS (
    SELECT course_id, student_id, grade,
           rank() OVER (PARTITION BY course_id ORDER BY grade DESC) AS pos
    FROM enrollments
)
SELECT course_id, student_id, grade
FROM ranked
WHERE pos <= 3;

JSONB

রিলেশনাল কলামের পাশে নমনীয় অ্যাট্রিবিউট রাখুন এবং GIN দিয়ে ইনডেক্স করুন।

SQL
ALTER TABLE students ADD COLUMN profile JSONB NOT NULL DEFAULT '{}';
CREATE INDEX idx_students_profile ON students USING GIN (profile);

SELECT full_name
FROM students
WHERE profile @> '{"club": "robotics"}';

ভিউ

ভিউ একটি কুয়েরি সংরক্ষণ করে। ম্যাটেরিয়ালাইজড ভিউ ফলাফল সংরক্ষণ করে, অর্থাৎ হালনাগাদের বদলে গতি পাওয়া যায়।

SQL
CREATE MATERIALIZED VIEW course_stats AS
SELECT course_id, count(*) AS n, round(avg(grade),2) AS avg_grade
FROM enrollments
GROUP BY course_id;

CREATE UNIQUE INDEX ON course_stats (course_id);
REFRESH MATERIALIZED VIEW CONCURRENTLY course_stats;
মডিউল 16 · উন্নত

রিকার্সিভ কুয়েরি ও হায়ারার্কি

রিকার্সিভ CTE নিজের ফলাফলের ওপর কুয়েরি বারবার চালায়। গাছ ও গ্রাফের জন্য উপযোগী: অর্গ চার্ট, ক্যাটাগরি মেনু, ফোল্ডার, বিল অব ম্যাটেরিয়ালস। UNION ALL দিয়ে দুই অংশ জোড়া থাকে: অ্যাঙ্কর (শুরুর সারি) ও রিকার্সিভ ধাপ (পরের স্তর খোঁজে)। ধাপ নতুন সারি না দিলে থামে।

SQL
CREATE TABLE staff (
    id      INT PRIMARY KEY,
    name    TEXT NOT NULL,
    boss_id INT REFERENCES staff(id)
);
INSERT INTO staff VALUES (1,'Dean',NULL), (2,'Head of CS',1), (3,'Lecturer A',2), (4,'Lecturer B',2), (5,'Head of Math',1);

WITH RECURSIVE chain AS (
    SELECT id, name, boss_id, 0 AS depth
    FROM staff
    WHERE boss_id IS NULL
    UNION ALL
    SELECT s.id, s.name, s.boss_id, c.depth + 1
    FROM staff s
    JOIN chain c ON s.boss_id = c.id
    WHERE c.depth < 20
)
SELECT repeat('    ', depth) || name AS org_chart, depth
FROM chain
ORDER BY depth, id;
মডিউল 17 · উন্নত

PL/pgSQL প্রোগ্রামিং

PL/pgSQL SQL-এ ভেরিয়েবল, IF, লুপ ও এরর হ্যান্ডলিং যোগ করে। কুয়েরিতে মান ফেরত লাগলে ফাংশন, ধাপে ধাপে কাজ চালাতে প্রসিডিউর (CALL দিয়ে ডাকা হয়), আর একবারের স্ক্রিপ্টের জন্য DO ব্লক।

  • DECLARE দিয়ে ভেরিয়েবল, SELECT ... INTO দিয়ে মান ভরা।
  • নিয়ন্ত্রণে IF, ELSIF, FOR ... LOOP।
  • এরর সামলাতে EXCEPTION WHEN ... THEN, জানাতে RAISE।
SQL
CREATE OR REPLACE FUNCTION grade_letter(score NUMERIC) RETURNS TEXT
LANGUAGE plpgsql IMMUTABLE AS $$
BEGIN
    IF score IS NULL THEN
        RETURN NULL;
    ELSIF score >= 3.7 THEN
        RETURN 'A';
    ELSIF score >= 3.0 THEN
        RETURN 'B';
    ELSE
        RETURN 'C';
    END IF;
END;
$$;

SELECT full_name, grade_letter(gpa) AS letter FROM students;

CREATE PROCEDURE enroll_student(p_student BIGINT, p_course BIGINT)
LANGUAGE plpgsql AS $$
DECLARE
    seats INT;
BEGIN
    SELECT count(*) INTO seats FROM enrollments WHERE course_id = p_course;
    IF seats >= 30 THEN
        RAISE EXCEPTION 'Course % is full', p_course;
    END IF;
    INSERT INTO enrollments (student_id, course_id) VALUES (p_student, p_course);
EXCEPTION WHEN unique_violation THEN
    RAISE NOTICE 'Student % is already enrolled', p_student;
END;
$$;

CALL enroll_student(6, 1);
CALL enroll_student(6, 1);
মডিউল 18 · উন্নত

ফাংশন, ট্রিগার, পার্টিশনিং

PL/pgSQL দিয়ে ডেটাবেসের ভেতরেই লজিক চালানো যায়। ট্রিগার INSERT, UPDATE বা DELETE-এ স্বয়ংক্রিয়ভাবে ফাংশন ডাকে, যা অডিট কলাম ও ছোট নিয়ম বজায় রাখতে উপযোগী।

SQL
ALTER TABLE students ADD COLUMN updated_at TIMESTAMPTZ NOT NULL DEFAULT now();

CREATE FUNCTION touch_updated_at() RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN
    NEW.updated_at := now();
    RETURN NEW;
END;
$$;

CREATE TRIGGER trg_students_touch
BEFORE UPDATE ON students
FOR EACH ROW EXECUTE FUNCTION touch_updated_at();

পার্টিশনিং

ক্রমাগত বাড়তে থাকা টেবিলকে রেঞ্জ, লিস্ট বা হ্যাশ দিয়ে ভাগ করুন। পার্টিশন কী দিয়ে ফিল্টার করলে শুধু প্রাসঙ্গিক পার্টিশন পড়া হয়, আর পুরোনো ডেটা সঙ্গে সঙ্গে আলাদা বা মুছে ফেলা যায়।

SQL
CREATE TABLE audit_log (
    id        BIGINT GENERATED ALWAYS AS IDENTITY,
    logged_at TIMESTAMPTZ NOT NULL,
    payload   JSONB
) PARTITION BY RANGE (logged_at);

CREATE TABLE audit_log_2026_10 PARTITION OF audit_log
FOR VALUES FROM ('2026-10-01') TO ('2026-11-01');
SQL
-- Keyset pagination: stays fast on huge tables, unlike large OFFSET values
SELECT id, full_name
FROM students
WHERE id > 1000
ORDER BY id
LIMIT 50;
মডিউল 19 · উন্নত

রেপ্লিকেশন, এক্সটেনশন, টিউনিং

ফিজিক্যাল (স্ট্রিমিং) রেপ্লিকেশন পুরো ক্লাস্টারের WAL কপি করে, হট স্ট্যান্ডবাই ও ফেইলওভারের জন্য। লজিক্যাল রেপ্লিকেশন বেছে নেওয়া টেবিলের পরিবর্তন পাঠায়, মেজর ভার্সন আপগ্রেড ও ডেটা বিতরণে কাজে লাগে।

SQL
-- Primary (postgresql.conf): wal_level = logical
-- Publish selected tables
CREATE PUBLICATION pub_students FOR TABLE students, courses;

-- Subscriber: pull those changes continuously
CREATE SUBSCRIPTION sub_students
CONNECTION 'host=primary dbname=university user=repl'
PUBLICATION pub_students;

এক্সটেনশন

এক্সটেনশন ডেটাবেস ফর্ক না করেই নতুন সুবিধা যোগ করে: pg_trgm (অস্পষ্ট সার্চ), pgcrypto, PostGIS (ভূগোল), pg_stat_statements (কুয়েরি পরিসংখ্যান), TimescaleDB (টাইম সিরিজ)।

SQL
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE INDEX idx_students_name_trgm ON students USING GIN (full_name gin_trgm_ops);
SELECT full_name FROM students WHERE full_name ILIKE '%rahm%';

SHOW shared_buffers;
ALTER SYSTEM SET work_mem = '32MB';
SELECT pg_reload_conf();

টিউনিংয়ের প্রথম নবগুলো

  • shared_buffers: সাধারণ শুরুর হিসাব RAM-এর প্রায় ২৫%।
  • effective_cache_size: প্ল্যানারকে জানায় OS কতটা ক্যাশ করতে পারে, প্রায়ই RAM-এর ৫০ থেকে ৭৫%।
  • work_mem: প্রতিটি সর্ট বা হ্যাশ ধাপে লাগে, তাই সাবধানে বাড়ান।
  • maintenance_work_mem: VACUUM ও ইনডেক্স বানানো দ্রুত করে।
  • max_connections: কম রাখুন, পুল ব্যবহার করুন।
মডিউল 20 · উন্নত

নিরাপত্তা, ব্যাকআপ ও প্রোডাকশন

প্রতিটি অ্যাপ্লিকেশনের জন্য রোল বানান, যতটুকু অনুমতি দরকার ততটুকুই দিন। অ্যাপকে কখনো সুপারইউজার হিসেবে সংযুক্ত হতে দেবেন না।

SQL
CREATE ROLE app_user LOGIN PASSWORD 'change_me';
GRANT CONNECT ON DATABASE university TO app_user;
GRANT SELECT, INSERT, UPDATE ON students TO app_user;
REVOKE ALL ON enrollments FROM PUBLIC;

ব্যাকআপ ও পুনরুদ্ধার

pg_dump লজিক্যাল ব্যাকআপ দেয়। পয়েন্ট ইন টাইম রিকভারির জন্য বেস ব্যাকআপের সঙ্গে আর্কাইভ করা WAL ব্যবহার করুন। স্ট্রিমিং রেপ্লিকেশন একটি হট স্ট্যান্ডবাই রাখে, যা শুধু-পড়া ট্রাফিকও সামলাতে পারে।

Shell
# Compressed custom format dump
pg_dump -Fc -d university -f university.dump

# Restore into a separate copy first
createdb university_copy
pg_restore -d university_copy university.dump

বাস্তবে চালানো

  • সার্ভারের সামনে PgBouncer বা অন্য কানেকশন পুল রাখুন।
  • autovacuum চালু রাখুন এবং টেবিল ব্লোট নজরে রাখুন।
  • pg_stat_statements দিয়ে ধীর কুয়েরি ধরুন।
  • বড় টেবিলে দীর্ঘ লক ছাড়া মাইগ্রেশন করুন।
SQL
-- Safe migration on a big table: nullable column, batched backfill, then constraint
ALTER TABLE students ADD COLUMN phone TEXT;
UPDATE students SET phone = '' WHERE id BETWEEN 1 AND 1000 AND phone IS NULL;
ALTER TABLE students ADD CONSTRAINT phone_required CHECK (phone IS NOT NULL) NOT VALID;
ALTER TABLE students VALIDATE CONSTRAINT phone_required;

-- Find the slowest statements (needs the pg_stat_statements extension)
SELECT query, calls, round(mean_exec_time::numeric, 2) AS avg_ms
FROM pg_stat_statements
ORDER BY mean_exec_time DESC
LIMIT 5;
মডিউল 21 · উন্নত

রো লেভেল সিকিউরিটি

GRANT ঠিক করে একটি রোল কোন টেবিল ছুঁতে পারবে। রো লেভেল সিকিউরিটি (RLS) ঠিক করে কোন সারি, এবং ডেটাবেস নিজেই তা কার্যকর করে। মাল্টি-টেন্যান্ট অ্যাপে, যেখানে প্রতিটি গ্রাহক শুধু নিজের সারি দেখবে, এটিই মানক উপায়। পলিসি হলো নিয়ম: USING কোন সারি পড়া, আপডেট বা মোছা যাবে তা ছাঁকে, আর WITH CHECK লেখা সারি যাচাই করে।

SQL
CREATE TABLE notes (
    id    SERIAL PRIMARY KEY,
    owner TEXT NOT NULL DEFAULT current_user,
    body  TEXT NOT NULL
);

ALTER TABLE notes ENABLE ROW LEVEL SECURITY;
ALTER TABLE notes FORCE ROW LEVEL SECURITY;

CREATE POLICY own_notes ON notes
    USING (owner = current_user)
    WITH CHECK (owner = current_user);
মডিউল 22 · উন্নত

আধুনিক PostgreSQL: Docker Compose ও pgvector

docker-compose.yml এক কমান্ডে, docker compose up -d, প্রত্যেক টিমমেটকে একই ডেটাবেস দেয়। pgvector এক্সটেনশন vector কলামে এমবেডিং (AI মডেলের বানানো সংখ্যার তালিকা) রাখে এবং সবচেয়ে কাছেরগুলো খুঁজে দেয়। সিম্যান্টিক সার্চ ও RAG অ্যাপের ভিত্তি এটাই।

Shell
# docker-compose.yml
services:
  db:
    image: pgvector/pgvector:pg16
    environment:
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: university
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data
volumes:
  pgdata:
SQL
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE docs (
    id        BIGSERIAL PRIMARY KEY,
    content   TEXT NOT NULL,
    embedding vector(3)
);
INSERT INTO docs (content, embedding)
VALUES ('cat', '[1,0,0]'), ('kitten', '[0.9,0.1,0]'), ('car', '[0,0,1]');
CREATE INDEX ON docs USING hnsw (embedding vector_cosine_ops);

-- Nearest two documents by cosine distance
SELECT content FROM docs ORDER BY embedding <=> '[1,0,0]' LIMIT 2;
অপারেটরদূরত্ব
<->ইউক্লিডীয় (L2)
<=>কোসাইন
<#>ঋণাত্মক ইনার প্রোডাক্ট
মডিউল 23 · রেফারেন্স

চিট শিট, শব্দকোষ, পরের ধাপ

SQL দ্রুত রেফারেন্স

কাজস্টেটমেন্ট
টেবিল বানানোCREATE TABLE t (id INT PRIMARY KEY, name TEXT);
ইনসার্টINSERT INTO t (id, name) VALUES (1, 'a');
পড়াSELECT name FROM t WHERE id = 1;
আপডেটUPDATE t SET name = 'b' WHERE id = 1;
মোছাDELETE FROM t WHERE id = 1;
জয়েনSELECT a.x, b.y FROM a JOIN b ON b.a_id = a.id;
অ্যাগ্রিগেটSELECT k, count(*) FROM t GROUP BY k;
ইনডেক্সCREATE INDEX idx_t_name ON t (name);
ট্রানজ্যাকশনBEGIN; ... COMMIT;
প্ল্যানEXPLAIN (ANALYZE) SELECT ...;

psql কমান্ড

কমান্ডকাজ
\lডেটাবেসের তালিকা
\c nameডেটাবেসে সংযোগ
\dtটেবিলের তালিকা
\d tableটেবিলের বিবরণ
\duরোলের তালিকা
\dnস্কিমার তালিকা
\xবিস্তারিত আউটপুট চালু বা বন্ধ
\timingকুয়েরির সময় দেখায়
\i file.sqlফাইল চালায়
\qবের হওয়া

শব্দকোষ

শব্দঅর্থ
সারি, কলামএকটি রেকর্ড, এবং প্রতিটি রেকর্ডের একটি নামকরা ঘর
Primary keyযে কলাম সারিকে অনন্যভাবে চিহ্নিত করে
Foreign keyযে কলাম অন্য টেবিলের সারির দিকে নির্দেশ করে
Indexঅতিরিক্ত কাঠামো যা খোঁজা দ্রুত করে
Transactionএকদল স্টেটমেন্ট যা একসঙ্গে সফল বা ব্যর্থ হয়
MVCCপ্রতিটি ট্রানজ্যাকশন স্ন্যাপশট দেখে, পাঠক লেখককে আটকায় না
WALস্থায়িত্ব, রিকভারি ও রেপ্লিকেশনের জন্য ব্যবহৃত লগ
VACUUMআপডেট ও ডিলিটে জমা মৃত সারির সংস্করণ পরিষ্কার করে
Schemaডেটাবেসের ভেতরে টেবিলের নেমস্পেস (ফোল্ডার)
Viewসংরক্ষিত কুয়েরি যা টেবিলের মতো দেখায়
Roleঅনুমতিসহ ইউজার বা গ্রুপ
CTEএকটি কুয়েরির ভেতরে নামকরা সাময়িক ফলাফল (WITH)
Replicaপ্রাইমারি থেকে সিঙ্ক রাখা সার্ভারের কপি

পরের ধাপ

  • প্র্যাকটিস ল্যাবে ইউনিভার্সিটি স্কিমা মুখস্থ থেকে নতুন করে বানান, তারপর নিজের টেবিল যোগ করুন।
  • যেকোনো কমান্ডের খুঁটিনাটির জন্য PostgreSQL-এর অফিসিয়াল ডকুমেন্টেশন পড়ুন।
  • নিজের ধীর কুয়েরিতে EXPLAIN ANALYZE অনুশীলন করুন।
  • যেকোনো ভাষায় ছোট একটি অ্যাপ বানান যা ড্রাইভারের মাধ্যমে PostgreSQL-এর সঙ্গে কথা বলে।