FA-TOOLS — Header Component
آموزش sqlite در پایتون

آموزش کامل SQLite در پایتون: از مفاهیم پایه تا مدیریت پیشرفته داده‌ها

فهرست مطالب

  • SQLite چیست و چرا در پایتون استفاده می‌شود؟
  • اتصال به دیتابیس و مدیریت ساختار (Schema)
  • انجام عملیات اصلی CRUD با رعایت امنیت
  • مدیریت تراکنش‌ها (Transactions) و Context Manager
  • نکات تخصصی و بهینه‌سازی عملکرد (WAL، In-Memory و توابع سفارشی)
  • جدول مقایسه SQLite با پایگاه‌های داده سرورمحور
  • عیب‌یابی سریع و رفع خطاهای رایج
  • پرسش‌های متداول
خلاصه سریع:

کتابخانه sqlite3 به‌صورت داخلی در پایتون قرار دارد و نیازی به نصب سرور جداگانه ندارد. شما می‌توانید دیتابیس‌های سبک، سریع و ایمن را در قالب یک فایل منفرد ایجاد کنید. رعایت پرس‌وجوهای پارامتری برای جلوگیری از SQL Injection، استفاده از حالت WAL برای بهبود سرعت، و به‌کارگیری Context Managerها از مهم‌ترین اصول کار با SQLite در پروژه‌های واقعی است.

پایتون با ارائه کتابخانه داخلی sqlite3، امکان ذخیره‌سازی و مدیریت داده‌ها را بدون نیاز به راه‌اندازی سرورهای سنگین فراهم کرده است. این دیتابیس تمام اطلاعات را در یک فایل معمولی روی دیسک ذخیره می‌کند و برای نرم‌افزارهای دسکتاپ، ابزارهای تست، سیستم‌های کوچک و برنامه‌های پردازش داده انتخابی ایده‌آل است. در این مقاله جامع، نحوه‌ی پیاده‌سازی حرفه‌ای SQLite در پایتون را به‌صورت گام‌به‌گام و با سناریوهای کاربردی مرور می‌کنیم.

SQLite چیست و چرا در پایتون استفاده می‌شود؟

SQLite چیست و چرا در پایتون استفاده می‌شود؟

پایگاه داده SQLite یک موتور دیتابیس خودکفا (Self-contained)، بدون نیاز به سرور (Serverless) و بدون نیاز به پیکربندی (Zero-configuration) است. این دیتابیس به دلیل سرعت بالا، حجم کم و یکپارچگی کامل با پایتون، محبوب‌ترین گزینه برای ذخیره‌سازی محلی داده‌ها محسوب می‌شود.

برخلاف پایگاه‌های داده‌ای مانند PostgreSQL یا MySQL که به‌صورت یک فرآیند مجزا (Server Process) اجرا می‌شوند و از طریق شبکه ارتباط برقرار می‌کنند، SQLite مستقیماً درون برنامه شما اجرا می‌شود. تمام جداول، اندیس‌ها و داده‌ها درون یک فایل واحد با پسوند .db یا .sqlite قرار می‌گیرند.

اصلی‌ترین مزایای استفاده از SQLite در پایتون عبارتند از:

  • عدم نیاز به نصب وابسته: کتابخانه استاندارد sqlite3 همراه با پایتون نصب می‌شود.
  • پرتابل بودن (Portability): نقل‌وانتقال دیتابیس به سادگیِ کپی کردن یک فایل است.
  • پشتیبانی از استاندارد ACID: تمام تراکنش‌ها به‌صورت کامل ایمن و قابل استناد هستند.
  • مصرف ناچیز منابع: حافظه RAM بسیار کمی اشغال می‌کند و اجرا بسیار سریع است.

اتصال به دیتابیس و مدیریت ساختار (Schema)

اتصال به دیتابیس و مدیریت ساختار (Schema)

برای شروع کار با SQLite در پایتون، کافیست ماژول sqlite3 را وارد کرده و متد connect را فراخوانی کنید. این متد در صورت عدم وجود فایل دیتابیس، آن را به‌صورت خودکار می‌سازد.

