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

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

رفع خطای ORA‑۰۶۵۰۲: PL/SQL Numeric or Value Error

خطای ORA‑۰۶۵۰۲: PL/SQL Numeric or Value Error یکی از پرتکرارترین و آزاردهنده‌ترین خطاهای Oracle است. معمولاً زمانی ظاهر می‌شود که در اجرای PL/SQL، مقدار داده‌ای با نوع داده یا ظرفیت متغیر هم‌خوانی ندارد.

این خطا کامپایل را خراب نمی‌کند، اما در زمان اجرا برنامه را متوقف می‌کند و معمولاً باعث سردرگمی برنامه‌نویس می‌شود.

اگر شما هم هنگام کار با اوراکل با خطاهایی مثل overflow, character string buffer too small یا invalid number روبه‌رو شده‌اید، این مقاله آموزش Oracle در بخش خطای های اوراکلی،دقیقاً برای شماست.

در این مقاله یاد می‌گیرید:

  • چرا ORA‑۰۶۵۰۲ اتفاق می‌افتد
  • رایج‌ترین علت‌های Overflow و mismatch نوع داده
  • مثال‌های واقعی و کاربردی
  • روش‌های جلوگیری از وقوع این خطا
  • الگوهای درست طراحی در PL/SQL

اگر هنگام کار با تاریخ‌ها در Oracle به خطای ORA‑۰۱۸۴۳: Not a Valid Month برخورده‌ای، کاملاً طبیعی است؛ این خطا یکی از شایع‌ترین خطاهای پایگاه‌داده Oracle است.

پیشنهاد می کنم این مقاله زیر رو حتما مطالعه کنی.

در این مقاله شما می خوانید

خطای ORA‑۰۶۵۰۲ چیست و دقیقاً چه می‌گوید؟

وقتی Oracle خطای ORA‑۰۶۵۰۲ را می‌دهد، یعنی یک مشکل منطقی در مقدار داده رخ داده است، نه در ساختار یا سینتکس.

به بیان ساده:

«داده‌ای که وارد یک متغیر یا ستون شده، با نوع دادهٔ مقصد سازگار نیست.»

این خطا می‌تواند ناشی از طول زیاد رشته، مقدار عددی خارج از محدوده، تبدیل نامعتبر (conversion error) یا مشکلات NLS باشد.

علت‌های اصلی خطای ORA‑۰۶۵۰۲

۱) طول رشته بیشتر از اندازه متغیر (Character String Buffer Too Small)

یکی از مهم‌ترین علت‌ها همین است. اگر متغیر یا ستون ظرفیت محدودی داشته باشد، Oracle اجازه ورود مقدار بزرگ‌تر را نمی‌دهد.

مثال اشتباه

				
					declare
  v_name varchar2(5);
begin
  v_name := 'ORACLEDB';
end;
				
			

نتیجه:

ORA‑۰۶۵۰۲: character string buffer too small

راه‌حل

  • افزایش طول
  • بریدن مقدار با substr
  • استفاده از %TYPE برای هم‌اندازه ماندن با ستون‌ها

نسخه صحیح

				
					declare
  v_name employees.last_name%type;
begin
  v_name := 'ORACLEDB';
end;
				
			

۲) Overflow در انواع عددی (NUMBER Precision/Scale Error)

نوع داده NUMBER محدودیت دارد. مثلاً:

NUMBER(5,2)

حداکثر مقدار ≈ ۹۹۹.۹۹

مثال اشتباه

				
					declare
  v_amount number(5,2);
begin
  v_amount := 12345.67; -- kheili bozorg tar az damane
end;
				
			

راه‌حل

  • افزایش precision
  • گرد کردن
  • استفاده از NUMBER بدون محدودیت (در صورت ضرورت)

نسخه صحیح

				
					declare
  v_amount number(9,2);
begin
  v_amount := 12345.67;
end;
				
			

۳) تبدیل نادرست رشته به عدد (Invalid Number)

گاهی Oracle تلاش می‌کند یک رشته را ضمنی به NUMBER تبدیل کند و شکست می‌خورد.

مثال اشتباه

				
					declare
  v_num number;
begin
  v_num := '12A';
end;
				
			

نسخه امن (در ۱۲c به بالا)

				
					v_num := to_number(v_txt default null on conversion error);

				
			

یا با REGEXP:

				
					if regexp_like(v_txt, '^\d+(\.\d+)?$') then
    v_num := to_number(v_txt);
end if;

				
			

۴) انتخاب مقدار بزرگ‌تر از اندازه متغیر در SELECT INTO

اگر مقدار داخل جدول بزرگ‌تر از اندازه متغیر باشد، احتمالاً این خطا را می‌بینید.

نسخه اشتباه

				
					declare
  v_email varchar2(10);
begin
  select email into v_email
  from employees
  where employee_id = 100;
end;
				
			

نسخه صحیح

				
					declare
  v_email employees.email%type;
begin
  select email into v_email
  from employees
  where employee_id = 100;
end;
				
			

۵) مشکلات CHAR/NCHAR و فاصله‌های اضافه (Padding Issues)

استفاده از نوع CHAR به دلیل پر شدن خودکار با space می‌تواند باعث خطاهای مقایسه یا طول نامعتبر شود. استفاده از VARCHAR2 اغلب ساده‌تر و ایمن‌تر است.

چطور بفهمیم خطا دقیقاً کجاست؟ (Debugging)

استفاده از Backtrace

این روش دقیقاً خطی از کد که باعث ORA‑۰۶۵۰۲ شده را نشان می‌دهد.

				
					exception
  when others then
    dbms_output.put_line(sqlerrm);
    dbms_output.put_line(dbms_utility.format_error_backtrace);
    raise;

				
			

