谁能帮我推导函数依赖关系和规范化表?

Can anyone help me in Deriving of functional dependencies and Normalizing tables?

我已经为我的个人工作创建了餐厅 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);

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

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

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

进一步,查看“Bill”中的“OrderDetail”属性。形式化为逻辑模型意味着您将不得不决定此 属性 的数据类型。那么你要使用什么“数据类型”?在我看来,订单的“详细信息”是 整个列表 订购的商品,以及订购的数量等等。这是你的事吗将在您的数据库中的某些 table 中表示为一列? (我这里不是暗示说你的型号,是的,订单有订单明细,只是这么说还停留在非常高的抽象级别 +- 与您设法为其他实体实现的较低级别的抽象冲突。通过将其包含为 属性,您正在传达“它在那里,我知道它在那里,但我仍然不知道它是什么样子的。这需要“然后先详细说明”。(提示:你可能会发现实际上“order”和“bill”之间也有关系,因为“bill”仅在已送达订单的上下文中创建。这当然也意味着您将不得不形式化 that关系。)

我要到此为止了。

所以这是一个 Entity Relationship Model diagram, which back in the day we also used to call a Chen diagram. For some odd reason colleges and tutorials almost exclusively teach data modelling using this type of diagram model. What's odd is that virtually no one in industry or practical DB development ever uses them, it is considered an entirely unnecessary and onerous intermediate step in data modelling and database design, we just go straight to tables, columns and relations modelling (which we call "ER Models/Diagrams" but are technically IDEFX1 模型图,但同样没有人这样称呼它们)。

因此,从学校或教程中出来的每个人都称之为 ER 图,与工业界和实际使用中的每个人都认为是 ER 图是完全不同的事情。此外,如您所见,许多具有 DB 经验的数据人员甚至不知道 Chen 图是什么或如何阅读 Chen 图,因此他们完全不知道它们是(几乎)完整的数据库设计规范。因此,这个问题根本不是“太宽泛”或不具体。我自己在 20 年前就必须学习如何阅读这些图表,因为当时我采访了很多大学毕业生,而这是他们唯一知道的 diagramming/data-modelling 技术。

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

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

图例:

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

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

Tables 函数依赖:

  • 收银员: Cashier_Id --> 收银员姓名
  • 餐厅:名称 --> 地址,联系方式
  • 厨师: 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 列标记为有问题,因为它似乎是一个 non-relational/denormalized 的聚合字段,因此在数据设计中不合适(它们稍后在应用程序中添加 design/implementation,并且通常作为动态元素,而不是静态元素)。但为了清楚起见,我将保留它。

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

关系:

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

(*) -- 关于最后四个关系(Contains、Prepare、Works 和 Has)的注释,其中 none 与上面的箭头有联系,暗示它们应该代表多对多关系有几个问题。首先,多对多在关系数据设计中不是有效关系,在实践中需要人为创建一个中间“连接点”table 将其从 A:many-to-many:B 更改为三个 [=] 之间的两个关系234=]s:A:many-to-one:J:one-to-many:B。另一个问题是,从上下文(table 名称的含义)中可以清楚地看出,一个订单可以有很多餐点,但一顿饭的订单永远不会有很多,因此该图显然是错误的.

因此,为了避免陷入交汇点 table 的复杂性,我只是假设这些关系的图表是错误的,并且应该有从 <Contains>[Order] 和从 <Prepare>[Chef],等等。如果您确定这些应该是多对多关系,那么您将不得不合并它。

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

最终功能依赖性:

  • 收银员: Cashier_Id --> CashierName, Restaurant(Name)
  • 餐厅:名称 --> 地址,联系方式
  • 厨师: Chef_Id --> 厨师姓名,薪水,餐厅(名称)
  • Bill: 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

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

最后,我们准备做 Table 和关系 implementation/design。没有足够的 information/context 让我一直这样做到 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)
)

请注意,下面没有数据类型,因为图表中提供了 none。 None 实际上将在不为每一列指定数据类型的情况下进行编译。此外,“Order”一词在几乎所有数据库中都是保留关键字,因此您可能希望将 Orders table 的名称更改为类似“Order_”的名称以避免任何问题(否则您将不得不明确引用在所有引用它的 SQL 中都有这个名字。

我要注意的最后一件事:似乎 Bill table 应该有一个 relation/reference 到 Order table 但它没有(OrderDetail 列不这样做)根据你的图表)。