برای برقراری ارتباط و ایجاد یک جدول نمونه، طبق مراحل زیر عمل می‌کنیم. در فرآیند توسعه نرم‌افزار، استفاده از شیء Cursor برای اجرای دستورات SQL ضروری است.

  1. وارد کردن ماژول sqlite3.
  2. ایجاد اتصال (Connection) به فایل دیتابیس.
  3. ایجاد نشانگر (Cursor) برای اجرای دستورات.
  4. اجرای دستور SQL ساخت جدول با استفاده از CREATE TABLE IF NOT EXISTS.
  5. بستن اتصال جهت آزادسازی منابع دیسک.
import sqlite3

# اتصال به دیتابیس (اگر وجود نداشته باشد، ساخته می‌شود)
conn = sqlite3.connect("app_data.db")

# ایجاد کرسر برای اجرای دستورات
cursor = conn.cursor()

# ساخت جدول کاربران
cursor.execute("""
CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    username TEXT NOT NULL UNIQUE,
    email TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""")

# ذخیره تغییرات و بستن اتصال
conn.commit()
conn.close()

انجام عملیات اصلی CRUD با رعایت امنیت

انجام عملیات اصلی CRUD با رعایت امنیت

عملیات CRUD شامل چهار بخش اصلی ساخت (Create)، خواندن (Read)، به‌روزرسانی (Update) و حذف (Delete) داده‌ها است. امن‌ترین روش برای درج متغیرها در دستورات SQL استفاده از علامت سؤال (Placeholder) به جای چسباندن رشته‌ها است.

هرگز از f-string یا ترکیب مستقیم رشته‌ها برای ساخت دستورات SQL استفاده نکنید؛ زیرا این کار برنامه شما را در معرض حملات تزریق کد (SQL Injection) قرار می‌دهد. هنگام توسعه برنامه‌ها در کنار استفاده از تکه‌کدهای پایتون برای پردازش متن، امنیت دیتابیس همیشه باید در اولویت باشد.

۱. درج داده (Create)

برای درج یک رکورد از execute و برای درج دسته‌ای از executemany استفاده می‌شود:

conn = sqlite3.connect("app_data.db")
cursor = conn.cursor()

# درج یک رکورد به‌صورت امن
user_data = ("ali_dev", "ali@example.com")
cursor.execute("INSERT INTO users (username, email) VALUES (?, ?)", user_data)

# درج دسته‌ای از داده‌ها (Batch Insert)
many_users = [
    ("sara_m", "sara@example.com"),
    ("reza_k", "reza@example.com")
]
cursor.executemany("INSERT INTO users (username, email) VALUES (?, ?)", many_users)

conn.commit()
conn.close()

۲. خواندن داده‌ها (Read)

برای دریافت اطلاعات سه متد اصلی وجود دارد: fetchone() (دریافت یک سطر)، fetchall() (دریافت تمام سطور به‌صورت لیست) و fetchmany(size) (دریافت تعداد مشخصی سطر):

conn = sqlite3.connect("app_data.db")
cursor = conn.cursor()

# خواندن تمام کاربران
cursor.execute("SELECT id, username, email FROM users")
all_users = cursor.fetchall()

for user in all_users:
    print(f"ID: {user[0]}, Username: {user[1]}, Email: {user[2]}")

conn.close()

۳. به روزرسانی و حذف (Update & Delete)

عملیات ویرایش و حذف نیز دقیقاً طبق الگوی پارامتری انجام می‌شوند تا از تغییر ناخواسته کل جدول جلوگیری شود:

conn = sqlite3.connect("app_data.db")
cursor = conn.cursor()

# به‌روزرسانی ایمیل یک کاربر مشخص
cursor.execute("UPDATE users SET email = ? WHERE username = ?", ("new_ali@example.com", "ali_dev"))

# حذف یک کاربر
cursor.execute("DELETE FROM users WHERE id = ?", (3,))

conn.commit()
print(f"تعداد سطور تغییر یافته: {cursor.rowcount}")
conn.close()

مدیریت تراکنش‌ها (Transactions) و Context Manager

مدیریت تراکنش‌ها (Transactions) و Context Manager

استفاده از دستور with در پایتون (Context Manager) تضمین می‌کند که تراکنش‌ها در صورت بروز خطا به‌طور خودکار Rollback شوند و در صورت موفقیت، Commit گردند. این کار مانع از قفل ماندن فایل دیتابیس می‌شود.

