بیژن حجازی
بیژن حجازی
خواندن ۵ دقیقه·۳ سال پیش

mySQL در پایتان

کار کردن با database در زبان پایتان راحت و سریعه.
کار کردن با database در زبان پایتان راحت و سریعه.

مقدمه

پایگاه های داده مختلفی مثل mySQL و sqlite هست که هر کدوم مزایای خودش رو داره. در زبان پایتان ماژول هایی داریم که به ما امکان ارتباط برقرار کردن با این پایگاه های داده رو میده. برای مثال ماژول sqlite3 برای کار کردن با پایگاه های داده sqlite و ماژول mysql برای کار کردن با پایگاه های داده mySQL. روش کار کردن با این ماژول ها کم و بیش یکسانه. به صورت کلی ابتدا باید import شون کنیم، بعدش به پایگاه داده متصل شیم و سپس یک cursor درست کنیم. دستورات SQL رو از طریق متد های cursor به پایگاه داده میدیم و نتایج رو به دست میاریم. در ادامه این مقاله قدم به قدم با ماژول mysql آشنا میشیم.

نصب Driver

پیش از هر چیزی باید 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=&quotlocalhost&quot, user=&quotroot&quot, password=&quotany_password&quot, database=&quottest&quot, # this parameter is optional )

تو کد بالا اگه پارامتر چهارم رو ندیم دستورات مون برای کل mySQL اجرا میشه. حالا در گام بعدی برای این که بتونیم دستورات SQL رو به Database برسونیم باید یک cursor درست کنیم:

cur = conn.cursor()

این شئ cur که کوتاه شده همون cursor هست مثل cursor در command line عمل میکنه و دستورات SQL رو از ما دریافت خواهد کرد.

اجرا دستورات SQL

حالا که شئ cur رو داریم می تونیم با استفاده از متد execute روش دستورات SQL مون رو به پایگاه داده ارسال کنیم:

cur.execute(&quotSHOW TABLES&quot)

حاصل این دستورات توی همون شئ cur ذخیره میشه و می تونیم با استفاده از یک حلقه for نتایج رو print کنیم:

for row in cur: print(row)

در نتایجی که حاصل میشه هر ردیف به صورت یک tuple هست که هر عضوش متناظر یکی از ستون های جدول ما در database میشه. برای مثال:

cur.execute(&quotSELECT * FROM tags&quot) 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(&quotSELECT * FROM users&quot) users = cur.fetchall()

متد بالا همه ردیف ها رو به صورت list ای از tuple ها (هر تاپل به منزله یک ردیف) دریافت میکنه.

Statement Binding

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

DROP TABLE users

اگه حواسمون نباشه این SQL به پایگاه داده تزریق میشه و بعدشم که فاتحه مع صلوات! راهکار جلوگیری از این آسیب پذیری استفاده از Statement Binding هست. این یعنی به جایی که خودمون بیایم و متغیر های مد نظرمون رو به رشته SQL بچسبونیم اجازه بدیم خود Python این کار رو برامون بکنه. این شکلی:

data = ('bizhan', 26, 'male') cur.execute(&quotINSERT INTO users(name, age, gender) VALUES (%s, %s, %s)&quot, data)

در کد بالا چندین نکته وجود داره.

  • اولا این که عدد ۲۶ هر چند از جنس integer هست ولی برای bind کردنش به رشته SQL از s% استفاده کردیم. شاید در نگاه اول شبیه به string formatting برسه ولی این تشابه اتفاقی عه.
  • دوم این که به جای 's%' نوشتیم s%. در غیر این صورت ارور میده.
  • و نکته آخر این که اگه بعد از اجرای این دستور جدول users رو نگاه کنیم می بینیم که چیزی اضافه نشده؟!!! چرا؟!

اضافه نشدن ردیف جدید به جدول 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(&quotINSERT INTO tags(user_id, name) VALUES(%s, %s)&quot, informations) conn.commit()

عادت های خوب

از همین الان که داری یاد میگیری سعی کن این عادت ها رو در خودت پرورش بدی:

  • هنگام تمام شدن عملیات conn رو ببندی. این طوری:
conn.close()
  • کد هایی که ممکنه exception درست کنه رو داخل try قرار بدی. مثلا فرض کن که یکی از ستون های جدولت مقادیر تکراری نمی پذیره (Unique داره) و تو همه کد هات رو درست زدی و خطایی نیست منتها به حاصل نهایی نمیرسی.
  • از statement binding خود متد execute استفاده کنی به جای این که خودت string format کنی.
  • قبل از استفاده از هر گونه data ای که از سمت کاربر میاد، بررسیش کنی. شاید خطرناک باشه. به این کار میگن validate کردن که در عین سادگی، مهم و ظریفه. نیازی نیست همه کارای validation رو خودت بکنی. کتاب خونه هایی مثل Django امکانات از پیش آماده شده ای برای validation در نظر گرفتن.

نتیجه گیری

کار کردن با پایگاه داده یک مهارت اصولی حساب میشه. به خصوص زمانی که با مباحثی مثل web development سر و کار داریم database در مرکز اهمیت قراره میگیره. حتی نرم افزار هایی مثل firefox هم پایگاه داده های local خودشون رو دارن. برای مثال history در مرورگر google chrome به صورت یک sqlite database ذخیره میشه. بر خلاف mySQL که خیلی مفصل تر و مرکزی عه، پایگاه های داده sqlite به صورت یک فایل داخل همون پوشه برنامه خودت می تونن ذخیره بشن. کار کردن با ماژول sqlite هم ۹۰ درصد شبیه به همین mysql.connector عه.در نهایت خوشحال میشم اگه من رو به یک کامنت مهمون کنی.

پایتانپایتونبرنامه نویسیتوسعه وبکد نویسی
سلام! نوشتن به منزله مطالعه «خود» هست. من بیشتر تو زمینه برنامه نویسی و روان شناسی مطلب میذارم. خوشحال میشم نظرات تون رو باهام در میون بذارین.
شاید از این پست‌ها خوشتان بیاید