1、第三部分 操作数据:SQL本部分内容 SQL 基础 中级 SQL 高级 SQL第 10章 SQL 基础本章内容SQL介绍使用 SELECT 语句从表中取数据创建新表字段属性 向表中添加数据删除和修改表 为了建立交互站点,你需要使用数据库来存储来自访问者的信息。例如,你要建立一个职业介绍服务的站点,你就需要存储诸如个人简历,所感兴趣的工作等等这样的信息。创建动态网叶也需要使用数据库,如果你想显示符合来访者要求的最好的工作,你就需要从数据库中取出这份工作的信息。你将会发现,在许多情况下需要使用数据库。在这一章里,你将学会怎样使用“结构化查询语言” (SQL来操作数据库。SQL 语言是数据库的标准语
2、言。在 Active Sever Pages 中,无论何时你要访问一个数据库,你就要使用 SQL语言。因此,掌握好 SQL对 ASP编程是非常重要的。注意:你可以把“SQL”读作“sequel” ,也可以按单个字母的读音读作 SQL。 两种发音都是正确的,每种发音各有大量的支持者。在本书里,认为“SQL”读作“sequel”。通过这一章的学习,你将理解怎样用 SQL实现数据库查询,你将学会怎样使用这种查询从数据表中取出信息,最后,你将学会怎样设计和建立自己的数据库。注意:通过下面几章对 SQL的介绍,你将对 SQL有足够的了解,从而可以有效地使用 Active Sever Pages。但是,S
3、QL 是一种复杂的语言,本书不可能包括它的全部细节。要全面掌握SQL语言,你需要学习在 Microsoft SQL Sever 中使用 SQL。你可以到附近的书店去买一本 Microsoft SQL Sever 6.5。SQL介绍:本书假设你是在 SQL操作 Microsoft SQL Sever 的数据库。你也可以用 SQL操作许多其它类型的数据库。SQL 是操作数据库的标准语言。 (事实上,关于 SQL语言有一个专门的ANSI标准注意:不要在你的站点上试图用 Microsoft Access代替 Microsoft SQL Sever。SQL Sever可以同时服务于许多用户,如果你希望你
4、的站点有较高的访问率,MS Access是不能胜任的。在学习 SQL的细节之前,你需要理解它的两大特点。一个特点容易掌握,另一个掌握起来有点困难。第一个特点是所有 SQL数据库中的数据都存储在表中。一个表由行和列组成。例如,下面这个简单的表包括 name 和 e-mail address:Name Email Address.Bill Gates president Clinton Stephen Walther 这个表有两列(列也称为字段,域:Name 和 Email Address。有三行,每一行包含一组数据。一行中的数据组合在一起称为一条记录。无论何时你向表中添加新数据,你就添加了一条新
5、记录。一个数据表可以有几十个记录,也可以有几千甚至几十亿个记录。虽然你也许永远不需要存储十亿个 Email地址,但知道你能这样做总是好的,也许有一天你会有这样的需要。你的数据库很有可能包含几十个表,所有存储在你数据库中的信息都被存储在这些表中。当你考虑怎样把信息存储在数据库中时,你应该考虑怎样把它们存储在表中。SQL的第二个特点有些难于掌握。这种语言被设计为不允许你按照某种特定的顺序来取出记录,因为这样做会降低 SQL Sever取记录的效率。使用 SQL,你只能按查询条件来读取记录。当考虑如何从表中取出记录时,自然会想到按记录的位置读取它们。例如,也许你会尝试通过一个循环,逐个记录地扫描,来
6、选出特定的记录。在使用 SQL时,你必须训练自己,不要有这种思路。假如你想选出所有的名字是“Bill Gates”的记录,如果使用传统的编程语言,你也许会构造一个循环,逐个查看表中的记录,看名字域是否是“Bill Gates” 。这种选择记录的方法是可行的,但是效率不高。使用 SQL,你只要说, “选择所有名字域等于 Bill Gates的记录” ,SQL 就会为你选出所有符合条件的记录。SQL 会确定实现查询的最佳方法。建设你想取出表中的前十个记录。使用传统的编程语言,你可以做一个循环,取出前十个记录后结束循环。但使用标准的 SQL查询,这是不可能实现的。从 SQL的角度来说,在一个表中不存
7、在前十个记录这种概念。开始时,当你知道你不能用 SQL实现某些你感觉应该能实现的功能,你会受到挫折。你也许会以头撞墙甚至想写恶毒的信件给 SQL的设计者们。但后来你会认识到,SQL 的这个特点不仅不是个限制,反而是其长处。因为 SQL不根据位置来读取记录,它读取记录可以很快。综上所述,SQL 有两个特点:所有数据存储在表中,从 SQL的角度来说,表中的记录没有顺序。在下一节,你将学会怎样用 SQL从表中选择特殊的记录。使用 SQL从表中取记录。SQL的主要功能之一是实现数据库查询。如果你熟悉 Internet 引擎,那么你已经熟悉查询了。你使用查询来取得满足特定条件的信息。例如,如果你想找到有
8、 ASP信息的全部站点,你可以连接到 Yahoo!并执行一个对 Active Sever Pages的搜索。在你输入这个查询后,你会收到一个列表,表中包括所有其描述中包含搜索表达式的站点。多数 Internet 引擎允许逻辑查询。在逻辑查询中,你可以包括特殊的运算符如AND、OR 和 NOT,你使用这些运算符来选择特定的记录。例如,你可以用 AND来限制查询结果。如果你执行一个对 Active Sever Pages AND SQL 的搜索。你将得到其描述中同时包含 Active Sever Pages 和 SQL的记录。当你需要限制查询结果时,你可以使用 AND。如果你需要扩展查询的结果,你
9、可以使用逻辑操作符 OR。例如,如果你执行一个搜索,搜索所有的其描述中包含 Active Sever Pages OR SQL 的站点,你收到的列表中将包括所有其描述中同时包含两个表达式或其中任何一个表达式的站点。如果你想从搜索结果中排除特定的站点,你可以使用 NOT。例如,查询“Active Sever Pages ”AND NOT “SQL”将返回一个列表,列表中的站点包含 Active Sever Pages,但不包含 SQL。当必须排除特定的记录时,你可以使用 NOT。用 SQL执行的查询与用 Internet搜索引擎执行的搜索非常相似。 当你执行一个 SQL查询时,通过使用包括逻辑运
10、算符的查询条件,你可以得到一个记录列表。此时查询结果是来自一个或多个表。SQL查询的句法非常简单。假设有一个名为 email_table 的表,包含名字和地址两个字段,要得到 Bill Gates 的 e_mail地址,你可以使用下面的查询:SELECT email from email_table WHERE name=“Bill Gates“当这个查询执行时,就从名为 email_table的表中读取 Bill Gates的 e_mail 地址。这个简单的语句包括三部分: SELECT语句的第一部分指名要选取的列。在此例中,只有 email列被选取。当执行 时,只显示 email列的值 。
11、 SELECTT语句的第二部份指明要从哪个(些)表中查询数据。在此例中,要查询的表名为 email_table 。 最后,SELECT 语句的 WHERE子句指明要选择满足什么条件的记录。在此例中,查询条件为只有 name列的值为 Bill Gates 的记录才被选取。Bill Gates很有可能拥有不止一个 email地址。如果表中包含 Bill Gates的多个email地址。用上述的 SELECT语句可以读取他所有的 email地址。SELECT 语句从表中取出所有 name字段值为 Bill Gates 的记录的 email 字段的值。前面说过,查询可以在查询条件中包含逻辑运算符。假如
12、你想读取 Bill Gates 或Clinton总统的所有 email地址,你可以使用下面的查询语句:SELECT email FROM email_table WHERE name=“Bill Gates“ OR name=“president Clinton“此例中的查询条件比前一个复杂了一点。这个语句从表 email_table中选出所有 name列为 Bill Gates或 president Clinton的记录。如果表中含有 Bill Gates或 president Clinton的多个地址,所有的地址都被读取。SELECT语句的结构看起来很直观。如果你请一个朋友从一个表中为你选
13、择一组记录,你也许以非常相似的方式提出你的要求。在 SQL SELECT语句中,你“SELECT 特定的列FROM一个表 WHERE某些列满足一个特定的条件” 。下一节将介绍怎样执行 SQL查询来选取记录。这将帮助你熟悉用 SELECT语句从表中取数据的各种不同方法。使用 ISQL执行 SELECT查询当你安装 SQL Sever时,你同时安装了一个叫作 ISQL/w的应用程序。ISQL/w 允许你执行交互的 SQL查询。在把查询包括到你的 ASP网页中之前,用 ISQL/w对其进行测试是非常有用的。注意:在这本书的第一部份,你学习了怎样安装和配置 Microsoft SQL Sever 。如
14、果没有安装 SQL Sever或者 SQL Sever不能运行,请参阅第三章“安装和使用 SQL Sever”。选择任务上 SQL Sever程序组中的 ISQL_w以启动该程序。程序启动时,首先会出现一个对话框,要求输入服务器信息和登录信息(见图 10.1) 。在 Sever框中,输入你的 SQL服务器的名字。如果服务器正运行在本地计算机上,服务器名字就是你计算机的名字。在登录信息框中,输入一个登录帐号和密码或选择使用“可信连接” ,然后单击 Connect按钮。图 10。1注意:如果你将 SQL Sever配置为使用完整安全或混合安全,那么你可以使用可信连接。如果你使用标准安全,你则需要提
15、供用户帐号和密码。要了解更多信息,参见第三章。如果一切正常,在你单击连接按钮后会出现一个查询窗口,如图 10.2所示。 (如果有异常,请参考第三章) 图 10.2在执行查询之前,你需要选择数据库。安装 SQL Sever时你已为自己创建了一个数据库,SQL Sever 还有许多系统数据库,如 master,model,msdb,和 tempdb。方便的是,SQL Sever带有一个特殊的名为 pubs的例子数据库。库 pubs中包含供一个虚拟的出版商使用的各个表。文档中所有的例子程序都是针对这个库来设计的。本书中的许多例子也使用这个数据库。在查询窗口顶部的 DB下拉框中选择数据库 pubs,这
16、样你就选择了数据库。你所有的查询都将针对这个库中的各个表来执行。现在你可以执行你的第一个查询了。这真让人兴奋!你的第一个查询将针对一个名为 autrors的表,表中包含所有为某个虚拟出版商工作的作者的相关数据。单击查询窗口并输入以下的语句:SELECT phone FROM authors WHERE au_name=“Ringer“输入完成后,单击执行查询按钮(一个绿色三角形,看起来像 VCR播放键) 。单击此按钮后,任何出现在查询窗口中的语句均会被执行。查询窗口会自动变成结果显示窗口,你可以看到查询的结果(见图 10.3) 。你看到的查询结果也许与图 10.3所示的不同。在 SQL Sev
17、er的不同版本中,库 pubs中的数据会有所不同。对 SQL Sever 6.5来说,将会找到两条记录。结果显示窗口中应显示如下内容:phone.801 826_0752801 826_0752(2 row(s) affected)图 10.3你所执行的 SELECT语句从表 authors中取出所有名字为 Ringer的作者的电话号码。你通过在 WHERE子句中使用特殊的选择条件来限制查询的结果。你也可以忽略选择条件,从表中取出所有作者的电话号码。要做到这一点,单击 Query标签,返回到查询窗口,输入以下的 SELECT语句:SELECT Phone FROM authors这个查询执行后
18、,会取出表 authors中的所有电话号码(没有特定的顺序) 。如果表authors中包含一百个电话号码,会有一百个记录被取出,如果表中有十亿个电话号码,这十亿条记录都会被取出(这也许需要一些时间) 。表 authrs的字段包括姓,名字,电话号码,地址,城市,州和邮政编码。通过在SELECT语句的第一部份指定它们,你可以从表中取出任何一个字段。你可以在一个 SELECT语句中一次取出多个字段,比如:SELECT au_fname ,au_lname, phone FROM authors这个 SELECT语句执行后,将取出这三个列的所有值。下面是这个查询的结果的一个示例(为了节省纸张,只显示查
19、询结果的一部分,其余记录用省略号代替):au_fname au_lname phone .Johnson White 408 496_7223Marjorie Green 415 986_7020Cheryl Carson 415 548_7723Michael OLeary 408 286_2428 (23 row(s) affected)在 SELECT语句中,你需要列出多少个字段,你就可以列出多少。不要忘了把字段名用逗号隔开。你也可以用星号(*)从一个表中取出所有的字段。这里有一个使用星号的例子:SELECT * FROM authors这个 SELECT语句执行后,表中的所有字段的值都
20、被取出。你会发现你将在 SQL查询中频繁使用星号。技巧:你可以使用星号来查看一个表的所有列的名字。要做到这一点,只需要在执行完SELECT语句后看一下查询结果的列标题。操作多个表到现在为止,你只尝试了用一句 SQL查询从一个表中取出数据。你也可以用一个SELECT语句同时从多个表中取出数据,只需在 SELECT语句的 FROM从句中列出要从中取出数据的表名称即可:SELECT au_lname ,title FROM authors, titles 这个 SELECT语句执行时,同时从表 authors和表 titles中取出数据。从表 authors中取出所有的作者名字,从表 titles中
21、取出所有的书名。在 ISQL/w程序中执行这个查询,看一下查询结果。你会发现一些奇怪的出乎意料的情况:作者的名字并没有和它们所著的书相匹配,而是出现了作者名字和书名的所有可能的组合,这也许不是你所希望见到的。出了什么差错?问题在于你没有指明这两个表之间的关系。你没有通过任何方式告诉SQL如何把表和表关联在一起。由于不知道如何关联两个表,服务器只能简单地返回取自两个表中的记录的所有可能组合。要从两个表中选出有意义的记录组合,你需要通过建立两表中字段的关系来关联两个表。要做到这一点的途径之一是创建第三个表,专门用来描述另外两个表的字段之间的关系。表 authors有一个名为 au_id的字段,包含
22、有每个作者的唯一标识。表 titles有一个名为 title_id的字段,包含每个书名的唯一标识。如果你能在字段 au_id和字段title_id 之间建立一个关系,你就可以关联这两个表。数据库 pubs中有一个名为titleauthor的表,正是用来完成这个工作。表中的每个记录包括两个字段,用来把表titles和表 authors关联在一起。下面的 SELECT语句使用了这三个表以得到正确的结果:SELECT au_name,title FROM authors,titles,titleauthor WHERE authors.au_id=titleauthor.au_idAND title
23、s.title_id=titleauthor.title_id 当这个 SELECT语句执行时,每个作者都将与正确的书名相匹配。表 titleauthor指明了表 authors和表 titles的关系,它通过包含分别来自两个表的各一个字段实现这一点。第三个表的唯一目的是在另外两个表的字段之间建立关系。它本身不包含任何附加数据。注意在这个例子中字段名是如何书写的。为了区别表 authors和表 titles中相同的字段名 au_id,每个字段名前面都加上了表名前缀和一个句号。名为 author.au_id 的字段属于表 authors,名为 titleauthor.au_id的字段属于表 ti
24、tleauthor,两者不会混淆。通过使用第三个表,你可以在两个表的字段之间建立各种类型的关系。例如,一个作者也许写了许多不同的书,或者一本书也许由许多不同的作者共同完成。当两个表的字段之间有这种“多对多”的关系时,你需要使用第三个表来指明这种关系。但是,在许多情况下,两个表之间的关系并不复杂。比如你需要指明表 titles和表publishers之间的关系。因为一个书名不可能与多个出版商相匹配,你不需要通过第三个表来指明这两个表之间的关系。要指明表 titles和表 publishers之间的关系,你只要让这两个表有一个公共的字段就可以了。在数据库 pubs中,表 titles和表 publ
25、ishers都有一个名为 pub_id的字段。如果你想得到书名及其出版商的一个列表,你可以使用如下的语句:SELECT title,pub_name FROM titles,publishersWHERE titles.pub_id=publishers.pub_id当然,如果一本书是由两个出版商联合出版的,那么你需要第三个表来代表这种关系。通常,当你予先知道两个表的字段间存在“多对多”关系时,就使用第三个表来关联这两个表。反之,如果两个表的字段间只有“一对一”或“一对多”关系,你可以使用公共字段来关联它门。操作字段通常,当你从一个表中取出字段值时,该值与创建该表时所定义的字段名联系在一起。如
26、果你从表 authors中选择所有的作者名字,所有的值将会与字段名 au_lname相联系。但是在某些情况下,你需要对字段名进行操作。在 SELECT语句中,你可以在缺省字段名后面仅跟一个新名字来取代它。例如,可以用一个更直观易读的名字 Author Last Name来代替字段名 au_lname:SELECT au_lname “Author Last Name“ FROM authors当这个 SELECT语句执行时,来自字段 au_lname的值会与“Author Last Name”相联系。查询结果可能是这样:Author Last Name . WhiteGreenCarsonOL
27、earyStraight (23 row(s) affected)注意字段标题不再是 au_lname,而是被 Author Last Name所取代。你也可以通过执行运算,来操作从一个表返回的字段值。例如,如果你想把表 titles中的所有书的价格加倍,你可以使用下面的 SELECT语句:SELECT price*2 FROM titles 当这个查询执行时,每本书的价格从表中取出时都会加倍。但是,通过这种途径操作字段不会改变存储在表中的书价。对字段的运算只会影响 SELECT语句的输出,而不会影响表中的数据。为了同时显示书的原始价格和涨价后的新价格,你可以使用下面的查询:SELECT pr
28、ice “Original price“, price*2 “New price“ FROM titles当数据从表 titles中取出时,原始价格显示在标题 Original price下面,加倍后的价格显示在标题 New price下面。结果可能是这样:original price new price.19.99 39.9811.95 23.90 2.99 5.9819.99 39.98(18 row(s) affected)你可以使用大多数标准的数学运算符来操作字段值,如加(+) ,减(-) ,乘(*)和除(/) 。你也可以一次对多个字段进行运算,例如:SELECT price*ytd_
29、sales “total revenue“ FROM titles在这个例子中,通过把价格与销售量相乘,计算出了每种书的总销售额。这个 SELECT语句的结果将是这样的:total revenue.81,859,0546,318,2055,978,7881,859,0540,619,68(18 row(s) affected)最后,你还可以使用连接运算符(它看起来像个加号)来连接两个字符型字段:SELECT au_fname+“ “+au_lname “author name“ FROM authors在这个例子中,你把字段 au_fname和字段 au_lname粘贴在一起,中间用一个逗号 隔开,并把查询结果的标题指定为 author name。这个语句的执行结果将是这样的:author names