it-swarm.asia

كيف أقوم بتعيين علاقة IS-A في قاعدة بيانات؟

خذ بعين الاعتبار ما يلي:

entity User
{
    autoincrement uid;
    string(20) name;
    int privilegeLevel;
}

entity DirectLoginUser
{
    inherits User;
    string(20) username;
    string(16) passwordHash;
}

entity OpenIdUser
{
    inherits User;
    //Whatever attributes OpenID needs... I don't know; this is hypothetical
}

تعرض الأنواع المختلفة من المستخدمين (مستخدمي تسجيل الدخول المباشر ومستخدمي OpenID) علاقة IS-A ؛ أي أن كلا النوعين من المستخدمين هم من المستخدمين. الآن ، هناك عدة طرق يمكن تمثيلها في نظام إدارة قواعد البيانات (RDBMS):

طريق واحد

CREATE TABLE Users
(
    uid INTEGER AUTO_INCREMENT NOT NULL,
    name VARCHAR(20) NOT NULL,
    privlegeLevel INTEGER NOT NULL,
    type ENUM("DirectLogin", "OpenID") NOT NULL,
    username VARCHAR(20) NULL,
    passwordHash VARCHAR(20) NULL,
    //OpenID Attributes
    PRIMARY_KEY(uid)
)

الطريقة الثانية

CREATE TABLE Users
(
    uid INTEGER AUTO_INCREMENT NOT NULL,
    name VARCHAR(20) NOT NULL,
    privilegeLevel INTEGER NOT NULL,
    type ENUM("DirectLogin", "OpenID") NOT NULL,
    PRIMARY_KEY(uid)
)

CREATE TABLE DirectLogins
(
    uid INTEGER NOT_NULL,
    username VARCHAR(20) NOT NULL,
    passwordHash VARCHAR(20) NOT NULL,
    PRIMARY_KEY(uid),
    FORIGEN_KEY (uid) REFERENCES Users.uid
)

CREATE TABLE OpenIDLogins
(
    uid INTEGER NOT_NULL,
    // ...
    PRIMARY_KEY(uid),
    FORIGEN_KEY (uid) REFERENCES Users.uid
)

الطريق الثالث

CREATE TABLE DirectLoginUsers
(
    uid INTEGER AUTO_INCREMENT NOT NULL,
    name VARCHAR(20) NOT NULL,
    privlegeLevel INTEGER NOT NULL,
    username VARCHAR(20) NOT NULL,
    passwordHash VARCHAR(20) NOT NULL,
    PRIMARY_KEY(uid)
)

CREATE TABLE OpenIDUsers
(
    uid INTEGER AUTO_INCREMENT NOT NULL,
    name VARCHAR(20) NOT NULL,
    privlegeLevel INTEGER NOT NULL,
    //OpenID Attributes
    PRIMARY_KEY(uid)
)

أنا متأكد تقريبًا أن الطريقة الثالثة هي الطريقة الخاطئة ، لأنه ليس من الممكن القيام بانضمام بسيط ضد المستخدمين في أي مكان آخر في قاعدة البيانات.

مثال عالمي الحقيقي ليس مستخدمًا مع مثال لتسجيلات الدخول المختلفة ؛ أنا مهتم بكيفية صياغة هذه العلاقة في الحالة العامة.

26
Billy ONeal

الطريقة الثانية هي الطريقة الصحيحة.

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

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

على سبيل المثال ، سيبدو MySQL DDL على النحو التالي:

CREATE TABLE Users
(
      uid               INTEGER AUTO_INCREMENT NOT NULL
    , type              ENUM("DirectLogin", "OpenID") NOT NULL
    // ...

    , PRIMARY_KEY(uid)
);

CREATE TABLE DirectLogins
(
      uid               INTEGER NOT_NULL
    , type              ENUM("DirectLogin") NOT NULL
    // ...

    , PRIMARY_KEY(uid)
    , FORIGEN_KEY (uid, type) REFERENCES Users (uid, type)
);

CREATE TABLE OpenIDLogins
(
      uid               INTEGER NOT_NULL
    , type              ENUM("OpenID") NOT NULL
    // ...

    PRIMARY_KEY(uid),
    FORIGEN_KEY (uid, type) REFERENCES Users (uid, type)
);

(على الأنظمة الأساسية الأخرى ، يمكنك استخدام قيد CHECK بدلاً من ENUM.) MySQL يدعم مفاتيح خارجية مركبة ، لذا يجب أن يعمل هذا من أجلك.

الطريقة الأولى صالحة ، على الرغم من أنك تهدر مساحة في هذه الأعمدة القادرة NULL لأن استخدامها يعتمد على نوع المستخدم. الميزة هي أنه إذا اخترت توسيع أنواع أنواع المستخدمين التي تريد تخزينها وأن هذه الأنواع لا تتطلب أعمدة إضافية ، فيمكنك فقط توسيع نطاق ENUM واستخدام نفس الجدول.

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

16
Nick Chammas

سيتم تسميتهم

  1. وراثة جدول واحد
  2. وراثة جدول الصف
  3. وراثة المائدة الخرسانية .

وكلها لها استخداماتها المشروعة وتدعمها بعض المكتبات. عليك أن تعرف ما يناسبك.

إن وجود جداول متعددة سيجعل إدارة البيانات أكثر إلى رمز التطبيق الخاص بك ولكنه سيقلل من المساحة غير المستخدمة.

5
flob