日期:2011-01-10  浏览次数:20513 次

  在我们目前的情况下,我们所需要的列是Jokes表中的JokeText列以及Authors表中的Name列和Email列。Jokes表和Authors表的关联条件是Jokes表中的AID列的值等于Authors表中的ID列的值。下面是一个连接的例子(前两个查询只是用来显示我们的两个表中所包含的内容):


mysql> SELECT LEFT(JokeText,20), AID FROM Jokes;
+----------------------+------+
| LEFT(JokeText,20) | AID |
+----------------------+------+
| Why did the chicken | 1 |
| A man walked into a | 1 |
| Knock knock. Who's t | 2 |
+----------------------+------+
3 rows in set (0.00 sec)

mysql> SELECT * FROM Authors;
+----+------------+---------------------+
| ID | Name | EMail |
+----+------------+---------------------+
| 1 | Kevin Yank | kyank@attglobal.net |
| 2 | Joan Smith | joan@somewhere.net |
+----+------------+---------------------+
2 rows in set (0.00 sec)

mysql> SELECT LEFT(JokeText,15), Name, Email
    -> FROM Jokes, Authors WHERE AID = Authors.ID;
+-------------------+------------+--------- -- -
| LEFT(JokeText,15) | Name | EMail
+-------------------+------------+--------- -- -
| Why did the chi | Kevin Yank | kyank@attg...
| A man walked in | Kevin Yank | kyank@attg...
| Knock knock. Wh | Joan Smith | joan@somew...
+-------------------+------------+--------- -- -
3 rows in set (0.00 sec)



  现在明白了吗?第三个SELECT的结果就是一个连接,它将存储在两个表中的数据关联数据显示到了一个结果表中,尽管我们的数据是存储在两个表中的,我们仍然可以使用一个数据库查询就获得我们的Web页面所需要的笑话列表的全部信息。

  在这里,要注意一个问题,因为在两个表中都有一个叫ID的列,所以我们在用到Authors表中的ID列时我们必须指定表名(Authors.ID)。如果我们没有指定表名,MySQL将无法知道我们指的是哪一个表中的ID,这会导致这样的一个错误:


mysql> SELECT LEFT(JokeText,20), Name, Email
    -> FROM Jokes, Authors WHERE AID = ID;
ERROR 1052: Column: 'ID' in where clause is ambiguous



  现在我们知道如何有效率地从我们的两个表中获取信息了,我们可以利用连接来重新编写我们的笑话列表的程序:


$jokelist = mysql_query(
  "SELECT JokeText, Name, EMail " .
  "FROM Jokes, Authors WHERE AID=Authors.ID");

while ($joke = mysql_fetch_array($jokelist)) {
  $joketext = $joke["JokeText"];
  $name = $joke["Name"];
  $email = $joke["EMail"];

  // Display the joke with author information
  echo( "<P>$joketext<BR>" .
        "(by <A HREF='mailto:$email'>$name)</P>" );
}



  随着你对数据库的使用,你会越来越发现连接的功能有多大的意义。例如,下面的查询用来显示所有由Joan Smith写的笑话:


mysql> SELECT JokeText FROM Jokes, Authors WHERE
    -> Name="Joan Smith" AND AID=Authors.ID;



  上面的查询的输出结果仅仅来源于Jokes表,但是我们使用了一个连接来通过存储在Authors表中的值搜索笑话。在我们的这篇文章中会有更多的这样的精巧的查询,在实际应用中,连接是经常会被使用的,而且在绝大多数的情况下,这会很大程度地简化我们的工作!

简单的数据关系

  对于给定的情况的最好的数据模型往往决定于我们所工作的两种数据之间的关系类型。我这篇文章中,我们将对典型的关系类型进行研究,并学会如何在一个关系型数据中用最好的方法描述它。

  对于简单的一对一的关系,只要用一个表就足够了。一对一关系的一个例子就是我们在前面已经看到的在笑话数据库中的每一个作者的e-mail地址。因为对于每一个作者只有一个e-mail地址,而且对于一个e-mail地址对应的也只有一个作者,将它们分到两个数据库中是没有道理的。

  多对一的关系可能会稍微复杂一点,但是在之前其实我们也已经解决了这个问题,我们的数据库中的每一个笑话只会有一个作者,但是同一个作者可能写了很多笑话。笑话和作者之间的关系就是一个多对一的关系。我们曾经有过一个初步的解决方案,那就是将与这个笑话关联的作者的信息也促成在同一个数据库中。但是这样做,对于同一个数据会有许多拷贝,这不仅会在同步上造成困难,而且会浪费空间。将数据分开到两个数据表中并使用一个ID列来连接两个表(象上面所说的那样使用连接),所有的问题会得到很好的解决。

  到目前为止,我们还没接触到一对多的关系,但是想象这样的一个关系应该是不困难的。在我们之前建立的数据库中,我们假定一个作者只有一个e-mail地址。事实上情况并不总是这样的,作出这个限制的理由只是因为我们只需要一个e-mail地址来与作者联系。我们简单地假设了作者总会输入他们常用的e-mail地址,或者至少是一个正常使用的e-mail地址。如果我们想要支持多个e-mail地址,我们将面对一个一对多的关系(一个作者会有几个e-mail地址,但是一个e-mail地址只会与一个确定的作者对应)。

  一个没有经验的数据库设计者面对一个一对多的关系时,他首先会想到的是试图把多个数据存储到一个数据库域中,就象这样:

  这种结构在投入使用后,要从数据库中获得一个单个的e-mail地址,将不得不通过搜索逗号(或者你所选择的用来分隔的其他符号)来分割字符串,这样做并不简单,而且会很耗时。设想一下如果要用PHP来删除某个作者的某个e-mail地址,那也将会是很困难的事。另外,对于EMail列我们需要很长的长度,这会导致磁盘空间的浪费,因为大多数的作者都只会有一个e-mail地址。

  解决一对多的关系和我们上面解决多对一的关系是非常类似的。实际上两者之前只是一个简单的颠倒。我们可将Authors表分成两个表,Authors和EMails,然后在EMails表中使用作者的ID(AID)