رفتن به محتوا
دیتابیس و SQLSQL از صفردرس ۱ از ۱۰

دیتابیس چیست؟

فرق فایل و دیتابیس، دیتابیس رابطه‌ای (جدول، سطر، ستون) و انواع دیگر (key-value، سندی)، PostgreSQL و MySQL و SQLite؛ نصب PostgreSQL روی Ubuntu، ساختن کاربر و دیتابیس، psql و دستورهای بک‌اسلشی، اولین جدول با CREATE TABLE، و INSERT و SELECT ساده.

  • حدود ۲۱ دقیقه مطالعه
  • ۷ مثال اجراشده
  • ۳ تمرین با جواب
  • مقدماتی تا متوسط
  • به‌روزرسانی: ۲۹ مهر ۱۴۰۵

توی این درس یاد می‌گیری دیتابیس چیست و چرا تقریباً هر برنامه‌ی واقعی به جای فایل از آن استفاده می‌کند. با مفهوم جدول (سطر و ستون) در دیتابیس رابطه‌ای آشنا می‌شوی و می‌فهمی انواع دیگر (key-value مثل Redis، سندی مثل MongoDB) برای چه‌اند. بعد PostgreSQL را روی Ubuntu نصب می‌کنی، با ابزار خط فرمانش psql کار می‌کنی، اولین جدولت را با CREATE TABLE می‌سازی، چند سطر با INSERT اضافه می‌کنی و با SELECT می‌خوانی. و می‌بینی دیتابیس چطور جلوی داده‌ی غلط را خودش می‌گیرد.

مسئله: وقتی فایل دیگر کافی نیست

Section titled “مسئله: وقتی فایل دیگر کافی نیست”

در دوره‌ی پایتون داده را در یک فایل JSON یا CSV نگه داشتی. برای یک برنامه‌ی کوچک عالی است. ولی فرض کن یک فروشگاه اینترنتی داری: ده هزار محصول، صد هزار سفارش، و هم‌زمان پنجاه نفر در حال خرید. حالا این سؤال‌ها پیش می‌آید:

  • دو نفر هم‌زمان آخرین عدد یک کالا را بخرند؛ چه کسی برنده است؟ (اگر هر دو فایل را بخوانند، کم کنند و بنویسند، یکی از خریدها گم می‌شود.)
  • «سفارش‌های هفته‌ی گذشته‌ی مشتری‌های تهران که بالای یک میلیون تومان بوده‌اند» را چطور پیدا کنی، بدون اینکه کل فایل را هر بار بخوانی؟
  • چه چیزی جلوی کسی را می‌گیرد که قیمت را «گران» بنویسد یا سفارشی برای مشتری‌ای ثبت کند که وجود ندارد؟

دیتابیس (پایگاه داده) برنامه‌ای است که دقیقاً برای همین سؤال‌ها ساخته شده.

تشبیه: کتابخانه با کتابدار

Section titled “تشبیه: کتابخانه با کتابدار”

فایل مثل یک جعبه کاغذ است: هر کس هر چه بخواهد داخلش می‌گذارد و برای پیدا کردن چیزی باید همه را ورق بزنی. دیتابیس مثل کتابخانه با کتابدار است: کتاب‌ها در قفسه‌های منظم‌اند (جدول‌ها)، هر کتاب شناسه‌ی یکتا دارد، یک فهرست (ایندکس) سریع پیدایشان می‌کند، و کتابدار (موتور دیتابیس) نمی‌گذارد کسی کتاب بدون عنوان ثبت کند یا دو نفر هم‌زمان یک کتاب را امانت بگیرند. تو با کتابدار به زبان مشخصی حرف می‌زنی: SQL.

دیتابیس رابطه‌ای (relational) داده را در جدول‌ها نگه می‌دارد، خیلی شبیه یک برگه‌ی اکسل ولی با قانون:

id name price stock
1 کتاب پایتون 320000 12
2 ماوس 450000 30
3 کیبورد 890000 8
  • ستون (column): یک ویژگی با نوع مشخص: name همیشه متن، price همیشه عدد صحیح.
  • سطر (row): یک رکورد، اینجا یک محصول.
  • کلید اصلی (primary key): ستونی که هر سطر را یکتا مشخص می‌کند (id). دو محصول ممکن است هم‌اسم باشند، ولی هرگز هم‌شناسه نیستند.

«رابطه‌ای» یعنی جدول‌ها با هم رابطه دارند: جدول orders با یک ستون product_id به جدول products اشاره می‌کند (درس JOIN).

