ESC را فشار دهید تا بسته شود

زمیوس آموزش، یادگیری و سرگرمی

نحوه نوشتن Dynamic SQL امن و بهینه در Oracle

برای نوشتن Dynamic SQL امن و بهینه در Oracle باید از EXECUTE IMMEDIATE یا DBMS_SQL به‌درستی استفاده کنید، ورودی‌ها را اعتبارسنجی کنید، از Bind Variable بهره ببرید، و اجرای کد را با Exception Handling امن نگه دارید.

در این مقاله آموزش اوراکل در بخش برنامه نویسی PL/SQL با نحوه نوشتن Dynamic SQL به‌صورت امن و بهینه در Oracle آشنا می‌شوید.

اگر می خواهید به عنوان یک برنامه نویس دیتابیس اوراکل بیشتر با تفاوت های SQL و PL/SQL بیشتر آشنا بشید، پیشنهاد می شود نوشته زیر را مطالعه کنید:

در این نوشته شما می خوانید

Dynamic SQL در Oracle چیست؟

Dynamic SQL یعنی نوشتن دستور SQL به‌صورت پویا و اجرای آن در زمان اجرا، نه زمان کامپایل. مثلاً وقتی نمی‌دانید دقیقاً چه ستونی، شرطی یا جدولی قرار است استفاده شود.

Oracle دو روش اصلی برای این کار دارد:

  • EXECUTE IMMEDIATE برای اجرای سریع دستورات ساده
  • DBMS_SQL برای اجرای دستورات پیچیده با تعداد ستون متغیر

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

				
					DECLARE
  v_sql VARCHAR2(1000);
BEGIN
  v_sql := 'UPDATE employees SET salary = salary * 1.1
  WHERE department_id = 10';
  EXECUTE IMMEDIATE v_sql;
END;

				
			

کاربردهای اصلی Dynamic SQL

  • زمانی که نام جدول یا ستون در زمان اجرا مشخص می‌شود
  • ایجاد گزارش‌های پویا با فیلترهای متغیر
  • اجرای دستورات DDL مانند CREATE, ALTER, DROP
  • طراحی ماژول‌های عمومی و چندمنظوره در سیستم‌های بزرگ

🔐 چگونه Dynamic SQL امن بنویسیم؟

🔹 ۱. استفاده از Bind Variable (کلیدی‌ترین نکته امنیتی)

به جای اینکه مقدار ورودی را مستقیماً داخل رشته SQL قرار دهید، از متغیرهای Bind استفاده کنید:

✅ روش امن:

				
					v_sql := 'SELECT * FROM employees WHERE employee_id = :id';
EXECUTE IMMEDIATE v_sql USING v_emp_id;

				
			

 

❌ روش ناامن:

				
					v_sql := 'SELECT * FROM employees WHERE employee_id = ' || v_emp_id;

				
			

🔹 ۲. اعتبارسنجی ورودی‌ها با پکیج DBMS_ASSERT

این تابع جلوی ورود داده‌های مخرب را می‌گیرد:

				
					v_table := DBMS_ASSERT.SIMPLE_SQL_NAME(v_user_input);

				
			

⚙️ چگونه Dynamic SQL بهینه بنویسیم؟

نکته توضیح
استفاده از Bind Variables برای جلوگیری از plan cache pollution
EXECUTE IMMEDIATE برای دستورات ساده سریع‌تر و کم‌هزینه‌تر
DBMS_SQL برای عملیات پیچیده انعطاف‌پذیرتر ولی نیازمند کدنویسی بیشتر
مدیریت خطا با EXCEPTION برای افزایش پایداری برنامه

🧪 مثال واقعی: اجرای گزارش با شرط متغیر

				
					DECLARE
  v_sql VARCHAR2(1000);
  v_dept_id NUMBER := 50;
BEGIN
  v_sql := 'SELECT * FROM employees WHERE department_id = :dept';
  EXECUTE IMMEDIATE v_sql USING v_dept_id;
END;

				
			

🛡 رعایت موارد ایمنی در Dynamic SQL

✅ از USING برای Bind Variable استفاده کن
✅ با DBMS_ASSERT ورودی‌ها را پاک‌سازی کن
✅ هیچ متغیر کاربر را مستقیم در SQL نگذار
✅ نقش‌های کاربری را محدود نگه دار
✅ خطاها را با EXCEPTION مدیریت کن

مقایسه EXECUTE IMMEDIATE و DBMS_SQL

مورد استفاده ابزار مناسب
دستور ساده، سریع، تک دستور EXECUTE IMMEDIATE
ساختار پیچیده یا تعداد ستون نامشخص DBMS_SQL

🚀 مثال‌های کاربردی از Dynamic SQL

🔹 ۱. ساخت جدول با نام متغیر:

				
					v_table := 'log_' || TO_CHAR(SYSDATE, 'YYYYMMDD');
EXECUTE IMMEDIATE 'CREATE TABLE ' || 
DBMS_ASSERT.SIMPLE_SQL_NAME(v_table)|| ' (id NUMBER)';

				
			

🔹 ۲. حذف ستون به صورت داینامیک:

				
					EXECUTE IMMEDIATE 'ALTER TABLE my_table DROP COLUMN ' ||
DBMS_ASSERT.SIMPLE_SQL_NAME(v_col);

				
			

سوالات متداول درباره Dynamic SQL در Oracle

اگر بدون اعتبارسنجی ورودی یا بدون Bind Variable استفاده شود، بله؛ چون به شدت در برابر SQL Injection آسیب‌پذیر است.

وقتی تعداد ستون‌ها یا نام آن‌ها مشخص نیست، یا نیاز به کنترل دقیق‌تری روی نتایج داریم.

در صورت استفاده نادرست از Bind Variable، بله. چون برنامه اجرای SQL (Execution Plan) قابل اشتراک‌گذاری نخواهد بود.

استفاده از DBMS_ASSERT.SIMPLE_SQL_NAME برای تأیید نام جدول یا ستون و جلوگیری از تزریق کد مخرب.

🧠 جمع‌بندی نهایی

نوشتن Dynamic SQL در Oracle اگر درست انجام شود، بسیار قدرتمند است؛ اما در صورت غفلت، می‌تواند به نقطه ضعف بزرگی تبدیل شود. پس:

  • همیشه از Bind Variable استفاده کن
  • ورودی‌ها را اعتبارسنجی کن
  • برای دستورات ساده از EXECUTE IMMEDIATE استفاده کن
  • برای عملیات پیچیده‌تر سراغ DBMS_SQL برو

📢 نظر شما چیست؟ اگر شما هم اطلاعات و تجربه خوبی در Dynamic SQL در Oracle دارید خوشحال میشم در بخش نظرات، تجربه های ارزشمندتان را با ما به اشتراک بگذارید! 🚀

میثم راد

من یه برنامه نویسم که حسابی با دیتابیس اوراکل رفیقم! از اونایی ام که تا چیزی رو کامل نفهمم،ول کن نیستم، یادگرفتن برام مثل بازیه، و نوشتن اینجا کمک می کنه تا چیزایی که یاد گرفتم رو با بقیه به شریک بشم، با هم پیشرفت کنیم.

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

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