(18)索引
索引允许DBMS更快地访问数据。系统创建了这个内部地数据结构(即索引),它导致当查询以列为索引的时候搜索行,这样查询会快得多。这个索引对于给定列索引数值的时通知DBMS找到表中某一行,这有点象书的索引,它告诉你对于给定的字你能找到哪一页。下面让我们在AntiqueOwners列中为OwnerID创建索引:
CREATE INDEX OID_IDX ON ANTIQUEOWNERS (OWNERID);
下面语句是为名字创建所以:
CREATE INDEX NAME_IDX ON ANTIQUEOWNERS (OWNERLASTNAME, OWNERFIRSTNAME);
为了删除索引,你可以利用DROP:
DROP INDEX OID_IDX;
就象前面教程中,我们也可以"drop"(删除)一个表。上面第二个例子中,是在两列上创建索引的。
有些DBMS不强迫要求主键,换句话说就是,类的唯一性不会自动强制。这是什么意思呢,好象听起来云里雾里的。好吧,再给你举个例子,如果你象插入另外一行到AntiqueOwners表中,比如这个OwnerID是02,有些系统可以让你这样做即使我们要求所有行的数值都要是不同的。为了避免两行有相同的值,我们有一种方法来克服,就是在列上创建唯一的索引,而在这个列上我们需要它成为主键,这样就可以系统不会出现复制的情况:
CREATE UNIQUE INDEX OID_IDX ON ANTIQUEOWNERS (OWNERID)
(19)DISTINCT和排除复制
假如你象列出所有买过古董的ID和名字,很明显,你可能会将所有的顾客都列出来而没有考虑有些顾客是买过多讲古董的,所以这时你会发现有些数据是重复的。这就意味着你需要通知SQL来排除复制的行,而不管这个顾客买过多少个古董只需要列出一次即可。为了实现这个目的,你可以使用DISTINCT关键字。
首先我们需要为AntiqueOwners表来一个equijoin以得到顾客的LastName和First的详细数据。但是,你要考虑到Antiques表中的SellerID列是AntiqueOwners表的一个外码,所以顾客只能在AntiqueOwners表列出ID和名字的行才被列出。我们还想在列的数据中排除SellerID复制的发生,所以我们要在发生重复的列上使用DISTINCT 。
为了防止复制的发生,我们还想将LastName以字母顺序排列,然后在按字母顺序排列FirstName最后排列OwnerID,因此我们还必须使用ORDER BY子句,具体语句如下:
SELECT DISTINCT SELLERID, OWNERLASTNAME, OWNERFIRSTNAME
FROM ANTIQUES, ANTIQUEOWNERS
WHERE SELLERID = OWNERID
ORDER BY OWNERLASTNAME, OWNERFIRSTNAME, OWNERID
在这个例子中,因为每个人都买都一个件古董,所以我们将Lasname以字母顺序列出所有的古董拥有者。
(20)Aliases 、In以及子查询
在本节教程中,我们将要介绍Aliases、 In以及子查询的用法。首先我们看一下一个查询语句,它搜索所有已经定货的顾客的LastName以及他们定什么货,语句如下:
SELECT OWN.OWNERLASTNAME Last Name, ORD.ITEMDESIRED Item Ordered
FROM ORDERS ORD, ANTIQUEOWNERS OWN
WHERE ORD.OWNERID = OWN.OWNERID
AND ORD.ITEMDESIRED IN
(SELECT ITEM
FROM ANTIQUES);
这条查询语句的结果为:
Last Name Item Ordered
--------- ------------
Smith Table
Smith Desk
Akins Chair
Lawson Mirror
下面好好解释一下上面的这条语句:
"Last Name" 和"Item Ordered"给出了报告的数据头。
OWN & ORD是aliases(别名),它们使用在FROM子句中,可在它们的后面加一个点号再加列名就可以进行查询了。这样做就避免了模棱两可的情况,特别是在equijoin WHERE子句中当两个列都名为OwenerID的时候,而点号就通知SQL我们使用是两个不同表的不同OwnerID。
这里要注意,在FROM子句中Orders表被首先列出,并且确保AntiqueOwners表只用于详细的信息(Last Name)。更为重要的,在WHERE子句中的AND强迫In子查询被调用("= ANY" or "= SOME" 都等价于使用IN)。但这到底做了些什么呢?当这个子查询完成了,它就返回Antiques表的所有Items因为这里没有WHERE子句。然后,对于从Orders表列出的行,ItemDesired必须在从Antiques表中返回的Items列表中,然后在定货可以有另外的拥有者填写的情况下列出一个item。你可以想想这个方法:子查询从Orders 表中的每一个ItemDesired被比较中返回一系列的Items;如果ItemDesired是在从Antiques表中返回的,那么条件才为真。