دیتابیس رابطه‌ای داده را در جدول‌های با ستون‌های نوع‌دار و رابطه بین جدول‌ها نگه می‌دارد؛ انواع NoSQL برای شکل‌های دیگری از داده بهینه‌اند.

سه دیتابیس رابطه‌ای معروف

Section titled “سه دیتابیس رابطه‌ای معروف”
PostgreSQL MySQL / MariaDB SQLite
نوع سرور (سرویس جدا) سرور یک فایل، داخل خود برنامه
قوت امکانات زیاد، دقیق، استاندارد، JSON و جستجوی متنی بسیار رایج در وب (WordPress و…) بدون نصب، صفر تنظیمات
کاربرد بیشتر پروژه‌های جدید میزبانی‌های اشتراکی، سیستم‌های قدیمی‌تر اپ موبایل، ابزارهای کوچک، تست

این دوره روی PostgreSQL است. SQL پایه در هر سه تقریباً یکی است، پس هر چه یاد بگیری بیشترش همه‌جا کار می‌کند.

روی ماشین تمرینی Ubuntu:

Terminal window
sudo apt update
sudo apt install postgresql

نصب، سرویس را خودش روشن و enable می‌کند (درس systemd):

Terminal window
systemctl status postgresql --no-pager
psql --version
خروجی (کوتاه‌شده)
● postgresql.service - PostgreSQL RDBMS
Loaded: loaded (/usr/lib/systemd/system/postgresql.service; enabled; preset: enabled)
Active: active (exited) since Wed 2026-10-21 09:12:40 UTC; 2min ago
psql (PostgreSQL) 16.15 (Ubuntu 16.15-0ubuntu0.24.04.1)

PostgreSQL 16 همراه Ubuntu 24.04 است. (active (exited) برای این واحد عادی است؛ سرور واقعی در واحد postgresql@16-main اجرا می‌شود.) سرور روی پورت ۵۴۳۲ گوش می‌دهد؛ با sudo ss -tlnp | grep 5432 ببین (درس پورت‌ها).

مثال ۲: کاربر و دیتابیس خودت

Section titled “مثال ۲: کاربر و دیتابیس خودت”

نصب یک کاربر لینوکسی و یک نقش (role) دیتابیسی به اسم postgres می‌سازد که مدیر دیتابیس است. روی Ubuntu، کاربر لینوکسی ali به‌طور پیش‌فرض بدون رمز به نقش دیتابیسی هم‌نامش وصل می‌شود (به این peer authentication می‌گویند؛ درس کاربر و امنیت). پس یک نقش هم‌نام خودت بساز و یک دیتابیس:

Terminal window
sudo -u postgres createuser --createdb $USER
createdb shop
psql shop
صفحه
psql (16.15 (Ubuntu 16.15-0ubuntu0.24.04.1))
Type "help" for help.
shop=>
  • sudo -u postgres createuser ... دستور را با کاربر لینوکسی postgres (همان مدیر) اجرا می‌کند و نقشی با اسم تو ($USER، یعنی ali) می‌سازد که اجازه‌ی ساختن دیتابیس دارد.
  • createdb shop یک دیتابیس به اسم shop می‌سازد (حالا دیگر با نقش خودت).
  • psql shop به آن وصل می‌شود. پرامپت shop=> یعنی «در دیتابیس shop هستی و منتظر SQL ام». (برای مدیر، =# است؛ مثل $ و # در ترمینال.)

یک سرور PostgreSQL می‌تواند چند دیتابیس جدا داشته باشد (مثلاً یکی برای هر برنامه)؛ هر دیتابیس هم جدول‌های خودش را.

مثال ۳: دستورهای بک‌اسلشی psql

Section titled “مثال ۳: دستورهای بک‌اسلشی psql”

دستورهایی که با \ شروع می‌شوند مال خود psql‌اند، نه SQL، و نقطه‌ویرگول لازم ندارند:

دستورها و کلیدها
\l
خروجی (کوتاه‌شده)
List of databases
Name | Owner | Encoding | Locale Provider | Collate | Ctype | ICU Locale | ICU Rules | Access privileges
-----------+----------+----------+-----------------+---------+---------+------------+-----------+-----------------------
postgres | postgres | UTF8 | libc | C.UTF-8 | C.UTF-8 | | |
shop | ali | UTF8 | libc | C.UTF-8 | C.UTF-8 | | |
template0 | postgres | UTF8 | libc | C.UTF-8 | C.UTF-8 | | | =c/postgres +
...
(4 rows)
دستور کار
\l فهرست دیتابیس‌ها
\c نام وصل شدن به یک دیتابیس دیگر
\dt فهرست جدول‌ها
\d جدول ساختار یک جدول
\? / \h دستور راهنمای psql / راهنمای یک دستور SQL
\x نمایش عمودی (برای سطرهای پهن)
\q خروج (یا Ctrl+D)

Encoding همه UTF8 است، پس فارسی بی‌دردسر ذخیره می‌شود.

مثال ۴: اولین جدول، CREATE TABLE

Section titled “مثال ۴: اولین جدول، CREATE TABLE”
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
price INTEGER NOT NULL,
stock INTEGER DEFAULT 0
);
خروجی
CREATE TABLE
  • هر ستون: اسم و نوع. TEXT متن با هر طولی، INTEGER عدد صحیح.
  • SERIAL PRIMARY KEY: id خودکار ۱، ۲، ۳… می‌شود و کلید اصلی است.
  • NOT NULL: این ستون نمی‌تواند خالی باشد. (NULL در SQL یعنی «مقدار نامعلوم/خالی».)
  • DEFAULT 0: اگر مقدار ندادی، صفر.
  • دستور SQL با ; تمام می‌شود. کلمه‌های SQL را رسم است با حروف بزرگ بنویسی (CREATE) تا از اسم‌ها جدا شوند؛ PostgreSQL به بزرگی و کوچکی آن‌ها حساس نیست.

