多个表和列的外键?

时间:2013-11-02 12:07:54

标签: mysql database database-design foreign-keys

我一直在学习外键,我想知道我在下面的例子中使用它的方式是否正确:

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)
);

由于

现在,如果我使用PHP,我怎样才能从外键获取最大信息呢?

2 个答案:

答案 0 :(得分:2)

您不必在两个表中都包含项目名称。这称为非规范化解决方案。 您应该只在items表中使用它并且只引用id,然后如果您需要该名称,您也可以根据主键(id)加入它。 否则在我看来完全没问题。

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 (id) REFERENCES user(id)
);

有时,当性能至关重要时,您必须使用非规范化表。它可以快得多。

归一化对于避免不同的异常非常重要。 如果你有一个高级正常形式的表,那么你的表将不会是多余的,不会有这些异常。例如,如果您在多个位置存储了某些内容,则必须保持所有冗余数据的最新状态。这使您有机会错误地执行此操作并最终出现不同的异常情况。

在您的情况下,使用外键可以帮助您保持数据完整性,但如果没有外键用于名称,您就可以在商品表中没有商品名称。

这是一种异常。

这种情况有很多种,只要你能尽力避免它们。

Read more here about anomalies

在某些情况下,您必须对其进行解密。因此,由于性能问题,冗余地存储一些数据。这样可以节省一些可能耗费大量时间的连接操作。

规范化的细节由不同正常形式的主题涵盖: NF0,NF1,NF2,NF3和BCNF

Normal forms in detail

有关无损分解到更高范式的数学基础的更多详细信息,请参阅“功能依赖性”。这有助于您了解为什么可以保持ID“冗余”。实际上它们是必要的冗余,因为您需要它们以便以后能够重建原始数据集。这将是不同正常形式的定义。允许什么级别的冗余?

Functional Dependencies

答案 1 :(得分:2)

您有一个i_id作为主键,您不需要将名称设置为外键。和btw外键必须引用唯一属性。

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 UNIQUE 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 (id) REFERENCES `user`(id)    
);