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

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

خطای ORA‑۰۲۲۹۱ در Oracle — چرا می‌افتد و چطور باید درستش کنیم؟

حتماً تا حالا در دنیای Oracle با ارور معروفی روبه‌رو شدی که روی صفحه نوشت:

				
					ORA-02291: integrity constraint violated - parent key not found

				
			

اگر دیدی این پیغام ظاهر شد، یعنی داری رکوردی را وارد جدول فرزند می‌کنی که والدش هنوز در پایگاه داده وجود ندارد. ساده بگوییم:

داری فرزند را قبل از پدرش می‌سازی.

در ادامه آموزش Oracle در بخش آموزش خطاهای اوراکلی همه چیز را توضیح می‌دهم، با مثال‌های واقعی، تا همیشه بتوانی بفهمی مشکل از کجاست و چطور از تکرارش جلوگیری کنی.

اگر با پایگاه‌داده‌ی اوراکل (Oracle Database) کار کرده باشی، احتمالاً با خطای معروف زیر برخورد کرده‌ای:
				
					ORA-01722: invalid number
				
			

این ارور یکی از متداول‌ترین خطاهای SQL در محیط Oracle است، و تقریباً همه‌ی توسعه‌دهنده‌ها و DBAها حداقل یک‌بار با آن دردسر داشته‌اند.

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

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

🔍 معنای واقعی خطا ORA‑۰۲۲۹۱: نقض تمامیت ارجاعی (Referential Integrity)

در Oracle، وقتی دو جدول با رابطه‌ی یک به چند طراحی می‌شوند، جدول والد (مثلاً customers) معمولاً کلید اصلی (Primary Key) دارد.

جدول فرزند (مثل orders)، دارای کلید خارجی (Foreign Key) است که باید به همان کلید والد اشاره کند.

اگر رکورد فرزند به والد اشاره کند ولی آن والد در جدول وجود نداشته باشد، Oracle فوراً جلوی این کار را می‌گیرد تا سازگاری داده‌ها از بین نرود.

نتیجه؟ همون خطای ORA‑۰۲۲۹۱.

فرض کن این دو جدول رو داری:

جدول والد: مشتریان

				
					CREATE TABLE customers (
    customer_id NUMBER PRIMARY KEY,
    name VARCHAR2(100)
);

				
			

جدول فرزند: سفارش‌ها

				
					CREATE TABLE orders (
    order_id NUMBER PRIMARY KEY,
    customer_id NUMBER,
    order_date DATE,
    CONSTRAINT fk_orders_customers 
        FOREIGN KEY (customer_id)
        REFERENCES customers(customer_id)
);

				
			

حالا اگر این دستور رو اجرا کنی:

				
					INSERT INTO orders (order_id, customer_id, order_date)
VALUES (1, 999, SYSDATE);

				
			

اما هیچ مشتری‌ای با customer_id = 999 در جدول customers وجود نداشته باشه، اوراکل پیغام می‌دهد:

				
					ORA-02291: integrity constraint (HR.FK_ORDERS_CUSTOMERS) violated - parent key not found

				
			

✅ راه‌حل‌های قطعی برای رفع خطا ORA‑۰۲۲۹۱

۱. ابتدا رکورد والد را درج کن

قبل از اینکه سفارش را ثبت کنی، باید مشتری را در جدول والد بسازی:

				
					INSERT INTO customers (customer_id, name)
VALUES (999, 'meisam raad');

INSERT INTO orders (order_id, customer_id, order_date)
VALUES (1, 999, SYSDATE);

				
			

الان همه‌چیز درست کار می‌کند چون والد وجود دارد.

۲. اگر ارتباط منطقی نیست → Constraint را حذف یا اصلاح کن

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

در این حالت می‌توانی constraint را حذف کنی:

				
					ALTER TABLE orders DROP CONSTRAINT fk_orders_customers;

				
			

اما با احتیاط استفاده کن. حذف constraint مثل برداشتن کمربند ایمنی است — راحت‌تر می‌روی، ولی خطر بیشتری دارد.

۳. استفاده از تراکنش‌ها (Transactions)

در فرآیندهای داده‌ای پیچیده، رکوردهای والد و فرزند را در یک تراکنش بگذار تا در صورت خطا، کل تراکنش rollback شود و ناسازگاری پیش نیاید:

				
					BEGIN
    INSERT INTO customers VALUES (1000, 'meisam raad');
    INSERT INTO orders VALUES (10, 1000, SYSDATE);
COMMIT;
END;

				
			

۴. استفاده از گزینه‌ی DEFERRABLE برای کنترل زمان بررسی Constraint