ساختار جدول را ببین:

دستورها و کلیدها
\dt
\d products
خروجی
List of relations
Schema | Name | Type | Owner
--------+----------+-------+-------
public | products | table | ali
(1 row)
Table "public.products"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+--------------------------------------
id | integer | | not null | nextval('products_id_seq'::regclass)
name | text | | not null |
price | integer | | not null |
stock | integer | | | 0
Indexes:
"products_pkey" PRIMARY KEY, btree (id)

SERIAL در واقع یک integer است که پیش‌فرضش از یک شمارنده (sequence) به اسم products_id_seq می‌آید. کلید اصلی هم خودکار یک ایندکس گرفت (درس ایندکس).

INSERT INTO products (name, price, stock) VALUES ('کتاب پایتون', 320000, 12);
INSERT INTO products (name, price, stock) VALUES ('ماوس', 450000, 30), ('کیبورد', 890000, 8);
SELECT * FROM products;
خروجی
INSERT 0 1
INSERT 0 2
id | name | price | stock
----+-------------+--------+-------
1 | کتاب پایتون | 320000 | 12
2 | ماوس | 450000 | 30
3 | کیبورد | 890000 | 8
(3 rows)
  • INSERT INTO جدول (ستون‌ها) VALUES (مقدارها) سطر اضافه می‌کند؛ با ویرگول بین پرانتزها، چند سطر یک‌جا. INSERT 0 2 یعنی «دو سطر اضافه شد».
  • متن در SQL با کوتیشن تکی ('...') است. (کوتیشن دوتایی معنی دیگری دارد؛ اشتباهات رایج.)
  • id را ندادیم؛ خودکار پر شد.
  • SELECT * FROM products همه‌ی ستون‌ها (*) و همه‌ی سطرها را برمی‌گرداند.

فقط ستون‌ها و سطرهای مشخص:

SELECT name, price FROM products WHERE price < 500000;
خروجی
name | price
-------------+--------
کتاب پایتون | 320000
ماوس | 450000
(2 rows)

WHERE فیلتر است؛ درس بعد مفصل.

⚡ بررسی سریع

دستور SQL در psql را با چه چیزی تمام می‌کنی؟

مثال ۶: دیتابیس از داده دفاع می‌کند

Section titled “مثال ۶: دیتابیس از داده دفاع می‌کند”
INSERT INTO products (price) VALUES (1000);
INSERT INTO products (name, price) VALUES ('هدفون', 'گران');
خروجی
ERROR: null value in column "name" of relation "products" violates not-null constraint
DETAIL: Failing row contains (4, null, 1000, 0).
ERROR: invalid input syntax for type integer: "گران"
LINE 1: INSERT INTO products (name, price) VALUES ('هدفون', 'گران');
^

دو سطر غلط رد شدند: اولی اسم نداشت (NOT NULL) و دومی برای ستون عددی متن داد. فایل JSON هیچ‌کدام را نمی‌گرفت. این قانون‌ها (قید یا constraint) تضمین می‌کنند هر برنامه‌ای که به این دیتابیس وصل شود، با هر زبانی، نتواند داده‌ی خراب بنویسد. (دقت کن 4 در DETAIL: شمارنده‌ی id برای سطر ردشده هم جلو رفت؛ پس شماره‌ها ممکن است فاصله داشته باشند، و این عادی است.)

مثال ۷: دستور چندخطی و نقطه‌ویرگول فراموش‌شده

