پایگاه های داده مختلفی مثل mySQL و sqlite هست که هر کدوم مزایای خودش رو داره. در زبان پایتان ماژول هایی داریم که به ما امکان ارتباط برقرار کردن با این پایگاه های داده رو میده. برای مثال ماژول sqlite3 برای کار کردن با پایگاه های داده sqlite و ماژول mysql برای کار کردن با پایگاه های داده mySQL. روش کار کردن با این ماژول ها کم و بیش یکسانه. به صورت کلی ابتدا باید import شون کنیم، بعدش به پایگاه داده متصل شیم و سپس یک cursor درست کنیم. دستورات SQL رو از طریق متد های cursor به پایگاه داده میدیم و نتایج رو به دست میاریم. در ادامه این مقاله قدم به قدم با ماژول mysql آشنا میشیم.
پیش از هر چیزی باید MySQL Connector رو به عنوان driver نصب کنیم. این طوری:
python -m pip install mysql-connector-python
منظور از pip در دستور بالا package manager عه پایتان هست. زبان های مطرحی مثل Python برنامه هایی دارن که package هاشون رو مدیریت میکنه. برای مثال تو PHP برنامه Composer این مسئولیت رو به عهده داره. تو Node.js این قابلیت با NPM فراهم میشه و تو پایتان هم PIP عه که سردمدار مدیریت بسته هاست.
این جا فرض میکنیم که mysql از قبل روی سیستم شما نصبه. mysql.connector هم که تو قسمت بالا توضیح دادیم چطوری نصب بشه. اول از هر چیزی باید ماژول mysql.connector رو import کنیم. بعدش connection اش رو تشکیل میدیم.
import mysql.connector conn = mysql.connector.connect( host="localhost", user="root", password="any_password", database="test", # this parameter is optional )
تو کد بالا اگه پارامتر چهارم رو ندیم دستورات مون برای کل mySQL اجرا میشه. حالا در گام بعدی برای این که بتونیم دستورات SQL رو به Database برسونیم باید یک cursor درست کنیم:
cur = conn.cursor()
این شئ cur که کوتاه شده همون cursor هست مثل cursor در command line عمل میکنه و دستورات SQL رو از ما دریافت خواهد کرد.
حالا که شئ cur رو داریم می تونیم با استفاده از متد execute روش دستورات SQL مون رو به پایگاه داده ارسال کنیم:
cur.execute("SHOW TABLES")
حاصل این دستورات توی همون شئ cur ذخیره میشه و می تونیم با استفاده از یک حلقه for نتایج رو print کنیم:
for row in cur: print(row)
در نتایجی که حاصل میشه هر ردیف به صورت یک tuple هست که هر عضوش متناظر یکی از ستون های جدول ما در database میشه. برای مثال:
cur.execute("SELECT * FROM tags") rows = [row for row in cur] print(rows[0])
حاصل کد بالا (دقت کردی که با استفاده از comprehension کل ردیف ها رو توی یک list ذخیره کردیم) چیزی شبیه به این میشه:
(1, 1, 'minima', datetime.datetime(2022, 4, 20, 15, 46, 32), datetime.datetime(2022, 4, 20, 15, 46, 32))
مشاهده میکنی که یک tuple داریم. نکته جالب این جاست که خود python زحمت کشیده و ستون هایی که جنس date بودن رو به object هایی از کلاس datetime تبدیل کرده! راه ساده تری هم هست برای ذخیره نتایج! استفاده از متد fetchall مثل زیر:
cur.execute("SELECT * FROM users") users = cur.fetchall()
متد بالا همه ردیف ها رو به صورت list ای از tuple ها (هر تاپل به منزله یک ردیف) دریافت میکنه.
یکی از اصول کلیدی امنیت در پایگاه داده جلوگیری از SQL Injection هست. منظور از تزریق SQL اینه که وقتی میخایم رشته دستور SQL رو با استفاده از متغیر ها درست کنیم (هر چیزی کاربر وارد کرده رو در غالب یک متغیر ذخیره کردیم) از کجا معلوم که کاربر مثلا به جای اسمش دستور زیر رو وارد نکرده باشه:
DROP TABLE users
اگه حواسمون نباشه این SQL به پایگاه داده تزریق میشه و بعدشم که فاتحه مع صلوات! راهکار جلوگیری از این آسیب پذیری استفاده از Statement Binding هست. این یعنی به جایی که خودمون بیایم و متغیر های مد نظرمون رو به رشته SQL بچسبونیم اجازه بدیم خود Python این کار رو برامون بکنه. این شکلی:
data = ('bizhan', 26, 'male') cur.execute("INSERT INTO users(name, age, gender) VALUES (%s, %s, %s)", data)
در کد بالا چندین نکته وجود داره.
اضافه نشدن ردیف جدید به جدول users واسه اینه که commit نکردیم. منظور از commit کردن اینه که دستوراتی که در پایگاه داده تغییرات مهمی مثل INSERT کردن یک ردیف ایجاد میکنن باید commit بشن. commit از طریق conn انجام میشه و به صورت زیر:
conn.commit()
دستوراتی که قراره تو پایگاه داده تغییر ایجاد کنن باید commit بشن. مثلا: INSERT, UPDATE, DELETE و ... ولی دستوراتی که صرفا اطلاعات رو استخراج میکنن مثل SELECT نیازی به commit ندارن.
حالا فرض کن list ای از data داریم و میخایم به ازای هر کدومش یک بار دستور INSERT رو اجرا کنیم. ممکنه از حلقه for استفاده کنیم ولی راه ساده تری هم هست. متد executemany
informations = [(1, 'a'), (2, 'b'), (3, 'c')] cur.executemany("INSERT INTO tags(user_id, name) VALUES(%s, %s)", informations) conn.commit()
از همین الان که داری یاد میگیری سعی کن این عادت ها رو در خودت پرورش بدی:
conn.close()
کار کردن با پایگاه داده یک مهارت اصولی حساب میشه. به خصوص زمانی که با مباحثی مثل web development سر و کار داریم database در مرکز اهمیت قراره میگیره. حتی نرم افزار هایی مثل firefox هم پایگاه داده های local خودشون رو دارن. برای مثال history در مرورگر google chrome به صورت یک sqlite database ذخیره میشه. بر خلاف mySQL که خیلی مفصل تر و مرکزی عه، پایگاه های داده sqlite به صورت یک فایل داخل همون پوشه برنامه خودت می تونن ذخیره بشن. کار کردن با ماژول sqlite هم ۹۰ درصد شبیه به همین mysql.connector عه.در نهایت خوشحال میشم اگه من رو به یک کامنت مهمون کنی.