﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客- i have only belief--wjw-随笔分类-数据库设计</title><link>http://www.cnitblog.com/wjw/category/3788.html</link><description>             生活是精彩还是黑暗，完全取决于自己-------I  BELIEF。</description><language>zh-cn</language><lastBuildDate>Wed, 28 Sep 2011 15:03:20 GMT</lastBuildDate><pubDate>Wed, 28 Sep 2011 15:03:20 GMT</pubDate><ttl>60</ttl><item><title>整合所有数据库 MySQL将构建'空中数据库'</title><link>http://www.cnitblog.com/wjw/archive/2006/11/12/19090.html</link><dc:creator>i have only belief</dc:creator><author>i have only belief</author><pubDate>Sun, 12 Nov 2006 01:50:00 GMT</pubDate><guid>http://www.cnitblog.com/wjw/archive/2006/11/12/19090.html</guid><wfw:comment>http://www.cnitblog.com/wjw/comments/19090.html</wfw:comment><comments>http://www.cnitblog.com/wjw/archive/2006/11/12/19090.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wjw/comments/commentRss/19090.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wjw/services/trackbacks/19090.html</trackback:ping><description><![CDATA[
		<strong>         当地时间本周四,MySQL AB公司首席执行官Marten Mickos对外宣称,该公司希望启动一个全球性项目－－构建一个巨型的分布式数据仓库,存储世界上结构型数据库中存储的所有数据.<br /></strong>Marten Mickos在此次的Web 2.0峰会上说道,虽然像Google这样的搜索引擎为人们提供基于互联网的非结构型数据访问,但是该“空中数据库”将为应用程序开发者和互联网企业提供结构型数据.<br /><br />Mickos还说,该数据仓库对数据库的访问将类似于eBay公司的Skype对于互联网电话(The data repository would be to database access what eBay Inc.'s Skype is to Internet telephony),并且它将为数据分析和恢复创建下一代OLAP(联机分析处理).<br /><br />Mickos说道,这个项目设法为数据应用开源模型,因此世界范围的开发者们可以共享和聚合数据,然后数据将成为平台.比如,用户可以访问世界上所有包含气象信息的结构型数据库.<br /><br />另外,这可能需要去构建一个“SQL Server的DNS”,解决路由障碍,从而使数据对于其他用户可访问.当然,在此同时还需要数据所有者希望将他们的数据公开.<br /><br />但是,最重要的一步就是召集一个研究者和志愿者社区来开发这个项目.该数据库并不会异常庞大,且以P2P模式运行.有兴趣了解关于这个项目的更新信息的用户可以访问:www.mysqlcamp.org<br /><img src ="http://www.cnitblog.com/wjw/aggbug/19090.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wjw/" target="_blank">i have only belief</a> 2006-11-12 09:50 <a href="http://www.cnitblog.com/wjw/archive/2006/11/12/19090.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何在MySQL中获得更好的全文搜索结果 </title><link>http://www.cnitblog.com/wjw/archive/2006/05/17/10633.html</link><dc:creator>i have only belief</dc:creator><author>i have only belief</author><pubDate>Wed, 17 May 2006 00:31:00 GMT</pubDate><guid>http://www.cnitblog.com/wjw/archive/2006/05/17/10633.html</guid><wfw:comment>http://www.cnitblog.com/wjw/comments/10633.html</wfw:comment><comments>http://www.cnitblog.com/wjw/archive/2006/05/17/10633.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wjw/comments/commentRss/10633.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wjw/services/trackbacks/10633.html</trackback:ping><description><![CDATA[
		<table cellspacing="0" cellpadding="4" width="95%" border="0">
				<p>
				</p>
				<tbody>
						<tr>
								<td class="textblack">
										<b>如何在MySQL中获得更好的全文搜索结果</b>
								</td>
						</tr>
						<tr>
								<td class="textblack">
										<br />
								</td>
						</tr>
						<tr>
								<td class="textgray">
										<p>
										</p>
										<p align="left">很多互联网应用程序都提供了全文搜索功能，用户可以使用一个词或者词语片断作为查询项目来定位匹配的记录。在后台，这些程序使用在一个SELECT查询中的LIKE语句来执行这种查询，尽管这种方法可行，但对于全文查找而言，这是一种效率极端低下的方法，尤其在处理大量数据的时候。</p>
										<table cellspacing="0" cellpadding="0" width="0" align="right" border="0">
												<tbody>
														<tr>
																<td align="middle">
																</td>
														</tr>
														<tr>
																<td>
																		<!--start banner ad-->
																		<!--ba-->
																		<script language="JavaScript1.1" src="http://ad.cn.doubleclick.net/adj/messagingplus.zdnet.com.cn/developer/database;sz=1x1;ord=200546964?">
																		</script>
																		<noscript>
																				<a href="http://ad.cn.doubleclick.net/jump/messagingplus.zdnet.com.cn/developer/database;sz=1x1;ord=200546964?">
																						<img src="http://ad.cn.doubleclick.net/ad/messagingplus.zdnet.com.cn/developer/database;sz=1x1;ord=200546964?" border="0" />
																				</a>
																		</noscript>
																		<!--end banner ad-->
																</td>
														</tr>
												</tbody>
										</table>
										<p>MySQL针对这一问题提供了一种基于内建的全文查找方式的解决方案。在此，开发者只需要简单地标记出需要全文查找的字段，然后使用特殊的MySQL方法在那些字段运行搜索，这不仅仅提高了性能和效率（因为MySQL对这些字段做了索引来优化搜索），而且实现了更高质量的搜索，因为MySQL使用自然语言来智能地对结果评级，以去掉不相关的项目。</p>
										<p>这篇文章将向您讲述在MySQL中如何进行全文搜索。</p>
										<p>
												<strong>1</strong>
												<strong>、设置基本表格</strong>
										</p>
										<p>从创建例子表格开始，使用以下的SQL命令：</p>
										<p>mysql&gt; CREATE TABLE reviews (id INT(5) PRIMARY KEY NOT NULL AUTO_INCREMENT, data TEXT);</p>
										<p>以上命令创建了一个简单的音乐专集资料库（主要是整段的文字），然后向这个表格中添加一些记录：</p>
										<p>mysql&gt; INSERT INTO `reviews` (`id`, `data`) VALUES</p>
										<p>(1, 'Gingerboy has a new single out called Throwing Rocks. It\'s great!');</p>
										<p>mysql&gt; INSERT INTO `reviews` (`id`, `data`) VALUES </p>
										<p>(2, 'Hello all, I really like the new Madonna single. </p>
										<p>One of the hottest tracks currently playing...I\'ve been listening to it all day');</p>
										<p>mysql&gt; INSERT INTO `reviews` (`id`, `data`)</p>
										<p>VALUES (3, 'Have you heard the new band Hotter Than Hell?</p>
										<p>They have five members and they burn their instruments when they play in concerts. </p>
										<p>These guys totally rock! Like, awesome, dude!');</p>
										<p>验证数据的正确录入：</p>
										<p>mysql&gt; SELECT * FROM reviews;</p>
										<p>+----+--------------------------------------------+</p>
										<p>| id | data                                       |</p>
										<p>+----+--------------------------------------------+</p>
										<p>|  1 | Gingerboy has a new single out called ...  |</p>
										<p>|  2 | Hello all, I really like the new Madon ... |</p>
										<p>|  3 | Have you heard the new band Hotter Than... |</p>
										<p>+----+--------------------------------------------+</p>
										<p>3 rows in set (0.00 sec)</p>
										<p>
												<strong>2</strong>
												<strong>、定义全文搜索字段</strong>
										</p>
										<p>接下来，定义您要作为全文搜索索引的字段</p>
										<p>mysql&gt; ALTER TABLE reviews ADD FULLTEXT INDEX (data);</p>
										<p>Query OK, 3 rows affected (0.21 sec)</p>
										<p>Records: 3  Duplicates: 0  Warnings: 0</p>
										<p>使用SHOW INDEXES命令来检查索引已经被添加了：</p>
										<p>mysql&gt; SHOW INDEXES FROM reviews;</p>
										<p>+---------+---------------+--------+------+------------+---------+</p>
										<p>| Table   | Column_name   | Packed | Null | Index_type | Comment |</p>
										<p>----------+---------------+--------+------+------------+---------+</p>
										<p>| reviews |  id           | NULL   |      | BTREE      |         |</p>
										<p>| reviews |  data         | NULL   | YES  | FULLTEXT   |         |</p>
										<p>+---------+---------------+--------+------+------------+---------+</p>
										<p>2 rows in set (0.01 sec)</p>
										<p>
												<strong>3</strong>
												<strong>、运行全文搜索</strong>
										</p>
										<p>当您拥有了数据和索引，就可以使用MySQL的全文搜索了，最简单的全文搜索方式是带有MATCH...AGAINST语句的SELECT查询，以下是一个简单的例子，可以来查找含有单词“single”的记录：</p>
										<p>mysql&gt; SELECT id FROM reviews WHERE MATCH (data) AGAINST ('single');+----+</p>
										<p>| id |</p>
										<p>+----+</p>
										<p>|  1 |</p>
										<p>|  2 |</p>
										<p>+----+</p>
										<p>2 rows in set (0.00 sec)</p>
										<p>在此，MATCH()将作为参数传递给它的字段中的文字与传递给AGAINST()的参数进行比较，如果有匹配的，那就按照正常的方式返回。注意您可以传递不止一个字段用MATCH()来查看­－只需用逗号来分割字段列表。</p>
										<p>当MySQL收到了一个全文搜索的请求，它就在内部对每个记录进行评分，不匹配的记录得分为零，而“更相关”的记录会得到比“不太相关”的记录相对更高的分数。相关性是由MySQL的一系列区分标准来决定的，查看MySQL的用户手册可以得到更多的信息。</p>
										<p>想看到每个记录的评分如何，只需要返回MATCH()方法作为结果集的一部分，如下所示：</p>
										<p>mysql&gt; SELECT id, MATCH (data) AGAINST ('rock') FROM reviews;</p>
										<p>+----+-------------------------------+</p>
										<p>| id | MATCH (data) AGAINST ('rock') |</p>
										<p>+----+-------------------------------+</p>
										<p>|  1 |                             0 |</p>
										<p>|  2 |                             0 |</p>
										<p>|  3 |               1.3862514533815 |</p>
										<p>+----+-------------------------------+</p>
										<p>3 rows in set (0.00 sec)</p>
										<p>
												<strong>4</strong>
												<strong>、使用逻辑搜索修饰符（Boolean search modifiers</strong>
												<strong>）</strong>
										</p>
										<p>您还可以使用逻辑搜索修饰符来进行更精确的搜索，这通过在AGAINST语句中添加特殊的IN BOOLEAN MODE修饰符来实现，在以下的例子中，将查找含有单词“single”但是没有“Madonna”的记录：</p>
										<p>mysql&gt; SELECT id FROM reviews WHERE MATCH (data) AGAINST ('+single -madonna' IN BOOLEAN MODE);</p>
										<p>+----+</p>
										<p>| id |</p>
										<p>+----+</p>
										<p>|  1 |</p>
										<p>+----+</p>
										<p>1 row in set (0.00 sec)</p>
										<p>这一搜索特性通常用于搜索单词片断（而不是完整的词语），这可以通过在IN BOOLEAN MODE语句中的*（星号）操作符来实现，以下的例子展示了如何查找单词中含有“hot”的记录：</p>
										<p>mysql&gt; SELECT id FROM reviews WHERE MATCH (data) AGAINST ('hot*' IN BOOLEAN MODE);+----+</p>
										<p>| id |</p>
										<p>+----+</p>
										<p>|  3 |</p>
										<p>|  2 |</p>
										<p>+----+</p>
										<p>2 rows in set (0.00 sec)</p>
										<p>您还可以使用这种方法来查找至少一个传递到AGAINST的参数中，以下的例子查找了至少包含单词“hell”和“rocks”中的一个的记录：</p>
										<p>mysql&gt; SELECT id FROM reviews WHERE MATCH (data) AGAINST ('hell rocks' IN BOOLEAN MODE);</p>
										<p>+----+</p>
										<p>| id |</p>
										<p>+----+</p>
										<p>|  1 |</p>
										<p>|  3 |</p>
										<p>+----+</p>
										<p>2 rows in set (0.00 sec)</p>
										<p>以上的这些例子演示了相对于传统的SELECT...LIKE语句，进行全文搜索的更有效的方法，当您下一次需要编写MySQL数据库搜索界面的时候，您可以尝试这一方法。</p>
								</td>
						</tr>
						<p>
						</p>
				</tbody>
		</table>
<img src ="http://www.cnitblog.com/wjw/aggbug/10633.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wjw/" target="_blank">i have only belief</a> 2006-05-17 08:31 <a href="http://www.cnitblog.com/wjw/archive/2006/05/17/10633.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>选择MySQL还是SQL Server</title><link>http://www.cnitblog.com/wjw/archive/2006/05/17/10632.html</link><dc:creator>i have only belief</dc:creator><author>i have only belief</author><pubDate>Wed, 17 May 2006 00:30:00 GMT</pubDate><guid>http://www.cnitblog.com/wjw/archive/2006/05/17/10632.html</guid><wfw:comment>http://www.cnitblog.com/wjw/comments/10632.html</wfw:comment><comments>http://www.cnitblog.com/wjw/archive/2006/05/17/10632.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wjw/comments/commentRss/10632.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wjw/services/trackbacks/10632.html</trackback:ping><description><![CDATA[
		<table cellspacing="0" cellpadding="4" width="95%" border="0">
				<p>
				</p>
				<tbody>
						<tr>
								<td class="textblack">
										<b>选择MySQL还是SQL Server</b>
								</td>
						</tr>
						<tr>
								<td class="textblack">
								</td>
						</tr>
						<tr>
								<td class="textgray">
										<p>对于程序开发人员而言，目前使用最流行的两种后台数据库即为<a href="http://www.mysql.com/" target="_target"><font color="#002c99">MySQL</font></a> and <a href="http://www.microsoft.com/sql/default.asp" target="_target"><font color="#002c99">SQL Server</font></a>。这两者最基本的相似之处在于数据存储和属于查询系统。你可以使用SQL来访问这两种数据库的数据，因为它们都支持ANSI-SQL。还有，这两种数据库系统都支持二进制关键词和关键索引，这就大大地加快了查询速度。同时，二者也都提供支持XML的各种格式。 </p>
										<table cellspacing="0" cellpadding="0" width="0" align="right" border="0">
												<tbody>
														<tr>
																<td align="middle">
																</td>
														</tr>
														<tr>
																<td>
																		<!--start banner ad-->
																		<!--ba-->
																		<script language="JavaScript1.1" src="http://ad.cn.doubleclick.net/adj/messagingplus.zdnet.com.cn/developer/database;sz=1x1;ord=1585386653?">
																		</script>
																		<noscript>
																				<a href="http://ad.cn.doubleclick.net/jump/messagingplus.zdnet.com.cn/developer/database;sz=1x1;ord=1585386653?">
																						<img src="http://ad.cn.doubleclick.net/ad/messagingplus.zdnet.com.cn/developer/database;sz=1x1;ord=1585386653?" border="0" />
																				</a>
																		</noscript>
																		<!--end banner ad-->
																</td>
														</tr>
												</tbody>
										</table>
										<p>除了在显而易见的软件价格上的区别之外，这两个产品还有什么明显的区别吗？在这二者之间你是如何选择的？让我们看看这两个产品的主要的不同之处，包括发行费用，性能以及它们的安全性。</p>
										<h5>根本的区别是它们遵循的基本原则</h5>
										<p>二者所遵循的基本原则是它们的主要区别：开放vs保守。SQL服务器的狭隘的，保守的存储引擎与MySQL服务器的可扩展，开放的存储引擎绝然不同。虽然你可以使用SQL服务器的Sybase引擎，但MySQL能够提供更多种的选择，如<a href="http://www.mysql.com/doc/en/MyISAM.html" target="_target"><font color="#002c99">MyISAM</font></a>, <a href="http://www.mysql.com/doc/en/HEAP.html" target="_target"><font color="#002c99">Heap</font></a>, <a href="http://www.innodb.com/" target="_target"><font color="#002c99">InnoDB</font></a>, and <a href="http://www.sleepycat.com/" target="_target"><font color="#002c99">Berkeley DB</font></a>。MySQL不完全支持陌生的关键词，所以它比SQL服务器要少一些相关的数据库。同时，MySQL也缺乏一些存储程序的功能，比如MyISAM引擎联支持交换功能。</p>
										<h5>发行费用：MySQL不全是免费，但很便宜</h5>
										<p>当提及发行的费用，这两个产品采用两种绝然不同的决策。对于SQL服务器，获取一个免费的开发费用最常的方式是购买微软的Office或者Visual Studio的费用。但是，如果你想用于商业产品的开发，你必须还要购买<a href="http://mysimon.search.com.com/search?q=SQL+Server+2000+Std+Edition&amp;c=root&amp;Search.x=44&amp;Search.y=7" target="_target"><font color="#002c99">SQL Server Standard Edition</font></a>。学校或非赢利的企业可以不考虑这一附加的费用。</p>
										<h5>性能：先进的MySQL <b>   </b></h5>
										<p>纯粹就性能而言，MySQL是相当出色的，因为它包含一个缺省桌面格式MyISAM。MyISAM 数据库与磁盘非常地兼容而不占用过多的CPU和内存。MySQL可以运行于Windows系统而不会发生冲突，在UNIX或类似UNIX系统上运行则更好。你还可以通过使用64位处理器来获取额外的一些性能。因为MySQL在内部里很多时候都使用64位的整数处理。Yahoo!商业网站就使用MySQL作为后台数据库。</p>
										<p>当提及软件的性能，SQL服务器的稳定性要比它的竞争对手强很多。但是，这些特性也要付出代价的。比如，必须增加额外复杂操作，磁盘存储，内存损耗等等。如果你的硬件和软件不能充分支持SQL服务器，我建议你最好选择其他如DBMS数据库，因为这样你会得到更好的结果。</p>
										<p>这两者数据库都能够在.NET或J2EE下运行正常，同样，都能够利用RAID。</p>
								</td>
						</tr>
						<p>
						</p>
				</tbody>
		</table>
<img src ="http://www.cnitblog.com/wjw/aggbug/10632.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wjw/" target="_blank">i have only belief</a> 2006-05-17 08:30 <a href="http://www.cnitblog.com/wjw/archive/2006/05/17/10632.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SQL 常用语句超详细介绍</title><link>http://www.cnitblog.com/wjw/archive/2006/05/13/10452.html</link><dc:creator>i have only belief</dc:creator><author>i have only belief</author><pubDate>Sat, 13 May 2006 13:21:00 GMT</pubDate><guid>http://www.cnitblog.com/wjw/archive/2006/05/13/10452.html</guid><wfw:comment>http://www.cnitblog.com/wjw/comments/10452.html</wfw:comment><comments>http://www.cnitblog.com/wjw/archive/2006/05/13/10452.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/wjw/comments/commentRss/10452.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wjw/services/trackbacks/10452.html</trackback:ping><description><![CDATA[
		<p>
				<span style="FONT-SIZE: 12px">
						<font color="red">
								<b>Select语句</b>
						</font>
						<br />
						<br />SQL 里面最常用的命令是 SELECT 语句，用于检索数据。语法是： <br /><br />SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]<br />    * | expression [ AS output_name ] [, ...]<br />    [ INTO [ TEMPORARY | TEMP ] [ TABLE ] new_table ]<br />    [ FROM from_item [, ...] ]<br />    [ WHERE condition ]<br />    [ GROUP BY expression [, ...] ]<br />    [ HAVING condition [, ...] ]<br />    [ { UNION | INTERSECT | EXCEPT [ ALL ] } select ]<br />    [ ORDER BY expression [ ASC | DESC | USING operator ] [, ...] ]<br />    [ FOR UPDATE [ OF class_name [, ...] ] ]<br />    [ LIMIT { count | ALL } [ { OFFSET | , } start ]]<br />     <br /><br />现在我们将通过不同的例子演示 SELECT 语句复杂的语法。用于这些例子的表在 供应商和部件数据库 里定义。 <br /><br />1.4.1.1. 简单的 Select<br />这里是一些使用 SELECT 语句的简单例子： <br /><br />Example 1-4. 带有条件的简单查询<br /><br />要从表 PART 里面把字段 PRICE 大于 10 的所有记录找出来， 我们写出下面查询： <br /><br />SELECT * FROM PART<br />    WHERE PRICE &gt; 10;<br />        <br />然后得到表： <br />PNO |  PNAME  |  PRICE<br />-----+---------+--------<br />  3   |     Bolt   |   15<br />  4   |   Cam    |   25<br />        <br /><br />在 SELECT语句里使用 "*" 将检索出表中的所有属性。 如果我们只希望从表 PART 中检索出属性 PNAME 和 PRICE， 我们使用下面的语句： <br /><br />SELECT PNAME, PRICE <br />    FROM PART<br />    WHERE PRICE &gt; 10;<br />        <br />这回我们的结果是： <br />                      PNAME  |  PRICE<br />                     --------+--------<br />                      Bolt    |   15<br />                      Cam   |   25<br />        <br />请注意 SQL 的 SELECT 语句对应关系演算里面的 "projection" （映射），而不是 "selection"（选择）（参阅 关系演算 获取详细信息）。 <br /><br />WHERE 子句里的条件也可以用关键字 OR，AND，和 NOT 逻辑地连接起来： <br /><br />SELECT PNAME, PRICE <br />    FROM PART<br />    WHERE PNAME = 'Bolt' AND<br />         (PRICE = 0 OR PRICE &lt;= 15);<br />        <br />这样将生成下面的结果： <br />PNAME  |  PRICE<br />   --------+--------<br />    Bolt    |   15<br />        <br /><br />目标列表和 WHERE 子句里可以使用算术操作。例如， 如果我们想知道如果我们买两个部件的话要多少钱， 我们可以用下面的查询： <br /><br />SELECT PNAME, PRICE * 2 AS DOUBLE<br />    FROM PART<br />    WHERE PRICE * 2 &lt; 50;<br />        <br />这样我们得到： <br />PNAME  |  DOUBLE<br />--------+---------<br />Screw  |    20<br />   Nut    |    16<br />    Bolt   |    30<br />        <br />请注意在关键字 AS 后面的 DOUBLE 是第二个列的新名字。 这个技巧可以用于目标列表里的每个元素， 给它们赋予一个在结果列中显示的新的标题。 这个新的标题通常称为别名。这个别名不能在该查询的其他地方使用。 <br /><br /><br />1.4.1.2. Joins（连接）<br />下面的例子显示了 SQL 里是如何实现连接的。 <br /><br />要在共同的属性上连接三个表 SUPPLIER，PART 和 SELLS， 我们通常使用下面的语句： <br /><br />SELECT S.SNAME, P.PNAME<br />    FROM SUPPLIER S, PART P, SELLS SE<br />    WHERE S.SNO = SE.SNO AND<br />          P.PNO = SE.PNO;<br />      <br />而我们得到的结果是： <br />SNAME | PNAME<br />-------+-------<br />Smith | Screw<br />Smith | Nut<br />Jones | Cam<br />Adams | Screw<br />Adams | Bolt<br />  Blake | Nut<br />  Blake | Bolt<br />  Blake | Cam<br />      <br /><br />在 FROM 子句里，我们为每个关系使用了一个别名， 因为在这些关系间有着公共的命名属性（SNO 和 PNO）。 现在我们可以区分不同表的公共命名属性， 只需要简单的用每个关系的别名加上个点做前缀就行了。 联合是用与 一个内部联接 里显示的同样的方法计算的。首先算出笛卡儿积 SUPPLIER × PART × SELLS 。然后选出那些满足 WHERE 子句里给出的条件的记录 （也就是说，公共命名属性的值必须相等）。 最后我们映射出除 S.SNAME 和 P.PNAME 外的所有属性。 <br /><br />另外一个进行连接的方法是使用下面这样的 SQL JOIN 语法： <br /><br />select sname, pname from supplier<br />        JOIN sells USING (sno)<br />        JOIN part USING (pno);<br />        <br />giving again: <br />sname | pname<br />  -------+-------<br />  Smith | Screw<br />Adams | Screw<br />  Smith | Nut<br />  Blake | Nut<br />Adams | Bolt<br />  Blake | Bolt<br />Jones | Cam<br />  Blake | Cam<br />(8 rows) <br />         <br /><br />一个用 JOIN 语法创建的连接表，是一个出现在 FROM 子句里的， 在任何 WHERE，GROUP BY 或 HAVING 子句之前的表引用列表项． 其它表引用，包括表名字或者其它 JOIN 子句，如果用逗号分隔的话， 可以包含在 FROM 子句里． 连接生成的表逻辑上和任何其它在 FROM 子句里列出的表都一样． <br /><br />SQL JOIN 有两种主要类型，CROSS JOIN (无条件连接) 和条件连接．条件连接还可以根据声明的 连接条件(ON，USING，或 NATURAL)和它 应用的方式(INNER 或 OUTER 连接)进一步细分． <br /><br /><br />连接类型<br /><br />CROSS JOIN <br />{ T1 } CROSS JOIN { T2 }<br /><br />一个交叉连接（cross join）接收两个分别有 N 行和 M 行 的表 T1 和 T2，然后返回一个包含交叉乘积 NxM 条记录的 连接表． 对于 T1 的每行 R1，T2 的每行 R2 都与 R1 连接生成 连接的表行 JR，JR 包含所有 R1 和 R2 的字段． CROSS JOIN 实际上就是一个 INNER JOIN ON TRUE． <br /><br />条件 JOIN <br />{ T1 } [ NATURAL ] [ INNER | { LEFT | RIGHT | FULL } [ OUTER ] ] JOIN { T2 } { ON search condition | USING ( join column list ) }<br /><br />一个条件 JOIN 必须通过提供一个(并且只能有一个) NATURAL，ON，或者 USING 这样的关键字来声明它的 连接条件． ON 子句 接受一个 search condition， 它与一个 WHERE 子句相同．USING 子句接受一个用逗号分隔的 字段名列表，连接表中必须都有这些字段， 并且用那些字段连接这些表，生成的连接表包含每个共有字段 和两个表的所有其它字段． NATURAL 是 USING 子句的缩写，它列出两个表中所有公共 的字段名字．使用 USING 和 NATURAL 的副作用是 每个连接的字段都只有一份拷贝出现在结果表中 (与前面定义的关系演算的 JOIN 相比较)． <br /><br /><br />[ INNER ] JOIN <br /><br />对于 T1 的每行 R1，连接成的表在 T2 里都有一行满 足与 R1 一起的连接条件． <br /><br />对于所有 JOIN 而言，INNER 和 OUTER 都是可选的．INNER 是缺省． LEFT，RIGHT，和 FULL 只用于 OUTER JOIN． <br /><br />LEFT [ OUTER ] JOIN <br /><br />首先，执行一次 INNER JOIN． 然后，如果 T1 里有一行对任何 T2 的行都不满足 连接条件，那么返回一个连接行，该行的 T2 的字段 为 null． <br /><br />小技巧: 连接成的表无条件地包含 T1 里的所有行． <br /><br />RIGHT [ OUTER ] JOIN <br /><br />首先，执行一次 INNER JOIN． 然后，如果 T2 里有一行对任何 T1 的行都不满足 连接条件，那么返回一个连接行，该行的 T1 的字段 为 null． <br /><br />小技巧: 连接成的表无条件地包含 T2 里的所有行． <br /><br />FULL [ OUTER ] JOIN <br /><br />首先，执行一次 INNER JOIN． 然后，如果 T1 里有一行对任何 T2 的行都不满足 连接条件，那么返回一个连接行，该行的 T1 的字段 为 null． 同样，如果 T2 里有一行对任何 T1 的行都不满足 连接条件，那么返回一个连接行，该行的 T2 的字段 为 null． <br /><br />小技巧: 连接成的表无条件地拥有来自 T1 的每 一行和来自 T2 的每一行． <br /><br />所有 类型的 JOIN 都可以链接在一起或者嵌套在一起， 这时 T1 和 T2 都可以是连接生成的表．我们可以使用圆括弧控制 JOIN 的顺序，如果我们不主动控制，那么连接顺序是从左到右． <br /><br />1.4.1.3. 聚集操作符<br />SQL 提供以一些聚集操作符（如， AVG，COUNT，SUM，MIN，MAX），这些聚集操作符以一个表达式为参数。 只要是满足 WHERE 子句的行，就会计算这个表达式， 然后聚集操作符对这个输入数值的集合进行计算． 通常，一个聚集对整个 SELECT 语句计算的结果是 生成一个结果．但如果在一个查询里面声明了分组， 那么数据库将对每个组进行一次独立的计算，并且 聚集结果是按照各个组出现的(见下节)． <br /><br />Example 1-5. 聚集<br /><br />果我们想知道表 PART 里面所有部件的平均价格，我们可以使用下面查询： <br /><br />SELECT AVG(PRICE) AS AVG_PRICE<br />    FROM PART;<br />        <br /><br />结果是： <br /><br />AVG_PRICE<br />-----------<br />   14.5<br />        <br /><br />如果我们想知道在表 PART 里面存储了多少部件，我们可以使用语句： <br /><br />SELECT COUNT(PNO)<br />    FROM PART;<br />        <br />得到： <br />COUNT<br />-------<br />   4<br />        <br /><br /><br />1.4.1.4. 分组聚集<br />SQL 允许我们把一个表里面的记录分成组。 然后上面描述的聚集操作符可以应用于这些组上 （也就是说，聚集操作符的值不再是对所有声明的列的值进行操作， 而是对一个组的所有值进行操作。这样聚集函数是为每个组独立地进行计算的。） <br /><br />对记录的分组是通过关键字 GROUP BY 实现的，GROUP BY 后面跟着一个定义组的构成的属性列表。 如果我们使用语句 GROUP BY A1, &amp;tdot;, Ak 我们就把关系分成了组，这样当且仅当两条记录在所有属性 A1, &amp;tdot;, Ak 上达成一致，它们才是同一组的。 <br /><br />Example 1-6. 聚集<br /><br />如果我们想知道每个供应商销售多少个部件，我们可以这样写查询： <br /><br />SELECT S.SNO, S.SNAME, COUNT(SE.PNO)<br />    FROM SUPPLIER S, SELLS SE<br />    WHERE S.SNO = SE.SNO<br />    GROUP BY S.SNO, S.SNAME;<br />        <br />得到： <br />SNO | SNAME | COUNT<br />-----+-------+-------<br />  1  | Smith |   2<br />  2  | Jones |   1<br />  3  | Adams |   2<br />  4  | Blake |   3<br />        <br /><br />然后我们看一看发生了什么事情。首先生成表 SUPPLIER 和 SELLS 的连接： <br /><br />S.SNO | S.SNAME | SE.PNO<br />-----+---------+--------<br />   1   |  Smith  |   1<br />   1   |  Smith  |   2<br />   2   |  Jones  |   4<br />   3   |  Adams  |   1<br />   3   |  Adams  |   3<br />   4   |  Blake  |   2<br />   4   |  Blake  |   3<br />   4   |  Blake  |   4<br />        <br /><br />然后我们把那些属性 S.SNO 和 S.SNAME 相同的记录放在组中： <br /><br />S.SNO | S.SNAME | SE.PNO<br />-------+---------+--------<br />     1   |  Smith  |   1<br />                        |   2<br />--------------------------<br />     2   |  Jones  |   4<br />--------------------------<br />   3   |  Adams  |   1<br />                        |   3<br />--------------------------<br />   4   |  Blake  |   2<br />                      |   3<br />                      |   4<br />        <br /><br />在我们的例子里，我们有四个组并且现在我们可以对每个组应用聚集操作符 COUNT，生成上面给出的查询的最终结果。 <br /><br /><br />请注意如果要让一个使用 GROUP BY 和聚集操作符的查询的结果有意义， 那么用于分组的属性也必须出现在目标列表中。 所有没有在 GROUP BY 子句里面出现的属性都只能通过使用聚集函数来选择。 否则就不会有唯一的数值与其它字段关联． <br /><br />还要注意的是在聚集上聚集是没有意义的，比如，AVG(MAX(sno))， 因为 SELECT 只做一个回合的分组和聚集．你可以获得这样的结果， 方法是使用临时表或者在 FROM 子句中使用一个子 SELECT 做第一个层次的聚集． <br /><br />1.4.1.5. Having<br />HAVING 子句运做起来非常象 WHERE 子句， 只用于对那些满足 HAVING 子句里面给出的条件的组进行计算。 其实，WHERE 在分组和聚集之前过滤掉我们不需要的输入行， 而 HAVING 在 GROUP 之后那些不需要的组． 因此，WHERE 无法使用一个聚集函数的结果． 而另一方面，我们也没有理由写一个不涉及聚集函数的 HAVING． 如果你的条件不包含聚集，那么你也可以把它写在 WHERE 里面， 这样就可以避免对那些你准备抛弃的行进行的聚集运算． <br /><br />Example 1-7. Having<br /><br />如果我们想知道那些销售超过一个部件的供应商，使用下面查询： <br /><br />SELECT S.SNO, S.SNAME, COUNT(SE.PNO)<br />    FROM SUPPLIER S, SELLS SE<br />    WHERE S.SNO = SE.SNO<br />    GROUP BY S.SNO, S.SNAME<br />    HAVING COUNT(SE.PNO) &gt; 1;<br />        <br />and get: <br />SNO | SNAME | COUNT<br />   ----+-------+-------<br />     1  | Smith |   2<br />     3  | Adams |   2<br />     4  | Blake |   3<br />        <br /><br /><br />1.4.1.6. 子查询<br />在 WHERE 和 HAVING 子句里，允许在任何要产生数值的地方使用子查询 （子选择）。 这种情况下，该值必须首先来自对子查询的计算。子查询的使用扩展了 SQL 的表达能力。 <br /><br />Example 1-8. 子查询<br /><br />如果我们想知道所有比名为 'Screw' 的部件贵的部件，我们可以用下面的查询： <br /><br />SELECT * <br />    FROM PART <br />    WHERE PRICE &gt; (SELECT PRICE FROM PART<br />                   WHERE PNAME='Screw');<br />        <br /><br />结果是： <br /><br />PNO |  PNAME  |  PRICE<br />-----+---------+--------<br />    3  |  Bolt     |   15<br />    4  |  Cam    |   25<br />        <br /><br />当我们检查上面的查询时会发现出现了两次 SELECT 关键字。 第一个在查询的开头 - 我们将称之为外层 SELECT - 而另一个在 WHERE 子句里面，成为一个嵌入的查询 - 我们将称之为内层 SELECT。 对外层 SELECT 的每条记录都必须先计算内层 SELECT。在完成所有计算之后， 我们得知名为 'Screw' 部件的记录的价格， 然后我们就可以检查那些价格更贵的记录了。 (实际上，在本例中，内层查询只需要执行一次， 因为它不依赖于外层查询高等状态．) <br /><br />如果我们想知道那些不销售任何部件的供应商 （比如说，我们想把这些供应商从数据库中删除），我们用： <br /><br />SELECT * <br />    FROM SUPPLIER S<br />    WHERE NOT EXISTS<br />        (SELECT * FROM SELLS SE<br />         WHERE SE.SNO = S.SNO);<br />        <br /><br />在我们的例子里，结果列将是空的，因为每个供应商至少销售一个部件。 请注意我们在 WHERE 子句的内层 SELECT 里使用了来自外层 SELECT 的 S.SNO。 正如前面所说的，子查询为每个外层查询计算一次，也就是说， S.SNO 的值总是从外层 SELECT 的实际记录中取得的。 <br /><br /><br />1.4.1.7. 在 FROM 里面的子查询<br />一种有些特别的子查询的用法是把它们放在 FROM 子句里． 这个特性很有用，因为这样的子查询可以输出多列和多行， 而在表达式里使用的子查询必须生成一个结果． FROM 里的子查询还可以让我们获得多于一个回合的分组/聚集特性， 而不需要求助于临时表． <br /><br />Example 1-9. FROM 里面的子查询<br /><br />如果我们想知道在所有我们的供应商中的最高平均部件价格的那家， 我们不能用 MAX(AVG(PRICE))，但我们可以这么写： <br /><br />SELECT MAX(subtable.avgprice)<br />    FROM (SELECT AVG(P.PRICE) AS avgprice<br />          FROM SUPPLIER S, PART P, SELLS SE<br />          WHERE S.SNO = SE.SNO AND<br />                P.PNO = SE.PNO<br />          GROUP BY S.SNO) subtable;<br />        <br />这个子查询为每个供应商返回一行（因为它的 GROUP BY） 然后我们在外层查询对所有行进行聚集． <br /><br /><br />1.4.1.8. Union, Intersect, Except（联合，相交，相异）<br />这些操作符分别计算两个子查询产生的元组的联合，相交和集合理论里的相异。 <br /><br />Example 1-10. Union, Intersect, Except<br /><br />下面的例子是 UNION 的例子： <br /><br />SELECT S.SNO, S.SNAME, S.CITY<br />    FROM SUPPLIER S<br />    WHERE S.SNAME = 'Jones'<br />UNION<br />    SELECT S.SNO, S.SNAME, S.CITY<br />    FROM SUPPLIER S<br />    WHERE S.SNAME = 'Adams';    <br />        <br />产生结果： <br />SNO | SNAME |  CITY<br />-----+-------+--------<br />  2  | Jones | Paris<br />  3  | Adams | Vienna<br />        <br /><br />下面是相交（ INTERSECT）的例子： <br /><br />SELECT S.SNO, S.SNAME, S.CITY<br />    FROM SUPPLIER S<br />    WHERE S.SNO &gt; 1<br />INTERSECT<br />    SELECT S.SNO, S.SNAME, S.CITY<br />    FROM SUPPLIER S<br />    WHERE S.SNO &lt; 3;<br />        <br />产生结果： <br />SNO | SNAME |  CITY<br />-----+-------+--------<br />    2  | Jones | Paris<br />        <br />两个查询都会返回的元组是那条 SNO=2 的 <br /><br />最后是一个 EXCEPT 的例子： <br /><br />SELECT S.SNO, S.SNAME, S.CITY<br />    FROM SUPPLIER S<br />    WHERE S.SNO &gt; 1<br />EXCEPT<br />    SELECT S.SNO, S.SNAME, S.CITY<br />    FROM SUPPLIER S<br />    WHERE S.SNO &gt; 3;<br />        <br />结果是： <br />SNO | SNAME |  CITY<br />-----+-------+--------<br />  2  | Jones | Paris<br />  3  | Adams | Vienna</span>
		</p>
<img src ="http://www.cnitblog.com/wjw/aggbug/10452.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wjw/" target="_blank">i have only belief</a> 2006-05-13 21:21 <a href="http://www.cnitblog.com/wjw/archive/2006/05/13/10452.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>