بهترین روش‌های جلوگیری از خطای ORA‑۰۶۵۰۲

  • همیشه از %TYPE و %ROWTYPE استفاده کنید
  • تبدیل رشته به عدد را ایمن انجام دهید
  • محدوده‌های NUMBER را آگاهانه تعریف کنید
  • قبل از انتساب، طول رشته را بررسی یا کنترل کنید
  • در تبدیل‌ها تنظیمات NLS را مشخص کنید
  • اگر امکان دارد، از CLOB برای متن‌های بزرگ استفاده کنید

سناریوی واقعی: ورودی کاربر → تبدیل → ذخیره

				
					create or replace procedure save_price(p_price_txt varchar2) is
  v_price number(12,2);
begin
  v_price := to_number(p_price_txt default null on conversion error);

  if v_price is null then
    raise_application_error(-20001, 'list etebari nadarad!!');
  end if;

  insert into prices_log(price_value, created_at)
  values (v_price, systimestamp);
end;
				
			

چک‌لیست سریع تشخیص خطای ORA‑۰۶۵۰۲

  • آیا طول رشته زیاد است؟
  • آیا مقدار عددی از محدوده خارج شده؟
  • آیا تبدیل ضمنی انجام شده؟
  • آیا متغیر SELECT INTO ظرفیت کافی دارد؟
  • آیا فرمت تاریخ/عدد با NLS سازگار است؟

سوالات متداول درباره رفع خطای ORA‑۰۶۵۰۲ در اوراکل

خطای ORA‑۰۶۵۰۲ زمانی رخ می‌دهد که مقدار یک متغیر یا فیلد با نوع داده‌ای که برای آن تعریف شده سازگار نباشد. مهم‌ترین علت‌ها شامل طول بیش از حد رشته، overflow عددی در NUMBER(p,s)، تبدیل رشته نامعتبر به عدد یا مشکل در SELECT INTO است.

سریع‌ترین روش تشخیص علت واقعی این است که در بخش Exception از دستور زیر استفاده شود:

dbms_output.put_line(dbms_utility.format_error_backtrace);

این دستور شمارهٔ خط دقیق بروز خطا را نشان می‌دهد و معمولاً در کمتر از چند ثانیه مشخص می‌شود که کدام متغیر یا نوع داده باعث مشکل شده است.

رایج‌ترین اشتباه این است که کاربر مقدار '۱۲a' یا رشتهٔ مشابه را به NUMBER تبدیل می‌کند و برنامه با ORA‑۰۶۵۰۲ می‌ریزد. بهترین راه جلوگیری این است که از تبدیل ایمن در Oracle 12c به بالا استفاده کنید:

v_num := to_number(p_txt default null on conversion error);

اگر ورودی نامعتبر باشد، به جای خطا مقدار NULL برمی‌گردد و برنامه متوقف نمی‌شود.

این روش بهترین نرخ موفقیت را برای جلوگیری از خطاهای conversion دارد و در سیستم‌های Production نیز توصیه می‌شود.

اگر مقدار ستون در جدول طول بیشتری از متغیر مقصد داشته باشد، SELECT INTO باعث ORA‑۰۶۵۰۲ می‌شود.

برای مثال:

v_email varchar2(10);
select email into v_email from employees where employee_id = 100;

اگر مقدار email در جدول مثلاً ۲۰ کاراکتر باشد، خطا تولید می‌شود.

راه‌حل:

به‌جای تعیین دستی اندازه:

v_email employees.email%type;

این روش همیشه با اندازه واقعی ستون هماهنگ است و احتمال خطا را نزدیک به صفر می‌کند. این راهکار یکی از بهترین ترفندهای حرفه‌ای PL/SQL محسوب می‌شود.

برای تشخیص اینکه خطای ORA‑۰۶۵۰۲ از کدام متغیر ناشی شده، می‌توان قبل از هر انتساب، مقدار و طول داده را چاپ کرد:

dbms_output.put_line(‘LEN=’ || length(v_txt) || ‘, VAL=’ || v_txt);
dbms_output.put_line(‘NUM=’ || to_char(v_num, ‘TM’));

اگر مقدار عددی از محدوده NUMBER(p,s) خارج باشد، یا اگر رشته طول زیادی داشته باشد، در لحظه معلوم می‌شود مشکل دقیقاً چیست.

نشانه‌های رایج Overflow:

  • مقدار ۱۲۳۴۵ برای NUMBER(4)
  • مقدار ۱۰.۵۵ برای NUMBER(4,1)
  • مقدار رشته ۲۰ کاراکتر برای VARCHAR2(10)

این روش ساده‌ترین و سریع‌ترین راه برای تشخیص منشأ ORA‑۰۶۵۰۲ در پروژه‌های بزرگ است.

 

جمع‌بندی

خطای ORA‑۰۶۵۰۲ در Oracle یکی از خطاهای پرتکرار اما قابل‌پیشگیری است. با استفاده از اصول صحیح طراحی متغیرها، تبدیل امن داده‌ها، تعیین درست precision/scale و تحلیل خطا با Backtrace، می‌توان به‌طور کامل از این مشکل جلوگیری کرد.

سؤالی درباره این مقاله داری؟

اگر نکته‌ای در این مقاله برات مبهم بود یا خواستی بیشتر بدونی، همین حالا برام بنویس تا دقیق و صمیمی پاسخت رو بدم — مثل یه گفت‌وگوی واقعی 💬

برو به صفحه پرسش و پاسخ

میثم راد

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

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

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