【问题标题】:Can anyone help me in Deriving of functional dependencies and Normalizing tables?任何人都可以帮助我导出功能依赖关系和规范化表吗?
【发布时间】:2021-05-19 12:09:59
【问题描述】:

我已经创建了餐厅 e-r 图,对于我的个人工作,任何人都可以帮助我导出函数依赖关系,规范化表(BCNF 形式)和基于获得的关系构建数据库。

更新

我创建了关系模型并将其规范化为 3NF:

这是我的 oracle SQL 代码:

create table restaurant(
    name varchar(20),
    city varchar(20) not null,
    contact_no char(15),
    constraint pk_name_restaurant primary key(name)
    );

create table contact_number(
    contact_no char(15),
    address varchar(50) not null,
    constraint pk_contact_no_contact_number primary key(contact_no)
    
);
create table cashier(
    cashier_id char(10)  ,
    cashier_name varchar(20) not null,
    constraint pk_chashierId_cashier primary key(cashier_id)

);

create table restaurant_has(
    name varchar(20),
    cashier_id char(10),
    constraint pk_restaurantHas primary key(name,cashier_id)
 
);

create table chef(
    chef_id char(10),
    chef_name varchar(20) not null,
    salary number(5,0),
    constraint pk_chefid_chef primary key(chef_id)
);

create table chef_works(
    name varchar(20) ,
    chef_id char(10),
    constraint pk_chefworks primary key(name,chef_id)
);


create table customer_order(
    order_no char(10),
    num_meals number(2,0),
    bill_no char(10) not null,
    constraint pk_orderno_order primary key(order_no)
);

create table chef_prepares(
    chef_id char(10),
    order_no char(10),
    constraint pk_chefprepares primary key(chef_id,order_no)
);

create table meal(
    meal_no char(10),
    quantity number(2,0),
    meal_price number(2,0),
    meal_title varchar(25) not null,
    order_no char(10) not null,
    constraint pk_orderno_meal primary key(meal_no)
);

create table meal_title(
    meal_title varchar(25),
    ingredients varchar(75) not null,
    constraint pk_mealtitle primary key(meal_title)
);

create table customer(
    cust_id char(10),
    cust_address varchar(50),
    cust_phone char(15) not null,
    constraint pk_custid_customer primary key(cust_id)
);

create table customer_phone(
    cust_phone char(15),
    cust_name varchar(20) not null,
    constraint pk_customerphone primary key(cust_phone) 
);

create table order_bill(
    bill_no char(10),
    price number(5,0) not null,
    bill_date date not null,
    cust_id char(10) not null,
    cashier_id char(10) not null,
    constraint pk_billno_orderbill primary key(bill_no)
);

alter table restaurant add constraint fk_contactNo_restaurant foreign key(contact_no) references contact_number(contact_no);

alter table restaurant_has add constraint fk_name_restauranthas foreign key(name) references restaurant(name);

alter table restaurant_has add constraint fk_cashierid_restauranthas foreign key(cashier_id) references cashier(cashier_id);

alter table chef_works add constraint fk_name_chefworks foreign key(name) references restaurant(name);

alter table chef_works add constraint fk_chefid_chefworks foreign key(chef_id) references chef(chef_id);

alter table chef_prepares add constraint fk_chefid_chefprepares foreign key(chef_id) references chef(chef_id);

alter table chef_prepares add constraint fk_chefid_chefprepares foreign key(chef_id) references chef(chef_id);

alter table customer_order add constraint fk_billno_customerorder foreign key(bill_no) references  order_bill(bill_no);

alter table meal add constraint fk_mealtitle_meal foreign key(meal_title) references meal_title(meal_title);

alter table meal add constraint fk_orderno_meal foreign key(order_no) references customer_order(order_no);

alter table customer add constraint fk_custphone_customer foreign key(cust_phone) references customer_phone(cust_phone);

alter table order_bill add constraint fk_custid_orderbill foreign key(cust_id) references customer(cust_id);

