Ple*_* me 7 mysql database normalization denormalization
所以我理解如何创建外键,我知道FK的目的是什么.但是我在理解如何使用它们时遇到了问题.我问了一个关于外键的问题HERE(点击链接)
这是我做的:
CREATE TABLE user(
id INT(11) NOT NULL AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
password VARCHAR(20) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE items(
i_id INT(11) NOT NULL AUTO_INCREMENT,
name TINYTEXT NOT NULL,
price DECIMAL(8,2) NOT NULL,
PRIMARY KEY (i_id)
);
CREATE TABLE user_purchase(
i_id INT(11) NOT NULL,
name TINYTEXT NOT NULL,
id INT(11) NOT NULL,
FOREIGN KEY (i_id) REFERENCES items(i_id),
FOREIGN KEY (name) REFERENCES items(name),
FOREIGN KEY (id) REFERENCES user(id)
);
Run Code Online (Sandbox Code Playgroud)
现在我的问题是如何使用PHP充分利用它?从上面的链接,人们建议在user_purchase表中只使用一个外键是好的,但如果我想要多个列呢?为什么我们不为同一个表的不同列使用多个外键?
我正在使用mysql和php.如果你能展示一些如何使用带有外键的表来使用PHP来获取使用MYSQL命令获取信息的例子,我将不胜感激.我真的需要一个彻底的解释.
我还需要理解规范化和非规范化这两个术语.如果您能够通过示例详细解释这些术语,或者如果您对数据库设计,实现等初学者的一些好书有任何建议,我将不胜感激,我将非常感激.
非常感谢.
geo*_*gas 20
所以我理解如何创建外键,我知道FK的目的是什么.但是我在理解如何使用它们时遇到了问题.
假设您指的是外键约束,简短的答案就是您不要使用它们.
这是一个漫长的:
我们习惯于将列作为其他表的外键引用.特别是在规范化过程中,像" user_purchase.i_id是items表的外键"这样的短语会很常见.虽然这是描述关系的完美有效方式,但是当我们到达实施阶段时,它会变得有点模糊.
假设你已经创建了自己的表没有的FOREIGN KEY条款:
CREATE TABLE user(
id INT(11) NOT NULL AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
password VARCHAR(20) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE items(
i_id INT(11) NOT NULL AUTO_INCREMENT,
name TINYTEXT NOT NULL,
price DECIMAL(8,2) NOT NULL,
PRIMARY KEY (i_id)
);
CREATE TABLE user_purchase(
i_id INT(11) NOT NULL,
name TINYTEXT NOT NULL,
id INT(11) NOT NULL,
);
Run Code Online (Sandbox Code Playgroud)
请注意,关系的角度来看,外键列都还在实施.有一个引用usertable(id)的列和另一个引用itemstable(i_id)的name列- 让我们把这个列搁置一会儿.请考虑以下数据:
user user_purchase items
| id username | | id i_id | | i_id name price |
| 23 john | | 55 10 | | 10 chocolate bar 3.42 |
| 55 mary | | 70 10 | | 33 mobile phone 82.11 |
| 70 fred | | 70 33 | | 54 toothpaste 8.67 |
| 55 10 | | 26 toy car 6.00 |
| 70 26 |
Run Code Online (Sandbox Code Playgroud)
关系就在那里.它是通过user_purchase表格实现的,该表格保存了谁购买了什么的信息.如果我们要在数据库中查询相关报告,我们会这样做:
select * from user_purchase p
join user u on (p.id=u.id)
join items i on (p.i_id=i.i_id)
Run Code Online (Sandbox Code Playgroud)
这就是我们如何使用关系和所涉及的外键列.
现在,如果我们这样做:
insert into user_purchase (id,i_id) values (23,99)
Run Code Online (Sandbox Code Playgroud)
显然,这是一个无效的条目.虽然有用户id=23,但没有项目i_id=99.RDBMS将允许这种情况发生,因为它不知道更好.然而.
这就是外键约束发挥作用的地方.通过FOREIGN KEY (i_id) REFERENCES items(i_id)在user_purchase表定义中指定,我们基本上为RDBMS提供了遵循的规则:具有i_id未包含在items.i_id列中的值的条目是不可接受的.换句话说,当外键列实现引用时,外键约束强制引用完整性.
但是请注意,上面的内容select不会改变,只是因为您定义了FK约束.因此,您不使用RDBMS的FK约束来保护您的数据.
...如果我想要几列怎么办?为什么我们不为同一个表的不同列使用多个外键?
问问自己:你为什么要这样?如果两个外键用于同一目的,冗余最终会让您遇到麻烦.请考虑以下数据:
user_purchase items
| id i_id name | | i_id name price |
| 55 10 chocolate bar | | 10 chocolate bar 3.42 |
| 70 10 chocolate bar | | 33 mobile phone 82.11 |
| 70 33 mobile phone | | 54 toothpaste 8.67 |
| 55 10 toothpaste | | 26 toy car 6.00 |
| 70 26 toy car |
Run Code Online (Sandbox Code Playgroud)
这张照片出了什么问题?用户55买了两块巧克力棒,巧克力棒和牙膏吗?这种模糊性会导致为保持数据同步而付出很多努力,如果我们只保留一个外键,这将是不必要的.实际上,为什么不name完全删除列,因为关系暗示了它.
当然,我们可以通过实施复合外键,通过设置解决此PRIMARY KEY(i_id,name)为items表(或定义一个额外的UNIQUE(i_id,name)指标,它不会真的重要),然后设置一个FOREIGN KEY(i_id,name) REFERENCES items(i_id,name).这样,只有(i_id,name)夫妇存在于items表中才有效user_purchases.除了你仍然有一个外键的事实之外,这种方法是完全没必要的,前提是该i_id列已经足以识别一个项目(对于name列来说不能说相同......).
但是,没有规则禁止对表使用多个外键.事实上,有些情况需要这种方法.考虑一个person(id,name)表和一个表,parent(person,father,mother)其中包含以下数据:
person parent
| id name | | person father mother |
| 14 John | | 21 14 59 |
| 43 Jane | | 14 76 43 |
| 21 Mike |
| 76 Frank |
| 59 Mary |
Run Code Online (Sandbox Code Playgroud)
显然,表的所有三列parent都是外键person.不过,对于同一个关系,不过是三个不同的关系:既然一个人的父母也是人,那么两个相应的列必须引用同一个表person.但请注意,这三个字段不仅可以而且还必须person在同一parent行中引用不同的s ,因为没有人是他自己的父母,也没有人的父亲也是他的母亲.
外键用于连接。例如,如果您想知道购买特定商品的用户名,您可以编写:
select u.username
from items i
join user_purchase up on i.i_id = up.i_id
join user u on u.id = up.id
where i.name = "Some product name"
Run Code Online (Sandbox Code Playgroud)
它们也可以被数据库引擎本身使用。它可以检测您创建的行或列user_purchase是否与其他表中引用的列中的任何内容都不匹配。idi_id
您不应复制表name中的列user_purchase。这name只是 的一个属性item,它并不特定于任何特定的购买。如果您需要获取所购买商品的名称,请加入该items表。