我一直搞乱1NF

时间:2011-04-11 11:14:06

标签: sql normalization

对我来说,迄今为止我发现的关于1NF最易理解的描述是'主键是唯一标识每一行的列(或列组)。 '在www.phlonx.com上 我知道冗余意味着每个键每行的值不应超过1。超过1个值将是“多余的”。正确?

我仍然设法很多次搞砸1 NF。 我在线发布了一个问题pizzashop http://foo.com pizzashop here

我对第二种正常形式的东西感到困惑,只是注意到我在1 NF中开始出错了。 现在我想我在1NF中需要3个键才能唯一地识别每一行。 在这种情况下,我发现order_id,pizza_id和topping_id会为我做这件事。这就是3列。因为如果你想知道哪个特定的披萨你需要知道什么order_id它有什么类型的披萨(pizza_id)和那里的顶部。如果你知道,你可以查阅所有其他内容。 然而,从前一个问题的答案来看,这似乎是错误的,因为topping_id会转到另一个我不理解的表格。 这是列的列表:

ORDER_ID
order_date的
CUSTOMER_ID
CUSTOMER_NAME
电话
促销
黑名单Y或N
Customer_address
ZIP_CODE

企业邮箱
Pizza_id
Pizza_name
大小
Pizza_price

Topping_id
Topping_name
Topping_prijs
Availabitly
Delivery_id
Delivery_zone
Deliveryguy_id
Deliveryguy_name
交货Y或N

编辑:我用粗体标记了第一个连接键的id。它们只是列的列表,非标准化。他们不是一张桌子或三张桌子或任何东西

4 个答案:

答案 0 :(得分:2)

使用Object Role Modelling(比如使用NORMA)来捕获有关设计的信息,按下按钮并吐出SQL。

这比你在1NF,2NF等之间往返更容易。一个ORM设计保证在5NF。

一些注意事项:

  • 可以拥有复合键
  • 代理键可以在概念和逻辑设计之后添加:你已经预先添加了它们,这是不好的。由于RDBMS性能而不是在设计时添加它们
  • 你有没有在1NF上阅读几个来源?
  • 从简单的英语和一些事实开始。这是ORM用语言化做的事情。

所以:

  1. 顾客有很多比萨饼(0到n)
  2. 披萨有许多浇头(零到n)
  3. 客户有地址
  4. 披萨有一个基地
  5. ...

答案 1 :(得分:2)

我会为此使用更多表格,以消除客户,订单,浇头和pizze的重复:

表:客户

   Customer_id
    Customer_name
    Customer_name
    Phone
    Promotion
    Blacklist Y or N
    Customer_address
    ZIP_code
    City
    E_mail

表:订单

Order_id
Order_date
Customer_id
Delivery_zone
Deliveryguy_id
Deliveryguy_name
Delivery Y or N

表:Order_Details

Order_ID (FK on Order)
Pizza_ID (FK on Pizza)
Amount

表:比萨饼

Pizza_id
Pizza_name
Size
Pizza_price

表:Topping

Topping_id
Topping_name
Topping_prijs
Availabitly

表:Pizza_Topping

Pizza_ID
Topping_ID

Pizza_topping和Order_details是所谓的交叉表(“辅助”表,用于建模两个表之间的m:n关系)。

现在假设我们只有一个披萨,一些配料和我们的客户Billy Smith订购了2个quattro stagione pizze - 我们的表格将包含以下内容:

Pizza(Pizza_ID,Pizza_name,Pizza_price)

  1 Quattro stagioni 12€

Topping(Topping_id,topping_name,topping_price)

  1 Mozzarrella 0,50€
  2 Prosciutto 0,70€
  3 Salami 0,50€

Pizza_Topping(Pizza_ID,Topping_ID)

 1 1
 1 3

(这里,quattro stagioni披萨只包含Mozzarrella和Salami)。

订单(order_ID,客户名称 - 其余省略)

1 Billy Smith

Order_Details(order_id,Pizza_id,amount)

1 1 2  

我已删除了送货ID,因为对我来说,订单和送货没有区别 - 或者您是否支持部分送货?

答案 2 :(得分:1)

在1NF上,来自维基百科,引用日期:

  

根据Date对1NF的定义,   当且仅当表格为1NF时,表格为1NF   “与某种关系同构”,其中   具体而言,它意味着它满足   以下五个条件:

     
      
  • 这些行没有自上而下的排序。
  •   
  • 列中没有从左到右的排序。
  •   
  • 没有重复的行。
  •   
  • 每个行 - 列交叉点只包含一个   来自适用域的价值(和   没别的)。
  •   
  • 所有列都是常规的[即行没有隐藏的组件,如   行ID,对象ID或隐藏   时间戳]。

         

    -Chris Date,“First First Normal Form真正意味着什么”,第127-8页[4]

  •   

任何现代RDBMS都保证前两个。

现代RDBMS中可能存在重复行 - 但是,仅当您没有主键(或其他唯一约束)时才会这样。

第四个是最难的(并且取决于模型的语义) - 例如,您的字段Customer_address可能会破坏1NF。可能是因为如果你与自己(以及系统的任何潜在用户)签订合同,你将始终查看整个地址并且不想分开街道名称,街道号码或楼层,你仍然可以声称1NF没有被打破。

打破客户地址会更合适,但是那时你需要解决这些问题的复杂性,这可能带来任何好处(前提是你永远不必看到原子的一部分)地址线)。

第五个被一些现代的RDBM破坏了,但真正重要的是你的模型和系统应该依赖于隐藏的元素,这通常是正确的 - 即使你的RDBMS在内部使用OID进行某些操作,除非你开始使用对于非管理,非维护任务,你可以认为它没有打破1NF。

答案 3 :(得分:0)

relational databases的优势来自于将信息分成不同的表格。查看表的一个useful way首先将那些相对永久的概念(在您的情况下,可能是Pizza,Customer,Topping,Deliveryguy)标识为实体表。然后你考虑它们之间的关系(在你的情况下,订单,交货)。关系表通过使foreign keys指向相关实体将实体表链接在一起:订单具有Customer,Pizza,Topping的外键;交货有DeliveryGuy和订单的外键。而且,是的,关系可以联系关系,而不仅仅是实体。

只有在这样的环境中才能实现规范化。将一堆属性抛到一个单个表中并不会使数据库在任何有意义的意义上都是关系的。