Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何设计员工、客户和电话号码表之间的关系?_Sql_Database - Fatal编程技术网

Sql 如何设计员工、客户和电话号码表之间的关系?

Sql 如何设计员工、客户和电话号码表之间的关系?,sql,database,Sql,Database,我有一个带有客户机表的关系数据库,其中包含id、名称和地址,以及许多电话号码 我有一个员工表,也包含id、姓名、地址,还有许多电话号码 创建一个“电话号码”表并链接客户和员工,还是创建两个单独的“电话号码”表(一个用于客户,一个用于员工),更符合逻辑 如果我选择创建一个表,我可以为客户机和员工使用一个外键,还是必须创建两个外键 如果我选择生成一个外键,我是否必须使客户端ids从1开始并递增5,而员工ids从2开始并递增5,这样两个ids将不相同 如果我创建两个外键,一个有值,另一个允许为空?允许

我有一个带有
客户机
表的关系数据库,其中包含
id
名称
地址
,以及许多电话号码 我有一个
员工
表,也包含
id
姓名
地址
,还有许多电话号码

创建一个“电话号码”表并链接客户和员工,还是创建两个单独的“电话号码”表(一个用于客户,一个用于员工),更符合逻辑

如果我选择创建一个表,我可以为客户机和员工使用一个外键,还是必须创建两个外键

如果我选择生成一个外键,我是否必须使客户端
id
s从1开始并递增5,而员工
id
s从2开始并递增5,这样两个
id
s将不相同


如果我创建两个外键,一个有值,另一个允许为空?

允许您对所有内容使用外键的“正确方法”是有第四个表PhoneNumberRowner(id),并有client.phoneNumberRownerid和employee.phoneNumberRownerid字段;因此,每个客户机和每个员工在PhoneNumberRowner表中都有自己的记录。然后,您的phoneNumbers表变为(PhoneNumberRownerId,phoneNumber),允许您将多个电话号码附加到每个PhoneNumberRowner记录。

也许您可以以某种方式证明这一点,但在我看来,将员工和客户放在同一个表中是不合逻辑的。似乎您只想这样做,以便您的外键(在电话号码表中)都指向同一个表。这不是合并员工和客户的好理由


使用三个表格:员工、客户和电话号码。在电话表中,可以有一个字段指示员工或客户。顺便说一句,我不明白为什么电话号码必须是外键:这只会增加复杂性,但好处微乎其微。

我将采用的解决方案是:

CREATE TABLE Employees (
    employee_id    INT            NOT NULL,
    first_name     VARCHAR(30)    NOT NULL,
    ...
    CONSTRAINT PK_Employees PRIMARY KEY (employee_id)
)

CREATE TABLE Customers (
    customer_id    INT            NOT NULL,
    customer_name  VARCHAR(50)    NOT NULL,
    ...
    CONSTRAINT PK_Customers PRIMARY KEY (customer_id)
)

-- This is basic, only supports U.S. numbers, and would need to be changed to
-- support international phone numbers
CREATE TABLE Phone_Numbers (
    phone_number_id    INT            NOT NULL,
    area_code          CHAR(3)        NOT NULL,
    prefix             CHAR(3)        NOT NULL,
    line_number        CHAR(4)        NOT NULL,
    extension          VARCHAR(10)    NULL,
    CONSTRAINT PK_Phone_Numbers PRIMARY KEY (phone_number_id),
    CONSTRAINT UI_Phone_Numbers UNIQUE (area_code, prefix, line_number, extension)
)

CREATE TABLE Employee_Phone_Numbers (
    employee_id        INT    NOT NULL,
    phone_number_id    INT    NOT NULL,
    CONSTRAINT PK_Employee_Phone_Numbers PRIMARY KEY (employee_id, phone_number_id)
)

CREATE TABLE Customer_Phone_Numbers (
    customer_id        INT    NOT NULL,
    phone_number_id    INT    NOT NULL,
    CONSTRAINT PK_Customer_Phone_Numbers PRIMARY KEY (customer_id, phone_number_id)
)
当然,模型可能会根据许多不同的事情而改变。员工也可以是客户吗?如果两名员工共用一个电话号码,当一名员工的电话号码发生变化时,您如何在前端处理?它也会改变其他员工的电话号码吗?警告用户并询问他们想要做什么


最后几个问题不一定会影响数据的最终建模方式,但这肯定会影响前端的编码方式以及您可能需要支持它的存储过程的类型。

除非有特殊的业务需求,否则我希望电话号码是员工或客户实体的属性,而不是实体本身的属性


如果它本身被视为一个实体,它将是“全键”,即它的标识符是它的属性的复合物,除了它的标识符之外没有其他属性。如果子属性没有分开存储,那么它只有一个属性,即电话号码本身!因此,作为一个单独的实体,电话号码表(无论是超类还是子类)通常都不够“有趣”,而且通常过于复杂(如我所说,除非有特殊的业务需求)。

缺点是这种方法增加了模式的复杂性。您最好使用电话号码(type、ownerId、phoneNumber),类型为“client”或“employee”,并在数据库之外的应用程序中处理该逻辑。这排除了phoneNumbers.ownerId和client.id/employee.id.+1之间存在外键的可能性。这就是我要做的,只是我不会调用表
电话号码
,因为
-
需要转义…我认为这使得更新比需要的更复杂,例如必须具有“拆分”功能(例如,以前共享一个电话号码的两个客户端现在拥有单独的号码),“合并”(例如,以前拥有单独号码的两个客户端现在共享一个电话号码),删除“孤立的”电话号码等。有时,这是值得的,但对于电话号码,我怀疑不是。通常,这是一个由人读取的字段,允许他们通过电话方式联系可联系的实体,例如,
VARCHAR(35)
,可能带有一个
复选框
只允许数字加上一些其他字符。K.I.S.S.;)只有当你需要它的时候,它才是复杂的。如果您不想担心拆分和合并,请删除电话号码表中的唯一索引,但这是一个有意识的决定,您必须记住,当您更改我的家庭电话号码时,您还必须单独更改我妻子的家庭电话号码。只要业务规则要求这样做,只要各方都意识到每种方法的局限性和优点,那就可以了。我的观点是:删除唯一索引,拥有表就没有什么意义了。“当你更改我的家庭电话号码时,你还必须单独更改我妻子的家庭电话号码[sic]。”。。。是的,这是另一个问题:如果你假设拥有相同的
电话号码\u id
的人共用一部电话,但如果其中一部是打字错误,当该人更正后,两部手机都被更换了,而另一部则是错误的,那么事情就这样继续下去了。。。我的观点是:电话号码本身通常不是实体,所以通常不需要单独的表格。