سؤال

لدي جدول (أ) مفتاحه الأساسي هو إما مفتاح خارجي للجدول (ب) أو الجدول (ج).

create table A (
  akey number, 
  txt varchar2(10)
);

create table B (
  bkey number, 
  txt varchar2(10)
);

create table C (
  ckey number, 
  txt varchar2(10)
);

ما أريده هو شيء مثل:

alter table A add constraint BorCkey foreign key (akey) references B(bkey)` or C(ckey);

هل هذا ممكن؟

هل كانت مفيدة؟

المحلول

لا ، هذا النوع من الأشياء غير ممكن في أوراكل.

خياراتك بشكل عام

  • قم بإنشاء عمودين مختلفين (BKEY و CKEY) في A BKEY يشير B.BKEY و CKEY C.CKEY وإنشاء قيد يضمن أن واحدة فقط هي غير خالية في أي وقت.
  • قم بإنشاء نوع من الكيان "المشترك B&C" الذي يحتوي B&C على مفاتيح أجنبية وجعل المفتاح الأجنبي في إشارة إلى مفتاح هذا الكيان المزيج.

إذا كنت تريد قيودًا يضمن أن أحد عمودين هو بالضبط لا هو فارغ ، فهو ليس فارغًا لأي صف

create table one_key( 
  col1 number, 
  col2 number, 
  check( nvl2(col1,1,0) + nvl2(col2,1,0) = 1 ) 
)

نصائح أخرى

القيد الرئيسي الخارجي هو طاولة أجنبية واحدة.
هذا يعني أنك تحتاج إلى استخدام بيانين جدولين في هذا الموقف لإعداد مفاتيح أجنبية للإشارة إلى الجدولين. لا توجد فرصة لتحديد أو في العلاقة - القيمة في A.akey يجب أن توجد في كليهما B.bkey و C.ckey في نفس الوقت. على سبيل المثال ، إذا B.bkey له قيمة فارغة ، ولكن C.ckey لا - إذن A.akey لا يمكن أن يكون لها قيمة فارغة. المفاتيح الأجنبية قابلة للتأجيل في Oracle ، لكن السلوك الموصوف هو ما ستواجهه إذا تم تمكين كل من المفاتيح الأجنبية في نفس الوقت - فلن تتمكن من تمكين القيد إذا لم ترضى جميع القيم العلاقة.

تحتاج إلى مراجعة احتياجاتك لكيفية تبسيط العلاقة بحيث لا تحتاج إلى جدولين لجعل هذا العمل.

يبدو أن لديك بعض أشكال العلاقة بين النوع الفرعي/superType. مثال نموذجي هو "شخص" قد يكون إما "عميل" أو "مورد".

قد يكون لديك ، في جدول الشخص المفتاح الفريد لـ person_id بالإضافة إلى سمة من الشخصيات ("Cust" أو "Supp"). إذا قمت بإنشاء المفتاح الأساسي على person_id ، يمكنك الإشارة إلى ذلك في جداول النوع الفرعي (المورد/العميل).

ثم تضيف قيودًا فريدة على الشخص _id للتأكد من أن أي قيمة من الشخص يجب أن تكون إما عميل أو مورد ولكن ليس كلاهما ، والتحقق من القيود على جداول النوع الفرعي بحيث يتم تمثيل نوع واحد فقط في الجدول.

create table person
  (person_id     number,
   person_type   varchar2(4),
   name          varchar2(10),
    constraint person_pk primary key (person_id, person_type),
    constraint person_id_uk unique (person_id));

create table supplier
  (supplier_id   number,
   supplier_type varchar2(4),
   blah          varchar2(10),
  constraint supplier_pk primary key (supplier_id, supplier_type),
  constraint supp_pers_fk foreign key  (supplier_id, supplier_type)
    REFERENCES person (person_id, person_type)
  )
/
alter table supplier add constraint supp_type_ck check (supplier_type = 'SUPP');

إنها ليست جميلة ولكن الأنواع/الأنواع الفرعية هي مفهوم كائن أكثر من مفهوم علائقي.

حلي مستوحى من جوستين:

CREATE OR REPLACE TRIGGER abc
  BEFORE INSERT OR UPDATE ON a
  FOR EACH ROW
  DECLARE
  v_testB NUMBER:= 0;
  v_testC NUMBER:= 0;
  BEGIN
    SELECT
      COUNT(bkey)
    INTO
      v_testB
    FROM
      b
    WHERE
      bkey = :new.aKey;
    SELECT
      COUNT(ckey)
    INTO
      v_testC
    FROM
      c
    WHERE
      ckey = :new.aKey;
    IF ((v_testB + v_testC) <> 1) THEN
      RAISE_APPLICATION_ERROR(-20002,'Foreign key to B or C missing.');
    END IF;
  END;
/
SHOW ERRORS TRIGGER abc

قم بإنشاء طريقة عرض ملموس مفادها أن جداول النقابات B&C ، وقم بتوجيه قيود FK الخاصة بك إلى العرض

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top