加入收藏 | 设为首页 | 会员中心 | 我要投稿 财气旺网 - 财气网 (https://www.caiqiwang.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

数据库设计 – 如何将IS-A关系映射到数据库?

发布时间:2021-01-09 23:45:26 所属栏目:MsSql教程 来源:网络整理
导读:考虑以下: 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 d

考虑以下:

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,privilegeLevel INTEGER 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,PRIMARY_KEY(uid)
)

CREATE TABLE OpenIDUsers
(
    uid INTEGER AUTO_INCREMENT NOT NULL,//OpenID Attributes
    PRIMARY_KEY(uid)
)

我几乎可以肯定第三种方式是错误的方式,因为不可能对数据库中其他地方的用户进行简单的连接.

我的真实世界示例不是具有不同登录示例的用户;我对如何在一般情况下模拟这种关系感兴趣.

解决方法

方式二是正确的方法.

您的基类获取一个表,然后子类只使用它们引入的其他字段获得自己的表,以及对基表的外键引用.

正如Joel在对此答案的评论中所建议的那样,您可以保证用户将具有直接登录或OpenID登录,但不能同时(也可能两者都没有)通过向每个子类型表添加类型列来锁定到根表.每个子类型表中的type列被限制为具有表示该表类型的单个值.由于此列是外键到根表,因此一次只能有一个子类型行链接到同一根行.

例如,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
    // ...,FORIGEN_KEY (uid,type) REFERENCES Users (uid,type)
);

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

    PRIMARY_KEY(uid),type)
);

(在其他平台上,您将使用CHECK约束而不是ENUM.)MySQL supports复合外键,因此这应该适合您.

第一种方法是有效的,尽管你在那些可以使用NULL的列中浪费空间,因为它们的使用取决于用户的类型.优点是,如果您选择扩展要存储的类型的用户类型,并且这些类型不需要其他列,则只需展开ENUM的域并使用相同的表.

方式三强制任何引用用户检查两个表的查询.这也会阻止您通过外键引用单个用户表.

(编辑:财气旺网 - 财气网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读