در پروژه‌های صنعتی، اگر هنگام اجرای چند دستور SQL متوالی خطایی رخ دهد (مثلاً قطع شدن جریان برنامه وسط انتقال پول)، نباید هیچ‌یک از دستورات اعمال شوند. مدیریت تراکنش با with connection: این ایمنی را فراهم می‌سازد:

import sqlite3

conn = sqlite3.connect("app_data.db")

try:
    with conn:
        # تمام این دستورات در قالب یک تراکنش انجام می‌شوند
        conn.execute("INSERT INTO users (username, email) VALUES (?, ?)", ("user_a", "a@test.com"))
        conn.execute("INSERT INTO users (username, email) VALUES (?, ?)", ("user_b", "b@test.com"))
        # اگر در این نقطه خطایی رخ دهد، تمام درج‌های بالا لغو می‌شوند.
except sqlite3.IntegrityError as e:
    print(f"خطای یکپارچگی داده‌ها: {e}")
finally:
    conn.close()

نکات تخصصی و بهینه‌سازی عملکرد (Expert Insights)

نکات تخصصی و بهینه‌سازی عملکرد (Expert Insights)

در اغلب آموزش‌های مقدماتی فقط به دستورات ساده اشاره می‌شود، اما برای پیاده‌سازی پروژه‌های سنگین‌تر رعایت چند نکته کلیدی زیر الزامی است:

۱. فعال‌سازی حالت WAL (Write-Ahead Logging) برای همزمانی بالا

به‌طور پیش‌فرض وقتی یک فرآیند در حال نوشتن روی دیتابیس SQLite است، تمام خواننده‌ها قفل می‌شوند. برای رفع این مشکل و افزایش چشمگیر سرعت نوشتن و خواندن همزمان، حالت WAL را فعال کنید:

conn = sqlite3.connect("app_data.db")
conn.execute("PRAGMA journal_mode=WAL;")

۲. دیتابیس‌های درون حافظه (In-Memory Database)

اگر نیازی به ذخیره‌سازی دائمی روی دیسک ندارید و فقط می‌خواهید داده‌ها را سریع پردازش کنید، از مسیر :memory: استفاده کنید. این حالت سرعت خارق‌العاده‌ای به شما می‌دهد. برای مثال می‌توانید داده‌های موقت را مدیریت کرده و سپس جهت پردازش‌های آماری سنگین‌تر به سراغ آموزش پانداس در پایتون بروید و خروجی را به Dataframe تبدیل کنید.

# ساخت دیتابیس موقت در رم (RAM)
mem_conn = sqlite3.connect(":memory:")

۳. تعریف توابع سفارشی پایتون درون SQL

یکی از قابلیت‌های فوق‌العاده sqlite3 امکان نگاشت توابع پایتونی به درون کوئری‌های SQL است. با متد create_function می‌توان این کار را انجام داد:

def reverse_string(text):
    return text[::-1]

conn = sqlite3.connect(":memory:")
# نام تابع در SQL، تعداد ورودی‌ها، خود تابع
conn.create_function("REVERSE", 1, reverse_string)

cursor = conn.cursor()
cursor.execute("SELECT REVERSE('Python')")
print(cursor.fetchone()[0])  # خروجی: nohtyP

۴. فعال‌سازی اجباری کلیدهای خارجی (Foreign Keys)

SQLite به‌صورت پیش‌فرض قیدهای کلید خارجی را بررسی نمی‌کند! برای تضمین ارجاعات بین جداول باید پس از هر اتصال، آن را دستوری فعال کنید:

conn = sqlite3.connect("app_data.db")
conn.execute("PRAGMA foreign_keys = ON;")

جدول مقایسه SQLite با پایگاه‌های داده سرورمحور

انتخاب دیتابیس مناسب بستگی به معماری پروژه شما دارد. جدول زیر دید دقیقی برای تصمیم‌گیری ارائه می‌دهد:

معیار ارزیابی وضعیت در SQLite
نیاز به نصب و پیکربندی سرور ندارد (کامل کامپکت در قالب یک فایل)
حجم دیتابیس و الگوی ذخیره‌سازی مناسب تا حدود ۱۴۰ ترابایت (در عمل بهتر است زیر چند صد گیگابایت باشد)
همزمانی نوشتن (Concurrent Writes) محدود (فقط یک اتصال همزمان می‌تواند عملیات نوشتن انجام دهد)
مناسب برای سناریوهای کاربردی اپلیکیشن‌های دسکتاپ، اینترنت اشیاء، برنامه‌های کوچک وب و ابزارهای اتوماسیون کارهای تکراری در پایتون

