فصل ۱۱: اتصال ربات تلگرام به دیتابیس (SQL و NoSQL)

مقدمه فصل
فرض کن در یک ربات فروشگاهی میخواهی:
- لیست محصولات رو از دیتابیس بخونی.
- سفارشات مشتری رو ثبت کنی.
- آخرین خرید هر کاربر رو نمایش بدی.
یا در یک ربات آموزشی:
- نمره کاربر رو ذخیره کنی.
- تاریخ آخرین ورود رو داشته باشی.
- لیست سرفصلهایی که گذرانده رو ببینی.
برای تمام این کارها، ذخیره و خواندن داده از دیتابیس ضروریه.
بخش ۱: دیتابیس چیست؟
به زبان خیلی ساده، دیتابیس یک سیستم ذخیره اطلاعات است که به شما اجازه میدهد دادهها رو اضافه، حذف، ویرایش و جستجو کنید.
دو دسته اصلی:
| نوع | توضیح | مثالها |
|---|---|---|
| SQL (بانک رابطهای) | دادهها را در جدولها ذخیره میکند. هر جدول ستون و ردیف دارد. | SQLite، MySQL، PostgreSQL |
| NoSQL (بدون ساختار جدولی ثابت) | دادهها را معمولاً بهصورت JSON یا Key-Value نگه میدارد. | MongoDB، Redis |
بخش ۲: چرا SQL یا NoSQL انتخاب کنیم؟
| معیار | وقتی SQL مناسب است | وقتی NoSQL مناسب است |
|---|---|---|
| ساختار داده | ثابت و دارای ستونهای مشخص | پویا و متغیر |
| رابطه بین دادهها | بسیار زیاد | کم یا بدون رابطه |
| مقیاسپذیری | عمودی (تقویت سختافزار) | افقی (افزودن سرور) |
| مثال ربات | فروشگاه اینترنتی با جدول سفارشها | ربات ذخیره پیامهای سریع یا کش |
بخش ۳: نصب کتابخانههای لازم
برای SQL (SQLite):
pip install sqlite3 # این ماژول در پایتون بهصورت پیشفرض وجود دارد
برای NoSQL (MongoDB):
pip install pymongo
بخش ۴: مثال با SQLite (SQL ساده و داخلی پایتون)
سناریو:
ساخت رباتی که:
- وقتی کاربر دکمهای رو فشار میده، اسمش در دیتابیس ذخیره بشه.
- لیست تمام کاربران ذخیرهشده قابل مشاهده باشه.
ایجاد دیتابیس و جدول
import sqlite3
# اتصال به دیتابیس یا ایجاد آن اگر وجود نداشت
conn = sqlite3.connect("bot_data.db")
cursor = conn.cursor()
# ساخت جدول کاربران
cursor.execute("""
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER UNIQUE,
username TEXT
)
""")
conn.commit()
conn.close()
توضیح:
sqlite3.connect("bot_data.db")→ اتصال یا ساخت فایل دیتابیسCREATE TABLE IF NOT EXISTS→ ساخت جدول اگر وجود نداشت- ستونها:
id→ یک شناسه خودکارuser_id→ شناسه تلگرامی کاربرusername→ نام کاربری تلگرام
اتصال این دیتابیس به ربات با دکمه Inline
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.ext import ApplicationBuilder, CommandHandler, CallbackQueryHandler, ContextTypes
import sqlite3
TOKEN = "توکن_ربات"
# تابع افزودن کاربر
def add_user(user_id, username):
conn = sqlite3.connect("bot_data.db")
cursor = conn.cursor()
try:
cursor.execute("INSERT INTO users (user_id, username) VALUES (?, ?)", (user_id, username))
conn.commit()
except sqlite3.IntegrityError:
pass # کاربر قبلاً اضافه شده
conn.close()
# تابع نمایش کاربران
def get_users():
conn = sqlite3.connect("bot_data.db")
cursor = conn.cursor()
cursor.execute("SELECT user_id, username FROM users")
data = cursor.fetchall()
conn.close()
return data
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
keyboard = [
[InlineKeyboardButton("📥 ثبت نام", callback_data="register")],
[InlineKeyboardButton("📋 لیست کاربران", callback_data="show_users")],
]
await update.message.reply_text("یک گزینه را انتخاب کنید:", reply_markup=InlineKeyboardMarkup(keyboard))
async def button_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
query = update.callback_query
await query.answer()
if query.data == "register":
add_user(query.from_user.id, query.from_user.username or "بدون نام کاربری")
await query.edit_message_text("✅ شما با موفقیت ثبت نام شدید.")
elif query.data == "show_users":
users = get_users()
text = "👥 لیست کاربران:\n" + "\n".join([f"{u[0]} - {u[1]}" for u in users])
await query.edit_message_text(text)
app = ApplicationBuilder().token(TOKEN).build()
app.add_handler(CommandHandler("start", start))
app.add_handler(CallbackQueryHandler(button_handler))
app.run_polling()
توضیح بخشبهبخش این پروژه
- تابع
add_user→ کاربر را اگر قبلاً در دیتابیس نبوده، اضافه میکند. - تابع
get_users→ لیست همه کاربران را از جدول برمیگرداند. - دکمه «ثبت نام» → ذخیره ID و نام کاربری.
- دکمه «لیست کاربران» → نمایش همه کاربران.
بخش ۵: مثال با MongoDB (NoSQL)
اگر پروژه شما دادههای دینامیک و تغییرپذیر زیادی دارد، MongoDB گزینه خوبی است.
اتصال به MongoDB:
from pymongo import MongoClient
client = MongoClient("mongodb://localhost:27017/")
db = client["telegram_bot"]
users = db["users"]
# افزودن کاربر
users.insert_one({"user_id": 12345, "username": "test_user"})
# خواندن داده
for user in users.find():
print(user)
بخش ۶: سوالات متداول
س: آیا دیتابیس SQLite برای رباتهای بزرگ مناسب است؟
ج: برای شروع و رباتهای کوچک خوب است، ولی برای پروژههای بزرگتر پیشنهاد میشود به MySQL یا PostgreSQL مهاجرت کنید.
س: آیا MongoDB سریعتر از SQL است؟
ج: برای دادههای غیرساختاریافته و حجم خیلی بالا بله، ولی بستگی به سناریوی استفاده دارد.
بخش ۷: اشتباهات رایج
| اشتباه | توضیح |
|---|---|
| عدم بستن اتصال دیتابیس | باعث مصرف بیهوده منابع میشود. |
| ذخیره دادههای غیرضروری | دیتابیس باید فقط اطلاعات مهم و کاربردی نگه دارد. |
| نداشتن ساختار پشتیبانگیری | در صورت خرابی دیتابیس، اطلاعات از دست میرود. |
بخش ۸: نکات تکمیلی
- همیشه روی دادهها ایندکس بگذارید تا جستجو سریعتر شود.
- از رمزنگاری برای دادههای حساس مثل شماره تلفن استفاده کنید.
- برای پروژههای واقعی، فایل تنظیمات دیتابیس رو جدا کنید و در کد اصلی نگذارید.