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

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

راهنمای کامل رفع خطای «ORA‑۰۱۸۴۳: Not a Valid Month» در Oracle

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

در این مقاله آموزش Oracle در بخش خطای های اوراکلی، کامل خطای تاریخ ها در دیتابیس را مورد بررسی قرار می دهیم. 

اگر با Oracle Database کار کرده باشی، تقریباً محاله حداقل یک‌بار با خطای زیر روبه‌رو نشده باشی:

				
					ORA-00936: missing expression
				
			

خطایی که معمولاً وسط کار، آن هم دقیقاً زمانی که فکر می‌کنی کوئری‌ات بی‌نقص است، ظاهر می‌شود!

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

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

خطای ORA‑۰۱۸۴۳ در اوراکل چیست و چرا اتفاق می‌افتد؟

وقتی Oracle می‌خواهد یک رشته را به تاریخ تبدیل کند (مثلاً با TO_DATE یا در مقایسه تاریخ)، نیاز دارد بداند:

  • روز کجاست
  • ماه کجاست
  • سال کجاست

اگر رشته‌ای که وارد کرده‌ای با فرمت مورد انتظار مطابقت نداشته باشد، Oracle نمی‌تواند تشخیص دهد ماه چیست، و در نتیجه پیام زیر را برمی‌گرداند:

				
					ORA-01843: Not a Valid Month

				
			

یعنی: «ماه وارد شده معتبر نیست.»

در واقع Oracle می‌گوید:

تو گفتی این مقدار تاریخ است، اما من نمی‌فهمم ماهش کجاست یا چه شکلی است!

رایج‌ترین دلیل خطا: فرمت اشتباه در TO_DATE

بیش از ۸۰٪ مواقع مشکل از این است که فرمت داده با فرمت توصیف‌شده در TO_DATE فرق دارد.

مثال خطا:

				
					SELECT TO_DATE('2024-12-05', 'DD-MM-YYYY') FROM dual;

				
			

اینجا مقدار '۲۰۲۴-۱۲-۰۵' به شکل YYYY-MM-DD است

اما تو به Oracle می‌گویی 'DD-MM-YYYY'.

روش درست:

				
					SELECT TO_DATE('2024-12-05', 'YYYY-MM-DD') FROM dual;

				
			

یا اگر فرمت ورودی DD-MM-YYYY است:

				
					SELECT TO_DATE('05-12-2024', 'DD-MM-YYYY') FROM dual;

				
			

نقش NLS_DATE_FORMAT در ایجاد خطا

گاهی تو فرمت درست می‌نویسی اما باز هم خطا می‌گیری.

مشکل از جای دیگری است:

NLS_DATE_FORMAT سشن شما با فرمت ورودی سازگار نیست.

مثلاً اگر NLS روی DD-MON-YYYY باشد، Oracle انتظار دارد ماه به صورت سه حرف انگلیسی باشد، مثل:

  • JAN
  • FEB
  • MAR

حالا اگر تو بنویسی:

				
					SELECT * FROM users WHERE created_at = '2024-12-05';

				
			

Oracle تلاش می‌کند '۲۰۲۴-۱۲-۰۵' را مطابق DD-MON-YYYY بخواند و چون “۱۲” ماه معتبر نیست → خطا می‌دهد.

راه‌حل استاندارد:

				
					SELECT * FROM users 
WHERE created_at = TO_DATE('2024-12-05', 'YYYY-MM-DD');
				
			

یا تنظیم سشن:

				
					ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD';

				
			

مثال‌های واقعی از (سناریوهای کاربردی)

۱. خطا هنگام Import کردن CSV

فرض کن ستون‌های تاریخ در CSV این‌طور هستند:

				
					۰۵/۱۲/۲۰۲۴

				
			

ولی در برنامه‌ات این‌طور تبدیل می‌کنی:

				
					TO_DATE(date_column, 'YYYY/MM/DD')

				
			

Oracle سردرگم می‌شود و خطا می‌دهد.

راه‌حل

				
					TO_DATE(date_column, 'DD/MM/YYYY')

				
			

۲. داده‌های غیر استاندارد در جدول

گاهی داده‌ها از قبل خراب وارد شده‌اند:

				
					۵ day 1402
khordad 1401
۱۳۹۹/۱۳/۱۰   ← mah 13 aslan vojood nadarad

				
			