alter table order_bill add constraint fk_cashierid_orderbill foreign key(cashier_id) references cashier(cashier_id);

【问题讨论】:

  • 嗨 - 不幸的是,这个问题可能过于宽泛,无法得到有用的回应。如果您展示自己已成功实现的目标,然后针对您遇到的特定问题提出一个有针对性的具体问题,那么您更有可能得到答复
  • 嗨,我的一个问题是账单和订单之间必须有关系吗?
  • 第二个在我的图中订单和餐是一对多的关系,客户和订单,客户和账单也是一对多是真的吗?
  • 您的任何问题都没有正确答案,这完全取决于您的具体情况、您的要求、您决定如何建模等。例如,如果一组人们一起吃饭,每个订单可能有多个客户;一个人可以为团队支付账单,或者团队中的每个人都可以支付他们的份额
  • @RBarryYoung 除了你之外,每个人都认为这个问题过于宽泛的原因是 Stackoverflow 的目的是获得特定、技术、编码挑战的答案。你不得不写一篇“论文”来试图回答这个问题,这一事实证明了这一点

标签: sql database database-design entity-relationship functional-dependencies


【解决方案1】:

所以这是一个Entity Relationship Model diagram,过去我们也习惯称之为陈图。由于某些奇怪的原因,大学和教程几乎都专门使用这种类型的图表模型教授数据建模。奇怪的是,几乎没有人在工业或实际数据库开发中使用过它们,这被认为是数据建模和数据库设计中完全不必要且繁重的中间步骤,我们直接进入表、列和关系建模(我们称之为“ ER 模型/图表”,但从技术上讲是 IDEFX1 模型图,但同样没有人这么称呼它们)。

因此,从学校或教程中出来的每个人都称之为 ER 图,而行业和实际应用中的每个人都认为 ER 图是完全不同的东西。此外,如您所见,许多具有 DB 经验的数据人员甚至不知道 Chen 图是什么或如何阅读,因此他们完全不知道它们是(几乎)数据库设计的完整规范。因此,这个问题一点也不“太宽泛”或不具体。 20 年前,我自己不得不学习如何阅读这些图表,因为当时我正在采访这么多大学毕业生,而这是他们所知道的唯一图表/数据建模技术。

我将介绍阅读和解释此图表的过程,并解释如何将其转化为功能依赖关系和(几乎完整的)数据设计。这与将 Chen 图转换为文本形式本质上是相同的任务,我将把它保留为文本形式而不制作 IDEFX1(表关系)图(我现在真的没有一个好的工具,因为我是退休)。此处未指定数据类型(这对于 Chen 图来说很正常),虽然 技术上 正式的关系数据设计确实 NOT 需要数据类型,但实际上你确实需要它们来完成你的设计和实施。此外,您的图表中似乎有几个错误或遗漏,我会在找到它们时指出。

让我们从如何阅读陈图的基础开始:

传说:

  • (蓝色)矩形变成了 Codd“关系”(intra-table)的表格。
  • 椭圆形或“气泡”是它们所附加到的表中的列,
  • 带有下划线文本的椭圆表示它们所附加到的表的主键,
  • (蓝色)菱形代表 Chen 关系(inter-table),通常会成为您的外键约束,
  • 从菱形(关系)到矩形(表格)的线条也表示基数。箭头表示一个的基数,而没有箭头表示“许多”(这实际上在不同的“样式”中变化很大,所以我猜测您使用的是哪种样式)。

所以现在我们可以浏览图表,首先查看表和列,并从中派生出 intra 表的功能依赖关系。表内函数依赖主键列所有其他列(如果有备用键,那么这些将是额外的函数依赖)

表格功能依赖:

  • 收银员: Cashier_Id --> CashierName
  • 餐厅: 名称 --> 地址、联系方式
  • 主厨: Chef_Id --> ChefName, Salary
  • 账单: Bill_No --> 价格,订单详情
  • 客户: Cust_Id --> Cust_Name、Cust_Phone、Cust_Address
  • 膳食: Meal_No --> Meal_Title、Meal_Price、描述、数量
  • 订单: Order_No --> #Num_Meals(??)