Section titled “مثال ۷: دستور چندخطی و نقطه‌ویرگول فراموش‌شده”

اگر ; را فراموش کنی، psql منتظر ادامه می‌ماند و پرامپت عوض می‌شود:

صفحه
shop=> SELECT * FROM products
shop-> ;
id | name | price | stock
----+-------------+--------+-------
...

shop-> یعنی «دستورت هنوز تمام نشده». کافی است ; بزنی و Enter. اگر دستور را اشتباه شروع کرده‌ای و می‌خواهی رهایش کنی، Ctrl+C بزن. همین امکان را می‌دهد که دستورهای طولانی را در چند خط و خوانا بنویسی (مثل CREATE TABLE بالا).

PostgreSQL یک سرور است (درس کلاینت و سرور در دوره‌ی مبانی): یک سرویس systemd که همیشه روشن است، داده را در فایل‌هایی زیر /var/lib/postgresql/16/main نگه می‌دارد و روی پورت ۵۴۳۲ (و یک سوکت محلی) منتظر درخواست است. psql فقط یک کلاینت است؛ برنامه‌ی پایتون تو، یک پنل مدیریت گرافیکی یا یک اپ موبایل (از راه API) هم همین‌طور. همه با یک سرور حرف می‌زنند و سرور است که تصمیم می‌گیرد چه کسی چه کاری اجازه دارد، کدام تغییر اول ثبت شود و چطور داده بعد از قطع برق سالم بماند.

psql و برنامه‌ها کلاینت‌اند؛ سرور PostgreSQL قانون‌ها، هم‌زمانی و ذخیره روی دیسک را مدیریت می‌کند.

برای همین هرگز فایل‌های داخل /var/lib/postgresql را مستقیم کپی یا ویرایش نکن؛ بکاپ و بازیابی ابزارهای خودش را دارد (درس بکاپ).

نوع داده برای نمونه
INTEGER / BIGINT عدد صحیح / عدد خیلی بزرگ 320000
NUMERIC(10,2) عدد اعشاری دقیق (پول) 19.99
TEXT / VARCHAR(n) متن / متن با حداکثر طول 'ماوس'
BOOLEAN درست/غلط true
DATE / TIMESTAMPTZ تاریخ / زمان با منطقه‌ی زمانی '2026-10-21'
SERIAL عدد خودکار برای کلید اصلی
قید معنی
PRIMARY KEY یکتا و غیرخالی؛ شناسه‌ی سطر
NOT NULL خالی نباشد
DEFAULT v مقدار پیش‌فرض
UNIQUE تکراری نباشد
CHECK (شرط) شرط دلخواه، مثلاً CHECK (price >= 0)

۱) کوتیشن دوتایی برای متن

Section titled “۱) کوتیشن دوتایی برای متن”

INSERT INTO products (name, price) VALUES ("ماوس", 1); خطای column "ماوس" does not exist می‌دهد؛ در SQL کوتیشن دوتایی برای اسم (جدول، ستون) است و تکی برای متن. راه‌حل: 'ماوس'.

۲) نوشتن SQL در ترمینال لینوکس

Section titled “۲) نوشتن SQL در ترمینال لینوکس”
خروجی
bash: SELECT: command not found

SQL را باید داخل psql نوشت. راه‌حل: اول psql shop، یا برای یک دستور: psql shop -c "SELECT * FROM products;".

خروجی
ERROR: relation "prodcts" does not exist
LINE 1: SELECT * FROM prodcts;
^

PostgreSQL به جدول می‌گوید relation. یا غلط تایپی است، یا به دیتابیس دیگری وصلی. راه‌حل: \dt و دقت به پرامپت (shop=>).

خروجی
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: role "ali" does not exist

نقش دیتابیسی هم‌نام کاربر لینوکسی‌ات ساخته نشده. راه‌حل: مثال ۲ (sudo -u postgres createuser --createdb $USER).

۵) دست زدن مستقیم به فایل‌های داده

Section titled “۵) دست زدن مستقیم به فایل‌های داده”

کپی یا پاک کردن چیزی در /var/lib/postgresql وقتی سرور روشن است، دیتابیس را خراب می‌کند. راه‌حل: فقط با SQL و ابزارهای PostgreSQL (pg_dump در درس بکاپ).

تمرینآسان

دیتابیس جدیدی به اسم practice بساز، به آن وصل شو، با \l ببین ساخته شده و با \c shop به دیتابیس shop برگرد.

دیدن جواب
Terminal window
createdb practice
psql practice
دستورها و کلیدها
\l
\c shop
صفحه
You are now connected to database "shop" as user "ali".
shop=>

