
برای نوشتن 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 دارید خوشحال میشم در بخش نظرات، تجربه های ارزشمندتان را با ما به اشتراک بگذارید! 🚀
دیدگاهتان را بنویسید