我已将 #Num_Meals 列标记为有问题,因为它似乎是一个非关系/非规范化的聚合字段,因此在数据设计中不合适(它们是在应用程序设计/实现的后期添加的,通常作为动态元素,而不是静态元素)。但为了清楚起见,我会保留它。

现在我们准备查看 Chen 关系以导出 inter-表函数依赖关系:

关系:

  • PaidTo:账单 --> 收银员
  • 支付:账单 --> 客户
  • 地点:订单 --> 客户
  • 包含:膳食 --> 订单 (*)
  • 准备:订单 --> 厨师 (*)
  • 作品:收银员 --> 餐厅 (*)
  • :厨师 --> 餐厅 (*)

(*) -- 关于最后四个关系(Contains、Prepare、Works 和 Has)的注释,它们都没有带有箭头的连接,这意味着它们应该代表多对多有几个问题的关系。首先,多对多不是关系数据设计中的有效关系,实际上需要人为创建一个中间“连接”表,将其从A:many-to-many:B 更改为三个表之间的两个关系:A:many-to-one:J:one-to-many:B。另一个问题是,从上下文(表名的含义)中可以清楚地看出,一份订单可以有很多餐,但一份餐不能有很多订单,因此图表显然是错误的。

因此,为了避免进入连接表的复杂性,我只是假设图表对于这些关系是错误的,并且应该有从 <Contains>[Order] 和从 <Prepare> 到 @987654331 的箭头@ 等。如果您确定这些应该是多对多关系,那么您将不得不合并它。

现在我们需要做的就是合并和减少两个函数依赖列表,这样就没有冗余了。只需将表名替换为其主键对应的列名,即可将相关表 FD 更改为表列 FD。例如,PaidTo 关系的Bill --> Cashier 将变为Bill_No --> Cashier_Id。将所有 FD 更改为表列 FD 后,您希望通过组合左侧具有相同“键”的任何 FD 来删除任何冗余。因此,Bill_No --> Cashier_IdBill_No --> Price, OrderDetail 将合并为 Bill_No --> Price, OrderDetail, Cashier_Id

最终的功能依赖

  • 收银员: Cashier_Id --> CashierName, Restaurant(Name)
  • 餐厅: 名称 --> 地址、联系方式
  • 厨师: Chef_Id --> ChefName、Salary、Restaurant(Name)
  • 账单: Bill_No --> Price、OrderDetail、Cashier_Id、Cust_Id
  • 客户: Cust_Id --> Cust_Name、Cust_Phone、Cust_Address
  • 膳食: Meal_No --> Meal_Title、Meal_Price、描述、数量、Order_No
  • 订单: Order_No --> #Num_Meals(??), Cust_Id, Chef_Id

警告,不同的人、老师、讲师和教程可能会以不同的方式执行此(减少),从而最终得到不同的最终列表。您必须查看课程讲师期望的规则并在此处应用它们。

最后,我们准备好进行表和关系的实现/设计。没有足够的信息/上下文让我一直这样做到 BCNF,但根据我们上面的内容,我可以非常接近:

TABLE Restaurant
(   Name Primary Key,
    Address,
    ContactNo
)

TABLE Cashier
(   Cashier_Id Primary Key,
    CashierName ,
    Restaurant_Name FOREIGN KEY References Restaurant(Name)
)

TABLE Chef
(   Chef_Id Primary Key,
    ChefName,
    Salary,
    Restaurant_Name FOREIGN KEY References Restaurant(Name)
)

TABLE Bill
(   Bill_No Primary Key,
    Price,
    OrderDetail,
    Cashier_Id FOREIGN KEY References Cashier(Cashier_Id)
    Cust_Id FOREIGN KEY References Customer(Cust_Id)
)

TABLE Meal
(
    Meal_No Primary Key,
    Meal_Title,
    Meal_Price,
    Description,
    Quantity,
    Order_No FOREIGN KEY References Order(Order_No)
)

