اجرای دستورات خام Sql در SQLAlchemy

در پست قبلی درباره کتابخونه فوق العاده SQLAlchemy نوشتم و مثال هایی از نحوه استفاده از اون به صورت ORM، ولی موقعیت هایی پیش میاد که یا پروژه مورد ساده ایه یا میخواید بدون اینکه وقت بزارید و یک کوئری رو به معادلش در SQLAlchemy تبدیل کنید سریع اون رو اجرا کنید.

برای اینکار باز هم SQLAlchemy کمکتون میکنه. مثال های زیر رو ببینید

اگه تو کوئری از prepared statement استفاده میکنید باید کوئری رو تو تابع text قرار بدید.

نکته: cursor متغیریه که با MySQL در ارتباط هست.

و توضیح این توابع

scalar

اولین فیلد از اولین رکورد نتایج رو برمیگردونه و cursor رو میبنده, اگه دوباره تابع رو اجرا کنید با خطا مواجه میشید چون cursor بسته شده.

fetchone

اولین رکورد نتایح رو برمیگردونه و در فراخوانی بعدی رکورد بعدی، زمانی که تمام نتایج رو بگیرید در فراخوانی بعدی None دریافت میکنید.

fetchall

تمام نتایج رو یکجا برمیگردونه و زمانی که تمام نتایج رو بگیرید در فراخوانی بعدی یک لیست خالی دریافت میکنید.

first

اولین نتیجه رو بر میگردونه و cursor رو میبنده, اگه دوباره تابع رو اجرا کنید با خطا مواجه میشید که cursor بسته شده.

 

توجه داشته باشید که وقتی از scalar یا fetchone یا first استفاده میکنید در دستور sql هیچ تغییری ایجاد نمیشه و تنها نتایج رو فیلتر میکنن یعنی نمیشه بگیم که سرعت fetchone بیشتر از fetchall هست چون فقط یک رکورد رو برمیگردونه، اگه رکوردهاتون زیاد هست و فقط اولین رکورد خروجی رو میخواید و سرعت هم براتون مهم هست باید limit 1 رو به انتهای دستور sql در تابع fechone اضافه کنید.

 

fetchmany

مواقعی هست که  نتایج خیلی زیاد هست برای مثال بیشتر از ۱۰ هزار رکورد، وقتی همچین نتایجی رو میخواید پردازش کنید ممکن هست با مشکل حافظه مواجه بشید برای حل این مشکل باید با تابع fetchmany نتایج رو قسمت قسمت پردازش کنید، توجه داشته باشید در این روش نتایج یکجا از MySQL دریافت میشه. زمانی که تمام نتایج رو بگیرید در فراخوانی بعدی یک لیست خالی دریافت میکنید.

برای دیدن مثال های بیشتر از توابع بالا اینجا رو ببینید.

کلا بهتر هست که از parameter binding برای ارسال مقادیر استفاده کنید اما مواقعی هست که نمیشه مثلا اگه بخواید insert…select کنید اونموقع باید query رو به روش زیر بسازید

قبلش باید pymysql رو نصب کنید  pip install pymysql

تبدیل ‘:’ به ‘:\’ در واقع برای اسکیپ کردن ‘:’ هست چون SQLAlchemy وقتی این کاراکتر رو میبینه انتظار داره که یک مقدار متناظر در پارامتر دوم execute داشته باشه اما با این کار میگیم اینطوری نیستش و مثل یک کاراکتر عادی باهاش برخورد کنه.

باز هم میگم که این روش خطر حمله SQL Injection رو داره و بهتر هست استفاده نکنید.

چطوری رکورد های زیادی رو دریافت کنیم؟

اول پیشنهاد میکنم نوشته قبلیم ۷۰۰ میلیون رکورد MySQL را به راحتی آب خوردن با PHP پردازش کنید  که در همین رابطه هست رو بخونید.

به صورت پیشفرض وقتی یک کوئری اجرا کنید تمام نتایج از سرور MySQL دریافت میشه و به صورت بافر تو حافظه سرور پایتون بارگزاری میشه و با توجه به تابعی که استفاده میکنید مثل first, fetchall, fetchone, scalar یا fetchmany نتایج فیلتر میشن حالا اگه نتایج خیلی زیاد باشن تو همون دریافت نتایج به مشکل خواهید خورد.

برای حل این مشکل باید از SSCursor یا Server Side Cursor استفاده کنید که به صورت unbuffered نتایج رو دریافت میکنه تو این حالت وقتی کوئری ارسال میشه اول باید صبر کنید تا MySQL کوئری رو اجرا و نتایج رو آماده کنه در مرحله بعد MySQL به جای نتایج یک resource به پایتون ارسال میکنه و بعد با توجه به تابعی که استفاده میکنید نتایج اصلی از سرور MySQL دریافت میشه.

مزیت این روش همونطور که گفتم این هست که نتایج به یکباره در سرور پایتون بارگزاری نمیشه.

به چند روش هم میتونید unbuffered queries رو فعال کنید اولیش استفاده مستقیم از SSCursor هست

روش دوم قرار دادن server_side_cursors برابر True در db_engine

و روش سوم

خوب در نظر بگیرید میخوایم 100 هزار رکورد رو از MySQL بگیریم باید از SSCursor در کنار fetchmany استفاده کنیم

برای دیدن مثال های بیشتر از توابع بالا اینجا رو ببینید.

چندین راه برای اجرای دستورات خام هست من این راه رو همیشه استفاده میکنم یعنی از Session استفاده میکنم و تمام دستورات رو کاملن مستقل اجرا میکنم بدون اینکه هیچ کلاسی تعریف کنم

یه نکته مهم اینکه تو حذف کردن یا ایجاد رکورد ممکن هست که warning بده

در تمام دستورات بالا با استفاده از sessionmaker یک session ایجاد کردیم اگه میخواید از session استفاد نکنید میتونید از متد connect استفاده کنید. مثال

برای مثالهای بیشتر هم اینجا و اینجا رو ببینید.

جستجو در کل مطالب سایت

نوشته های مشابه

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

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