در فهرست \l سطر practice با Owner ali دیده می‌شود.

تمرینمتوسط

تمرین اصلی: در shop جدول customers بساز با ستون‌های id (خودکار، کلید اصلی)، name (متن، اجباری)، city (متن) و phone (متن، یکتا). سه مشتری اضافه کن و همه را بخوان. بعد ثابت کن دیتابیس اجازه‌ی شماره‌ی تکراری نمی‌دهد.

دیدن جواب
CREATE TABLE customers (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
city TEXT,
phone TEXT UNIQUE
);
INSERT INTO customers (name, city, phone) VALUES
('علی رضایی', 'تهران', '09120000001'),
('سارا محمدی', 'اصفهان', '09130000002'),
('رضا کریمی', 'تهران', '09120000003');
SELECT * FROM customers;
INSERT INTO customers (name, phone) VALUES ('مینا', '09120000001');
خروجی
CREATE TABLE
INSERT 0 3
id | name | city | phone
----+------------+--------+-------------
1 | علی رضایی | تهران | 09120000001
2 | سارا محمدی | اصفهان | 09130000002
3 | رضا کریمی | تهران | 09120000003
(3 rows)
ERROR: duplicate key value violates unique constraint "customers_phone_key"
DETAIL: Key (phone)=(09120000001) already exists.

شماره تلفن را TEXT گرفتیم نه عدد، چون صفر اولش مهم است و کسی رویش حساب انجام نمی‌دهد.

تمرینسخت

به جدول products قیدی اضافه کن که قیمت منفی ممنوع باشد، و ثابت کن کار می‌کند. (راهنما: ALTER TABLE products ADD CONSTRAINT price_positive CHECK (price >= 0);) بعد با \d products ببین قید کجا نمایش داده می‌شود.

دیدن جواب
ALTER TABLE products ADD CONSTRAINT price_positive CHECK (price >= 0);
INSERT INTO products (name, price) VALUES ('تخفیف عجیب', -5000);
خروجی
ALTER TABLE
ERROR: new row for relation "products" violates check constraint "price_positive"
DETAIL: Failing row contains (5, تخفیف عجیب, -5000, 0).
خروجی \d products (بخش آخر)
Indexes:
"products_pkey" PRIMARY KEY, btree (id)
Check constraints:
"price_positive" CHECK (price >= 0)

ALTER TABLE ساختار یک جدول موجود را عوض می‌کند. PostgreSQL قبل از افزودن قید، سطرهای فعلی را هم بررسی می‌کند؛ اگر از قبل قیمت منفی وجود داشت، قید اضافه نمی‌شد.

آزمونک
  1. مهم‌ترین فرق دیتابیس با فایل JSON برای یک فروشگاه چندکاربره؟

  2. در جدول، کلید اصلی (PRIMARY KEY) چیست؟

  3. پرامپت shop-> در psql یعنی…

  4. متن در SQL با کدام کوتیشن؟

  5. \dt در psql چه می‌کند؟

  6. INSERT با name خالی در ستون NOT NULL چه می‌شود؟

  • دیتابیس برنامه‌ای است برای نگه داشتن داده با هم‌زمانی امن، قانون‌های داده و جستجوی سریع؛ زبانش SQL.
  • رابطه‌ای: جدول (سطر و ستون نوع‌دار)، کلید اصلی، رابطه بین جدول‌ها. NoSQL برای کارهای خاص.
  • نصب: sudo apt install postgresql؛ نقش و دیتابیس: sudo -u postgres createuser --createdb $USER و createdb shop؛ اتصال: psql shop.
  • psql: \l، \c، \dt، \d، \q؛ SQL با ; تمام می‌شود.
  • CREATE TABLE با نوع و قید (PRIMARY KEY، NOT NULL، DEFAULT، UNIQUE، CHECK)؛ INSERT INTO ... VALUES ...؛ SELECT ... FROM ... WHERE ....
  • متن با کوتیشن تکی؛ دیتابیس داده‌ی غلط را خودش رد می‌کند.
برگه‌ی تقلب این درس
دستورکاری که می‌کند
sudo apt install postgresqlنصب
sudo -u postgres createuser --createdb $USERنقش هم‌نام خودت
createdb shop / psql shopساختن و وصل شدن
\l \c db \dt \d t \qدستورهای psql
CREATE TABLE t (id SERIAL PRIMARY KEY, ...);ساختن جدول
INSERT INTO t (a, b) VALUES ('x', 1);افزودن سطر
SELECT * FROM t WHERE ...;خواندن
psql shop -c "SELECT 1;"اجرای یک دستور از ترمینال