Oracle در تبدیل این مقادیر به DATE خطا می‌دهد.

اعتبارسنجی با REGEXP:

				
					SELECT *
FROM table1
WHERE NOT REGEXP_LIKE(date_str, '^\d{4}/(0[1-9]|1[0-2])/(0[1-9]|[12]\d|3[01])$');

				
			

۳. ماه‌های فارسی بدون تنظیم NLS

اگر ماه را فارسی می‌نویسی:

				
					TO_DATE('05-نیدرورف-۱۴۰۲', 'DD-MON-YYYY')

				
			

این اشتباه است، چون MON فقط ماه انگلیسی می‌پذیرد.

روش درست:

				
					TO_DATE('05-نیدرورف-۱۴۰۲', 'DD-MON-YYYY', 'NLS_DATE_LANGUAGE=FARSI');

				
			

روش‌های تضمینی برای جلوگیری از خطای ORA‑۰۱۸۴۳

این نکات را همیشه رعایت کن:

  • همیشه هنگام تبدیل رشته به تاریخ فرمت دقیق بده.
  • روی تبدیل خودبه‌خودی Oracle حساب نکن.
  • هیچ‌وقت تاریخ‌ها را بدون TO_DATE مقایسه نکن.
  • برای نمایش تاریخ از TO_CHAR استفاده کن.
  • فرمت‌های استاندارد مثل YYYY-MM-DD را به‌کار ببر.
  • اگر مقدار تاریخ از سمت کاربر می‌آید، همیشه آن را اعتبارسنجی کن.

سوالات متداول درباره رفع خطای ORA‑۰۱۸۴۳ در اوراکل

علت اصلی این خطا عدم تطابق بین فرمت تاریخ ورودی و فرمت مورد انتظار Oracle است.

وقتی رشته‌ای مثل “۲۰۲۴-۱۲-۰۵” را وارد می‌کنی و Oracle انتظار فرمت دیگری مثل “DD-MON-YYYY” یا “DD-MM-YYYY” را دارد، نمی‌تواند تشخیص دهد کدام بخش ماه است و خطا می‌دهد.

برای جلوگیری از این خطا هنگام Insert یا Update همیشه این اصول را رعایت کن:

  • مقدار رشته را با فرمت دقیق TO_DATE تبدیل کن
  • فرمت تاریخ در ورودی، فایل و برنامه را یکسان نگه دار
  • روی تبدیل خودکار Oracle حساب باز نکن

مثال استاندارد:

INSERT INTO users (birthday) VALUES (TO_DATE(‘1990-04-10’, ‘YYYY-MM-DD’));

اگر این کار را نکنی، Oracle نمی‌داند ماه کجاست و خطا می‌دهد.

اگر بدون TO_DATE تاریخ را مقایسه یا مقدار رشته تاریخ را مستقیماً استفاده کنی و خطا بگیری، احتمالاً NLS_DATE_FORMAT مشکل ایجاد کرده.

می‌توانی با این دستور از فرمت فعلی مطلع شوی:

SELECT value FROM nls_session_parameters WHERE parameter = ‘NLS_DATE_FORMAT’;

اگر فرمت فعلی با مقدار ورودی نمی‌خواند، باید یا فرمت را اصلاح کنی یا از TO_DATE با فرمت دقیق استفاده کنی.

بله، اگر NLS_DATE_LANGUAGE روی Farsi تنظیم نشده باشد، Oracle ماه فارسی را نمی‌شناسد و فوراً خطای ORA‑۰۱۸۴۳ می‌دهد.

برای رفع مشکل باید زبان تاریخ را مشخص کنی:

TO_DATE(’05-فروردین-۱۴۰۲′, ‘DD-MON-YYYY’, ‘NLS_DATE_LANGUAGE=FARSI’);

یا پیش از اجرای کوئری این مورد را تنظیم کن:

ALTER SESSION SET NLS_DATE_LANGUAGE = ‘FARSI’;

جمع‌بندی

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

در ۹۹٪ مواقع دلیلش یکی از این‌هاست:

  1. فرمت اشتباه در TO_DATE
  2. ناسازگاری NLS_DATE_FORMAT
  3. داده اشتباه یا ماه نامعتبر
  4. استفاده از ماه فارسی بدون تنظیم NLS

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

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

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

میثم راد

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

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

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