اگر لازم داری رکورد فرزند قبل از والد درج شود و بررسی در پایان تراکنش انجام شود:

				
					CREATE TABLE orders (
    order_id NUMBER PRIMARY KEY,
    customer_id NUMBER,
    CONSTRAINT fk_orders_customers 
        FOREIGN KEY (customer_id)
        REFERENCES customers(customer_id)
        DEFERRABLE INITIALLY DEFERRED
);

				
			

این روش مخصوص متخصصان Oracle است و در پروژه‌های Enterprise یا ETL بسیار مفید می‌شود.

💡 نکات پیشرفته برای پیدا کردن Constraint‌ معیوب

برای پیدا کردن جزئیات constraint‌ مشکل‌دار، این دستور را اجرا کن:

				
					SELECT constraint_name, table_name, column_name
FROM user_cons_columns
WHERE constraint_name = 'FK_ORDERS_CUSTOMERS';

				
			

با این کوئری می‌فهمی constraint دقیقاً روی کدام جدول و ستون فعال است.

🚀 پیشگیری از وقوع ORA‑۰۲۲۹۱ در پروژه‌های بزرگ (ETL / Data Migration)

در پروژه‌های ETL معمولاً داده‌ها از فایل یا سیستم دیگری بارگذاری می‌شوند، و ترتیب load داده بسیار مهم است.

برای جلوگیری از خطا:

  1. ابتدا جدول والد‌ها را load کن.
  2. بعد جدول فرزندها را.
  3. یا با Staging Table رکوردها را موقت نگه دار و سپس با دستور MERGE داده‌ها را ایمن منتقل کن:
				
					MERGE INTO orders o
USING customers c
ON (o.customer_id = c.customer_id)
WHEN MATCHED THEN
   INSERT (order_id, customer_id, order_date)
   VALUES (o.order_id, o.customer_id, o.order_date);

				
			

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

خطای ORA‑۰۲۲۹۱ یعنی شما در حال درج داده‌ای در جدول فرزند هستید که والدش هنوز در جدول مرجع وجود ندارد.

به زبان ساده، Oracle جلوی ورود رکوردی را می‌گیرد که ارتباطش از طریق Foreign Key با رکورد والد برقرار نشده.

این خطا معمولاً با پیام “parent key not found” نشان داده می‌شود و نشانه‌ی نقض تمامیت ارجاعی (Referential Integrity) در پایگاه داده است.

وقتی ترتیب درج داده‌ها اشتباه باشد — یعنی ابتدا رکورد فرزند و بعد رکورد والد را وارد کنید — Oracle نمی‌تواند ارتباط بین کلید خارجی و کلید اصلی را تأیید کند و ارور ORA‑۰۲۲۹۱ می‌دهد.

این خطا در فرآیندهای ETL، Integration یا Migration داده‌ها بسیار رایج است، چون ترتیب بارگذاری جداول رعایت نمی‌شود.

ساده‌ترین راه رفع این خطا درج رکورد والد قبل از فرزند است.

اگر فرزند باید قبل از والد اضافه شود، می‌توان constraint را به حالت DEFERRABLE INITIALLY DEFERRED تعریف کرد تا بررسی صحت ارتباط در زمان commit انجام شود، نه در لحظه‌ی INSERT.

همچنین بررسی این نکته که foreign key به جدول درست اشاره کند بسیار حیاتی است.

این دو خطا شباهت ظاهری دارند اما ماهیتشان متفاوت است:

  • ORA‑۰۲۲۹۱: هنگام INSERT رخ می‌دهد چون والد وجود ندارد.
  • ORA‑۰۲۲۹۲: هنگام DELETE رخ می‌دهد چون والد هنوز فرزند وابسته دارد.

به عبارت دیگر، یکی مربوط به ایجاد رابطه‌ست، دیگری به حذف آن.

عنوان توضیح
کد خطا ORA‑۰۲۲۹۱
علت اصلی درج رکورد فرزند بدون وجود رکورد والد در جدول مرجع (Foreign Key).
Constraint نقض‌شده تمامیت ارجاعی (Referential Integrity Constraint).
روش رفع خطا درج رکورد والد قبل از فرزند، استفاده از تراکنش یا گزینه DEFERRABLE.
نکته کلیدی اول والد را بساز، بعد فرزند را — درست مثل رابطه منطقی داده‌ها در Oracle.

📥 اگر سوالی داری در مورد رفع خطای ORA‑۰۲۲۹۱ در اوراکل داری، در بخش کامنت‌ها بپرس.

میثم راد

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

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

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