TABLE Order
(
    Order_No Primary Key,
    #Num_Meals (??),
    Cust_Id FOREIGN KEY References Customer(Cust_Id),
    Chef_Id FOREIGN KEY References Chef(Chef_Id)
)

请注意,下面没有数据类型,因为图中没有提供任何数据类型。如果不为每列指定数据类型,这些都不会真正编译。此外,“Order”一词在几乎所有数据库中都是保留关键字,因此您可能希望将 Orders 表的名称更改为“Order_”之类的名称以避免任何问题(否则您将不得不在所有数据库中明确引用此名称引用它的 SQL)。

我要注意的最后一件事:Bill 表似乎应该与 Order 表有关系/引用,但它没有(根据您的图表,OrderDetail 列没有这样做)。

【讨论】:

  • 感谢您的解释。我在我的 ER 图中进行了一些更新,并尝试创建一个关系模型,然后将其规范化为 3NF(在我的问题下方添加了图像),我还添加了 oracle SQL 代码。你能检查所有的吗?我所做的一切都是真的吗??
  • @NailaBagir 我现在没有那么多时间,从技术上讲,全面审查将是另一个(新的、不同的)问题。但是,快速回顾一下,您似乎确实正确地解决了我所有的问题和疑虑。请记住对您认为有帮助的任何答案进行投票,如果有任何答案回答了您的问题,请将其中一个标记为答案。
  • 哦,好的),再次感谢您。
【解决方案2】:

不幸的是,这确实是“一个过于宽泛的问题”。 (最短的答案是“阅读所有关于概念建模和形式逻辑建模之间差异的文章,以及如何从前者到后者。”。)我只能提供一些提示。

您似乎使用了 E/R 语法,其中实体是矩形,关系是菱形。省略号表示实体的“属性”。然而,E/R 是一种概念建模技术,而归一化理论适用于 形式化 模型,其中表示每一个作为关系(数学这个词的意义)。因此,您需要担心如何在这个概念模型中制作一切,表示为“与属性的关系”。提示:对于实体,您似乎已经拥有它们,但是关系呢(请注意:relationship 与关系不一样!!!)。例如,如果给定的收银员在一家餐厅工作 40%,在另一家餐厅工作 60%,你将如何表示?这种情况应该得到支持吗?

然后,您似乎已经考虑过标识符,因为您在它们下划线了。规范化理论的意义在于,+- 是为了便于识别所有应用于逻辑模式中的关系的键。查看您的“餐厅”实体。您似乎已经决定,用 FD 术语来说,{Name} -> {Address, ContactNo}。您需要担心的是诸如“{ContactNo} -> {Name, Address} 是否也是这种情况?”之类的问题。或者 iow,“会不会是两个不同的餐厅有相同的联系方式?”。

进一步,查看“Bill”中的“OrderDetail”属性。形式化为逻辑模型意味着您必须决定该属性的数据类型。那么你打算使用什么“数据类型”呢?在我看来,订单的“详细信息”是订购物品的整个列表,以及订购的数量等。这是你要代表的东西吗?数据库中某个表中的列? (我并不是说您的模型在这里错误。是的,订单有订单详细信息。只是这样说仍然处于非常高的抽象级别+- 与您设法为其他实体实现的较低抽象级别冲突。通过将其作为属性包含在内,您正在传达“它在那里,我知道它在那里,但我仍然不知道到它看起来像什么”。这需要“然后先详细说明”。(提示:您可能会发现实际上“订单”和“账单”之间也存在关系,因为“账单”仅在上下文中创建按送达的顺序。这当然也意味着您将不得不正式确定 关系。)

我要在这里停下来。

【讨论】:

  • 感谢您的解释。我在我的 ER 图中做了一些更新(我在上一张图片下添加了一张图片)。是否必须向收银员添加属性(例如,work_hours)?
猜你喜欢
  • 2020-12-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-25
  • 1970-01-01
  • 2016-04-29
  • 1970-01-01
  • 1970-01-01
  • 2019-10-12
相关资源
最近更新 更多