عیب‌یابی سریع و رفع خطاهای رایج

در هنگام توسعه برنامه‌ها ممکن است با خطاهای مشخصی مواجه شوید. در ادامه راهکار عملی رفع این مشکلات ارائه شده است:

خطای sqlite3.OperationalError: database is locked

علت: یک اتصال دیگر در حال نوشتن روی فایل است و فایل قفل شده است.
راه‌حل: مدت زمان تاخیر را با مقداردهی timeout افزایش دهید (مثلاً sqlite3.connect('app.db', timeout=10)) یا حالت WAL را فعال کنید.

خطای sqlite3.IntegrityError: UNIQUE constraint failed

علت: سعی دارید داده‌ای تکراری در ستونی که شرط UNIQUE دارد وارد کنید.
راه‌حل: قبل از درج، وجود داده را چک کنید یا از INSERT OR IGNORE یا INSERT OR REPLACE در کوئری SQL خود استفاده کنید.

خطای sqlite3.ProgrammingError: Incorrect number of bindings supplied

علت: تعداد علائم ? در SQL با تعداد اعضای تاپل (Tuple) ارسالی همخوانی ندارد.
راه‌حل: اگر فقط یک متغیر ارسال می‌کنید، حتماً کامای انتهایی تاپل را بگذارید؛ مثلاً (val,) به جای (val).

پرسش‌های متداول

آیا برای کار با SQLite در پایتون باید پکیجی با pip نصب کنیم؟

خیر، کتابخانه sqlite3 یکی از ماژول‌های داخلی پایتون است و نیازی به اجرای هیچ دستور نصبی ندارد.

چگونه می‌توان خروجی کوئری‌ها را به دیکشنری تبدیل کرد تا بر اساس اسم ستون دسترسی داشته باشیم؟

کافیست خاصیت conn.row_factory = sqlite3.Row را تنظیم کنید. پس از این کار، سطرها مانند دیکشنری با کلیدِ نام ستون قابل خواندن خواهند بود.

آیا SQLite برای سایت‌های وب واقعی مناسب است؟

برای وب‌سایت‌های کوچک تا متوسط (با ترافیک معمولی روزانه) عالی است. اما برای سایت‌هایی با ترافیک بسیار سنگین که میزان نوشتن همزمان بالایی دارند، استفاده از دیتابیس‌هایی مثل PostgreSQL توصیه می‌شود.

تفاوت commit و rollback چیست؟

دستور commit تمام تغییرات انجام‌شده در تراکنش جاری را روی دیسک ثبت دائمی می‌کند، اما rollback تمام تغییرات اعمال‌نشده را لغو کرده و دیتابیس را به حالت قبل بازمی‌گرداند.

سوالات متداول

آیا برای استفاده از SQLite در پایتون نیاز به نصب سرور مجزا است؟

خیر، کتابخانه sqlite3 به صورت داخلی در پایتون قرار دارد و تمام داده‌ها در قالب یک فایل ذخیره می‌شوند، بنابراین نیازی به نصب و پیکربندی سرور جداگانه نیست.

چگونه از حملات SQL Injection در SQLite پایتون جلوگیری کنیم؟

با استفاده از پرس‌وجوهای پارامتری و قرار دادن علامت سوال (?) به جای چسباندن مستقیم رشته‌ها یا استفاده از f-string در دستورات SQL، امنیت دیتابیس کاملاً تامین می‌شود.

تفاوت متد executemany با execute در پایتون چیست؟

متد execute برای اجرای یک دستور واحد یا درج یک رکورد استفاده می‌شود، در حالی که executemany برای درج دسته‌ای داده‌ها (Batch Insert) با سرعت بالا به کار می‌رود.

کاربرد Context Manager (دستور with) در مدیریت دیتابیس چیست؟

استفاده از دستور with تضمین می‌کند که تراکنش‌ها در صورت اجرای موفقیت‌آمیز Commit شده و در صورت بروز هرگونه خطا به‌طور خودکار Rollback شوند تا فایل دیتابیس قفل نشود.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *