如何使用PHP的外键

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_iditems表的外键"这样的短语会很常见.虽然这是描述关系的完美有效方式,但是当我们到达实施阶段时,它会变得有点模糊.

假设你已经创建了自己的表没有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 ,因为没有人是他自己的父母,也没有人的父亲也是他的母亲.


Bar*_*mar 4

外键用于连接。例如,如果您想知道购买特定商品的用户名,您可以编写:

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表。