এখানেই Python-এর প্রকৃত ডেটা সংরক্ষণ আর পুনরুদ্ধার করার ক্ষমতা ব্যবহারিক হয়ে ওঠে। এখনও SQL পরিচিতি পাঠটি না দেখে থাকলে, এখনই সেটা দেখার সঠিক সময় — এখান থেকে, এই পাঠটি ধরে নেয় আপনি জানেন একটি টেবিল, সারি, আর একটি সাধারণ SELECT স্টেটমেন্ট কী।
Python-এর স্ট্যান্ডার্ড লাইব্রেরিতে sqlite3 অন্তর্ভুক্ত — SQLite-এর জন্য একটি কানেক্টর, একটি সাধারণ ডেটাবেস একটি একক ফাইলে সংরক্ষিত, কোনো আলাদা সার্ভার বা এক্সটেনশনের দরকার নেই। এটি শুরু করার সবচেয়ে সহজ উপায়:
import sqlite3
conn = sqlite3.connect("school.db")
cursor = conn.cursor()
cursor.execute("SELECT name, course FROM students")
for row in cursor.fetchall():
print(row)
conn.close()নির্দিষ্টভাবে MySQL-এর জন্য — এই সাইটের নিজের SQL অংশ যা শেখায় সেই একই ডেটাবেস — একটি থার্ড-পার্টি প্যাকেজ কানেকশন হ্যান্ডেল করে, pip দিয়ে ইনস্টল করা (Modules and Imports পাঠ থেকে):
pip install mysql-connector-pythonimport mysql.connector
try:
conn = mysql.connector.connect(
host="localhost",
user="root",
password="",
database="school",
)
print("Connected successfully.")
except mysql.connector.Error as e:
print(f"Connection failed: {e}")কানেকশনকে (Exception Handling পাঠের) try/except-এ মোড়ানো এখানে গুরুত্বপূর্ণ — একটি ডেটাবেস আপনার কোডের সাথে সম্পর্কহীন কারণে সাময়িকভাবে অপ্রাপ্য হতে পারে।
কখনো সরাসরি একটি ভ্যারিয়েবল SQL স্ট্রিং-এ জোড়া লাগিয়ে একটি কোয়েরি তৈরি করবেন না — ডেটাবেসের সাথে কথা বলা প্রতিটি ভাষায় এটা গুরুত্বপূর্ণ, Python-ও এর ব্যতিক্রম নয়। Python-এর ডেটাবেস কানেক্টর সরাসরি ভ্যারিয়েবল জোড়া লাগানোর বদলে %s প্লেসহোল্ডার ব্যবহার করে:
cursor = conn.cursor()
# NEVER do this:
# cursor.execute(f"SELECT * FROM students WHERE name = '{name}'")
# Do this instead:
cursor.execute("SELECT * FROM students WHERE name = %s", (name,))
result = cursor.fetchone()এটি ঐচ্ছিক নয়
একটি ভ্যারিয়েবল সরাসরি একটি SQL স্ট্রিংয়ে জোড়া লাগালে SQL injection-এর দরজা খুলে যায় — একজন visitor anything' OR '1'='1-এর মতো কিছু দিলে আপনার কোয়েরির লজিক সম্পূর্ণভাবে পুনর্লিখন করে ফেলতে পারে। প্যারামিটারাইজড কোয়েরি এটা পুরোপুরি বন্ধ করে দেয়, কারণ ডেটাবেস ড্রাইভার নিজেই ডেটা আর কোডকে আলাদা রাখে — এটা "সহজ ক্ষেত্রে" বাদ দেওয়ার মতো কিছু নয়, কখনোই না।
# INSERT
cursor.execute("INSERT INTO students (name, course) VALUES (%s, %s)", ("Priya", "Web Development"))
conn.commit() # writes are not saved until you commit
# UPDATE
cursor.execute("UPDATE students SET course = %s WHERE name = %s", ("Graphic Design", "Priya"))
conn.commit()
# DELETE
cursor.execute("DELETE FROM students WHERE name = %s", ("Priya",))
conn.commit()conn.commit() নির্দিষ্টভাবে উল্লেখ করার মতো: Python-এর কানেক্টরে একটি লেখার পর একটি স্পষ্ট commit() দরকার, নাহলে পরিবর্তনটা আসলে সংরক্ষিত হবে না — লেখা স্বয়ংক্রিয়ভাবে commit হয় না।
আগের sqlite3 উদাহরণটি fetchall() ব্যবহার করেছিল — cursor আসলে ফলাফল ফেরত আনার তিনটি উপায় দেয়, আর সঠিকটা বেছে নিলে প্রয়োজনের চেয়ে বেশি মেমরিতে লোড হওয়া এড়ানো যায়:
| মেথড | রিটার্ন করে |
|---|---|
| cursor.fetchone() | একটি একক সারি (বা আর না থাকলে None) — যখন আপনি ঠিক একটি ফলাফল প্রত্যাশা করেন তখন ব্যবহার করুন |
| cursor.fetchmany(n) | একবারে সর্বোচ্চ n সারি — খণ্ডে একটি বড় ফলাফল সেটের মধ্যে দিয়ে paging করার জন্য দরকারি |
| cursor.fetchall() | বাকি প্রতিটি সারি, একটি লিস্ট হিসেবে — ছোট ফলাফল সেটের জন্য ঠিক আছে, বিশাল সেটের জন্য অপচয়ী |
cursor.execute("SELECT * FROM students WHERE name = %s", ("Priya",))
student = cursor.fetchone() # a single row, since names should be unique here
print(student)