PHP5的XML新特性
作者 Christian Stocker 翻译 ice_berg16(寻梦的稻草人)
面向的读者
这篇文章的面向对象是所有对PHP5的XML新功能感兴趣的各个水平的PHP开发者。我们假定读者掌握XML的基本知识。然而,如果你已经在你的PHP当中使用了XML,那么这篇文章也会让你受益非浅。
介绍
在当今的互联网世界,XML已经不再是一个时髦词了,它已经被广泛的接受和规范的使用了。因此相对于PHP4,PHP5对于XML的支持更受到了重视。在PHP4中你面对的几乎都是非标准,API中断,内存泄漏以及其它不完全的功能。尽管有些不足已经在PHP4.3中得到改进,开发者们还是决定抛弃原有的代码,在PHP5重写全部代码。
这篇文章将对PHP5中关于XML的所有令人激动的新特性逐一介绍。
PHP4 的 XML
早期的PHP版本就已经开始支持XML了,而这只是一个基于SAX的接口,它可以轻松的解析任何XML文档。随着PHP4中加入了DOMXML扩展模块,XML被更好的支持了。后来XSLT做为补充被加了进来。在整个PHP4的阶段,其它一些功能如HTML,XSLT和DTD验证也被加到了DOMXML扩展中,不幸的是,由于XSLT和DOMXML扩展始终处于实验阶段,API部分也被不止一次的修改,它们还是不能以默认方式安装。此外,DOMXML扩展没有遵循W3C制定的DOM标准,而有自己的命名方法。虽然在PHP4.3中这部分得到了改善并且许多内存泄漏和其它一些功能也得以修复,但它始终没有发展到一个稳定的阶段,一些深入的问题已经几乎不可能修复。只有SAX扩展被已默认方式安装,其它的一些扩展从未得到广泛的使用。
基于所有这些原因,PHP的XML开发者决定在PHP5重写全部代码,并遵循使用标准。
PHP5的XML
在PHP5中所有支持XML的部分几乎全部重新编写.现在的所有XML扩展都是基于GNOME项目的LIBXML2库。这将允许在不同的扩展模块之间互相操作,核心开发者只需要在一个底层的库上进行开发。例如,复杂的内存管理只实现一次就可以让所有XML相关扩展得到改善。
除了继承PHP4中闻名的SAX解析器之外,PHP5还支持遵循W3C标准的DOM和基于LIBXSLT引擎的XSLT。同时还加入了PHP独有的SimpleXML扩展和符合标准的SOAP扩展。随着XML越来越被重视,PHP开发者决定在默认安装方式中加入更多对XML的支持。这就意味着你现在可以使用SAX,DOM和SimpleXML,而这些扩展将会在更多的服务器上安装。然后对于XSLT和SOAP的支持,还需要在PHP编译时被显式的配置。
数据流的支持
现在所有的XML扩展都支持PHP数据流,即使你不从PHP中直接访问。例如,在PHP5中你可以从一个文件或从一条指令访问数据流。基本上你能够在任何可以访问普通文件的地方访问PHP数据流。
PHP4.3中简要的介绍了数据流,在PHP5中已经得到了进一步的提高,包含文件存取,网络存取和其它操作,如共享一套功能函数。你甚至可以使用PHP代码来实现你自己的数据流,这样数据存取将变得非常简单。关于这部分的更多细节请参考PHP文档。
SAX
SAX的全称是Simple API for XML,它是用于解析XML文档的接口,是基于回调形式的。从PHP3开始就已经支持了SAX,到现在也没有太大的变化。在PHP5中,API接口并没有改变,所以你的代码仍然可以运行。唯一不同的是它不再基于EXPAT库,而是基于LIBXML2库。
这个变化带来了一些对命名空间支持上的问题,这个问题在LIBXML2.2.6版本中已经得到解决。但是LIBXML2以前的版本中并没有解决,因此如果你使用了xml_parse_create_ns();强烈建议在你的系统上安装LIBXML2.2.6。
DOM
DOM (文档对象模型)是由W3C制定的一套访问XML文档树的标准。在PHP4可以使用DOMXML来对此进行操作,DOMXML的最主要问题是它不符合标准的命名方法。而且在很长一段时间内还存在内存泄漏问题(PHP4.3已经修复了这个问题)。
新的DOM扩展是基于W3C标准完成的,包含方法和属性名称。如果你在其它语言中熟悉DOM,例如在Javascript中,那么在PHP中编写类似的功能将变得非常容易。你不必每次都查看文档,因为方法和参数都是相同的。
由于使用了新的W3C标准,基于DOMXML的代码将不能运行。在PHP中的API有很大的不同。但是如果你的代码中使用了类似W3C标准的方法命名方式,移植并不是很困难。你只需要将载入函数和保存函数修改,删除函数名中的下划线(DOM标准使用首字母大写)。其它各处的调节当然也是必须的,但是主要逻辑部分可以保持不变。
读取DOM
我不会在这篇文章中解释DOM扩展的所有特性,那也是没有必要的。或许你应该将HTTP://www.w3.org/DOM的文档加入书签...糠只旧舷嗤?/a>
在这篇文章的大多数例子中我们将使用同一个XML文件,zend.com上有非常简单的RSS版本。将下面的文本粘贴到一个文本文件中并保存为articles.xml。
http://www.zend.com/zend/week/week172.php
http://www.zend.com/zend/tut/tut-hatwar3.php
要将这个例子载入到一个DOM对象,首先要创建一个DOMDocument对象,然后载入XML文件。
$dom = new DomDocument();
$dom->load("articles.xml");
正像上面所提及的,你可以使用PHP的数据流来载入一个XML文档,你应该这样写:
$dom->load("file:///articles.xml");
(或者其它类型的数据流)
如果你想将XML文档输出到浏览器或做为标准标出,使用:
print $dom->saveXML();
如果你想把它保存成文件,请使用:
print $dom->save("newfile.xml");
(注意这样做会将文件大小发送到stdout)
当然这个例子没有太多的功能,让我们来做些更有用的。我们来取得所有的title元素。有很多方法可以办到,最简单的就是使用getElementsByTagName($tagname):
$titles = $dom->getElementsByTagName("title");
foreach($titles as $node) {
print $node->textContent . "\n";
}
textContent属性并不是W3C标准,它可以让我们很方便的快速读取一个元素的所有文本节点,使用W3C的标准读取是下面这样:
$node->firstChild->data;
(这时候你要确保firstChild结点是你需要的文本结点,否则你还得遍历所有子结点来查找)。
另外一个要注意的问题是getElementsByTagName()返回一个DomNodeList,对象,而不是像PHP4中get_elements_by_tagname()那样返回一个数组,但是正像你在这个例子中看到的那样,你可以使用foreach语句轻松的遍历它。你也可以直接使用$titles->item(0)来访问结点。该方法将返回第一个title元素。
另一个取得所有title元素的办法是从根结点遍历,你可以看到,这个方法更复杂,但是如果你需要的不只是title元素的时候,这个方法也就更灵活。
foreach ($dom->documentElement->childNodes as $articles) {
//如果节点是一个元素(nodeType == 1)并且名字是item就继续循环
if ($articles->nodeType == 1 && $articles->nodeName == "item") {
foreach ($articles->childNodes as $item) {
//如果节点是一个元素,并且名字是title就打印它.
if ($item->nodeType == 1 && $item->nodeName == "title") {
print $item->textContent . "\n";
}
}
}
}
XPath
XPaht 就像是XML的SQL,使用XPath你可以在一个XML文档中查询符合一些模式语法的特定结点。想使用XPath获得所有title结点,只需要这么做:
$xp = new domxpath($dom);
$titles = $xp->query("/articles/item/title");
foreach ($titles as $node) {
print $node->textContent . "\n";
}
?>
这样和使用getElementsByTagName()方法差不多,但是Xpath要强大的多,例如,如果我们有一个title元素是article的子元素(而不是item的子元素),getElementsByTagName()就会将它返回。而使用/articles/item/title语法,我们只会得到在指定深度和位置的title元素。这只是一个简单的例子,再深入一点可能是这样:
/articles/item[position() = 1]/title 返回第一个item元素的所有
/articles/item/title[@id = '23'] 返回所有含有id属性并且值为23的title
/articles//title 返回所有articles元素下面的title(译者注://代表任意深度)
你也可以查询含有特殊兄弟元素的点,含有特殊文本内容的元素,或者使用命名空间等等。如果你必须大量的查询XML文档,适当的学习使用XPath会节省你很多时间,它使用简单,执行速度快,比标准的DOM需要更少的代码。
向DOM中写入数据
文档对象模型并不是只能读取和查询,你也可以操作和写入。(DOM标准有点冗长,因为编写者想尽量支持能够想像到的每一个环境,但是它工作的非常好)。看看下面这个例子,它在我们的article.xml文件中添加了一个新元素。
$item = $dom->createElement("item");
$title = $dom->createElement("title");
$titletext = $dom->createTextNode("XML in PHP5");
$title->appendChild($titletext);
$item->appendChild($title);
$dom->documentElement->appendChild($item);
print $dom->saveXML();
首先,我们创建了所有需要的结点,一个item元素,一个title元素和一个包含item标题的文本结点,然后我们将所有的结点链接起来,把文本结点加到title元素上,把title元素加到item元素上,最后我们把item元素插入到articles根元素上。现在,我们的XML文档中有一个新的文章列表了。
扩展类(class)
好了,上面的例子都可以在PHP4下面用DOMXML扩展来做(只是API有一些不同),能够自己扩展DOM类是PHP5的一个新特性,这使得书写更多可读性强的代码变得可能。下面是用DOMDocument类重新写的整个例子:
class Articles extends DomDocument {
function __construct() {
//必须调用!
parent::__construct();
}
function addArticle($title) {
$item = $this->createElement("item");
$titlespace = $this->createElement("title");
$titletext = $this->createTextNode($title);
$titlespace->appendChild($titletext);
$item->appendChild($titlespace);
$this->documentElement->appendChild($item);
}
}
$dom = new Articles();
$dom->load("articles.xml");
$dom->addArticle("XML in PHP5");
print $dom->save("newfile.xml");
HTML
PHP5中一个经常不被注意到的特性是libxml2库对HTML的支持,你不仅可以使用DOM扩展载入结构良好(well-formed)的XML文档,还可以载入非结构良好的(not-well-formed)HTML文档,把它当做标准的DOMDocument对象,使用所有能用的方法和特性,比如XPath和SimpleXML。
当你需要访问一个你无法控制站点的内容时,HTML的性能就显示十分有用了。在 XPath, XSLT 或 SimpleXML的帮助下,你省掉了许多代码,像使用正则表达式比较字符串或者SAX解析器。当HTML文档结构不是很好的时候,这个办法尤其有用(这是个频繁的问题!)。
下面的代码获得并解析php.net的首页,将返第一个title元素的内容。
$dom = new DomDocument();
$dom->loadHTMLFile("http://www.php.net/");
$title = $dom->getElementsByTagName("title");
print $title->item(0)->textContent;
请注意当指定元素没有找到时,你的输出可能会包含错误。如果你的网站还在使用PHP输出HTML4代码,有一个好消息要告诉你,DOM扩展不仅能载入HTML文档,而且还能将他们保存为HTML4格式的文件。在你添加完DOM文档后,使用$dom->saveHTML()来保存。要注意的是,为了使输出的HTML代码符合W3C标准,最好不用使用 整齐的扩展?(tidy extension)。Libxml2 库支持的HTML并不会考虑到每个可能发生的事情,也不能很好的处理非通用格式的输入。
验证
XML文档的验证越来越重要了。例如,如果你从一些国外资源中获得了一个XML文档,在你处理之前你需要检验它是否符合某个确定的格式。幸运的是你不需要在PHP中写自己的验证程序,因为你可以使用三个应用最广泛的标准之一(DTD,XML Schema 或RelaxNG)来完成它。.
DTD是一个产生于SGML时代的标准,缺少一些XML的新特性(如命名空间),而且由于它不是用XML写的,它也很难被解析和转换。
XML Schemai是由W3C制定的一个标准,它应用广泛,几乎包含了所有验证XML文档所需要的内容。
RelaxNG 是复杂的XML Schema标准的对头,是由自由者组织创建的,由于它比XML Schema更容易实现,越来越多的程序开始支持RelaxNG了
如果你没有遗留下来的计划文档或者非常复杂的XML文档,那么使用RelaxNG吧。它书写和阅读都比较简单,越来越多的工具也支持它。甚至还有一个工具叫Trang,它可以从XML范本中自动创建一个RelaxNG文档。而且只有RelaxNG(和老化的DTDS)被libxml2完全支持,尽管libxml2也即将完全支持ML Schema。
验证XML文档的语法相当简单:
$dom->validate('articles.dtd');
$dom->relaxNGValidate('articles.rng');
$dom->schemaValidate('articles.xsd');
目前,所有这些都只会简单的返回true或false,错误会被做为PHP警告输出。显然想返回给用户友好的信息这并不是一个好主意,在PHP5.0以后的版本里会有所改善。到底该怎么实现目前还在讨论之中,但是错误报告肯定会处理的更好。
SimpleXML
SimpleXML 是PHP的XML家族中最后一个被加入的成员,加入SimpleXML扩展的目的是为了提供一个使用标准对象属性和迭代器访问XML文档的更简单的方法。该扩展没有太多的方法,虽然如此它还是相当强大的。从我们的文档的取得所有title节点比原来需要更少的代码。
$sxe = simplexml_load_file("articles.xml");
foreach($sxe->item as $item) {
print $item->title ."\n";
}
这是在干什么?首先将articles.xml载入到一个SimpleXML对象。然后取得所有$sxe中的item元素,最后$item->title返回title元素的内容,就是这样。你也可以使用关联数组查询属性,使用: $item->title['id']。
看到了吧,这后面真是太神奇了,有许多不同的办法可以得到我们想要的结果,例如, $item->title[0]返回和例子中相同的结果,另一方面,foreach($sxe->item->title as $item)只返回第一个title,并不是所有在文档中的title元素。(就像我在XPath中预期的那样)。
SimpleXML 实际上是使用了Zend引擎2新特性的第一个扩展。因此也成了这些新特性的测试点,你要知道在开发阶段bugs和不可预料的错误可不是少数。
除了上面例子中所使用的遍历所有节点的方法,在SimpleXML中也有一个XPath接口,它为访问单个结点提供了更简单的办法。
foreach($sxe->xpath('/articles/item/title') as $item) {
print $item . "\n";
}
不可否认,这段代码也不比前面例子中的短,但是提供了更复杂或更深的嵌套XML文档,你会发现和SimpleXML一起使用XPath会节省你很多的输入。
向 SimpleXML 文档写入数据
你不仅可以解析和读取SimpleXML,而且还可以改变SimpleXML文档。至少我们加入一些扩展:
$sxe->item->title = "XML in PHP5 "; //title元素的新内容。
$sxe->item->title['id'] = 34; // title元素的新属性。
$xmlString = $sxe->asXML(); // 将SimpleXML对象做为序列化的XML字符串返回
print $xmlString;
互用协作性
由于SimpleXML也是基于libxml2库的,你可以在几乎不影响速度的情况下轻松的将SimpleXML对象转化成DomDocument对象。(文档不用进行内部复制),由于这个机制,你拥有了二个对象的最好部分,使用一个适合你手头工作的工具吧,它是这样使用的:
$sxe = simplexml_import_dom($dom);
$dom = dom_import_simplexml($sxe);
XSLT
XSLT是用来将XML文档转换为其它XML文档的语言,XSLT本身是用XML编写的,属于功能性语言家族,在程序处理上和面对对象语言(像PHP)有所不同。PHP4中有二种XSLT处理器:Sablotron(在广泛使用的XSLT扩展中)和Libxslt(在domxml扩展中),这两种API不互相兼容,并且使用方法也不相同。PHP5只支持libxslt处理器,之所以选择它是因为它是基于Libxml2的,因此也更符合PHP5的XML概念。
理论上将Sablotron绑定到PHP5上也是可能的,但是不幸的是没人来做。因此,如果你正在使用Sablotron,你不得不在PHP5中切换到libxslt处理器。Libxslt 是带有Javascript异常处理支持的Sablotron,甚至可以使用PHP强大的数据流来重新实现Sablotron独有的计划处理(scheme handlers)。此外,libxslt 是 最快的XSLT处理器之一,所以你还免费得到了速度的提升。(执行速度是Sablotron的二倍)。
和本文讨论的其它扩展一样,你可以在XSL扩展,DOM扩展和vice versa之间交换XML文档,实际上,你必须得这么做,因为EXT/XSL扩展并没有载入和保存XML文档的接口,只能使用DOM扩展。一开始学习XSLT转换,你不需要掌握太多的内容,这里也不存在W3C标准,因为这个API中从Mozilla“借”过来的。
首先你需要一个XSLT样式表,将下列文本粘贴到一个新文件并且保存灰articls.xsl
然后用PHP脚本调用它::
/* 将XML和XSL文档载入到DOMDocument对象*/
$xsl = new DomDocument();
$xsl->load("articles.xsl");
$inputdom = new DomDocument();
$inputdom->load("articles.xml");
/* 创建XSLT处理器,并导入样式表*/
$proc = new XsltProcessor();
$xsl = $proc->importStylesheet($xsl);
$proc->setParameter(null, "titles", "Titles");
/* 转换并输出XML文档 */
$newdom = $proc->transformToDoc($inputdom);
print $newdom->saveXML();
?>
上面的例子首先使用DOM的方法load()载入XSLT样式表articles.xsl,然后创建了一个新的XsltProcessor对象,该对象导到了后面要使用了XSLT样式表对象,参数可以这样设置setParameter(namespaceURI, name, value),最后XsltProcessor对象使用transformToDoc($inputdom)开始转换并返回一个新的DOMDocument对象。
. 这个API的优点在于你可以使用同一个样式表转换许多XML文档,只需要将它载入一次然后重复使用它,因为transormToDoc()函数可以应用于不同的XML文档。
除了transormToDoc(),还有二个用于转换的方法:transformToXML($dom)返回一个字符串,transformToURI($dom, $uri)将转换之后的文档保存到文件或一个PHP数据流。注意如果你想使用XSLT的一个语法如 或 indent="yes",你不能使用transformToDoc(),因为DOMDocument对象 不能保存该信息,只能当你将转换后的结果直接保存到字符串或文件中时才能这样做。
调用PHP函数
XSLT扩展最后一个新加的特性是能够在XSLT 样式表内部调用任何PHP函数,主张正统的XML支持者一定不会喜欢这个功能(这样的样式表有点复杂,很容易混淆逻辑和设计),在某些地方却是十分有用的。当涉及到函数时XSLT就变得很有限,即使想实现用不同的语言输出一个日期也是非常麻烦的。但是使用这个功能,处理这些就和只使用PHP一样容易。下面是向XSLT添加一个函数的代码:
function dateLang () {
return strftime("%A");
}
$xsl = new DomDocument();
$xsl->load("datetime.xsl");
$inputdom = new DomDocument();
$inputdom->load("today.xml");
$proc = new XsltProcessor();
$proc->registerPhpFunctions();
// 载入文档并使用$xsl来处理
$xsl = $proc->importStylesheet($xsl);
/* 转换并输出XML文档 */
$newdom = $proc->transformToDoc($inputdom);
print $newdom->saveXML();
?>
下面是XSLT样式表datetime.xsl,它会调用这个函数。
下面是要使用样式表转换的XML文档,today.xml(同理,articles.xml也会得到同样结果)。
上面的样式表,PHP脚本和所有的XML文件会用当前系统设置的语言输出星期的名字。你可以给php:function()添加更多的参数,添加的参数会被传递给PHP函数。这里有一个函数php:functionString(),这个函数自动将所有输入的参数转换为字符串,所以你不需要在PHP里进行转换。
注意你需要在转换之前调用$xslt->registerPhpFunctions(),否则PHP函数调用将因为安全原因不会被执行(你始终相信你的XSLT样式表吗?)。目前访问系统还没有实现,也许在将来PHP5的版本中会实现这个功能。
摘要
PHP对XML的支持已经向前迈进了一大步,它符合标准,功能强大,互用协作性强,被作为默认选项安装,已被授权使用。新加入的SimpleXML扩展提供了简单快速访问XML文档的方法,可以节省你很多的代码,尤其是当你有结构化文档或者可以使用强大的XPath时。
感谢libxml2—PHP5 XML扩展所使用的底层库,使用DTD,RelaxNG或XML Schema验证XML文档现在已经被支持了。
XSL支持也得到了翻新,现在使用Libxslt库,比原来的Sablotron库在性能上有很大提高,而且,在XSLT样式表内部调用PHP函数可以让你写出更强大的XSLT代码。
如果你已经在PHP4或其它语言中使用了XML,你会喜欢PHP5的XML特性的,XML在PHP5中有了很大的变化,符合标准,和其它工具,语言是同等的。
链接
PHP 4 相关
Domxml 扩展: http://www.php.net/domxml/
Sablotron 扩展: http://www.php.net/xslt/
Libxslt: http://www.php.net/manual/en/functi...-stylesheet.php
PHP 5 相关
SimpleXML: http://www.php.net/simplexml/
Streams: http://www.php.net/manual/en/ref.stream.php
标准
DOM: http://www.w3.org/DOM
XSLT: http://www.w3.org/TR/xslt
XPath: http://www.w3.org/TR/xpath
XML Schema: http://www.w3.org/XML/Schema
RelaxNG: http://relaxng.org/
Xinclude: http://www.w3.org/TR/xinclude/
工具
Libxml2, the underlying library: http://xmlsoft.org/
Trang, a Schema/RelaxNG/etc converter: http://www.thaiopensource.com/relaxng/trang.html
关于作者
Christian Stocker是苏黎士Bitflux GmbH公司的创始人和CEO,他是XSL,DOM和imagick扩展的维护人员,德语书籍PHP de Luxe的合作作者,同时致力于其它开源项目,如Bitflux Editor和Popoon.。可以通用chregu@php.net.和他联系。
为什么要创建索引呢?这是因为,创建索引可以大大提高系统的性能。第一,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。第二,可以大大加快数据的检索速度,这也是创建索引的最主要的原因。第三,可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。第四,在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。第五,通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。
也许会有人要问:增加索引有如此多的优点,为什么不对表中的每一个列创建一个索引呢?这种想法固然有其合理性,然而也有其片面性。虽然,索引有许多优点,但是,为表中的每一个列都增加索引,是非常不明智的。这是因为,增加索引也有许多不利的一个方面。第一,创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。第二,索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。第三,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。
索引是建立在数据库表中的某些列的上面。因此,在创建索引的时候,应该仔细考虑在哪些列上可以创建索引,在哪些列上不能创建索引。一般来说,应该在这些列上创建索引,例如:在经常需要搜索的列上,可以加快搜索的速度;在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。
同样,对于有些列不应该创建索引。一般来说,不应该创建索引的的这些列具有下列特点:第一,对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。第二,对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。第三,对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。第四,当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。
创建索引的方法和索引的特征
创建索引的方法
创建索引有多种方法,这些方法包括直接创建索引的方法和间接创建索引的方法。直接创建索引,例如使用CREATE INDEX语句或者使用创建索引向导,间接创建索引,例如在表中定义主键约束或者唯一性键约束时,同时也创建了索引。虽然,这两种方法都可以创建索引,但是,它们创建索引的具体内容是有区别的。
使用CREATE INDEX语句或者使用创建索引向导来创建索引,这是最基本的索引创建方式,并且这种方法最具有柔性,可以定制创建出符合自己需要的索引。在使用这种方式创建索引时,可以使用许多选项,例如指定数据页的充满度、进行排序、整理统计信息等,这样可以优化索引。使用这种方法,可以指定索引的类型、唯一性和复合性,也就是说,既可以创建聚簇索引,也可以创建非聚簇索引,既可以在一个列上创建索引,也可以在两个或者两个以上的列上创建索引。
通过定义主键约束或者唯一性键约束,也可以间接创建索引。主键约束是一种保持数据完整性的逻辑,它限制表中的记录有相同的主键记录。在创建主键约束时,系统自动创建了一个唯一性的聚簇索引。虽然,在逻辑上,主键约束是一种重要的结构,但是,在物理结构上,与主键约束相对应的结构是唯一性的聚簇索引。换句话说,在物理实现上,不存在主键约束,而只存在唯一性的聚簇索引。同样,在创建唯一性键约束时,也同时创建了索引,这种索引则是唯一性的非聚簇索引。因此,当使用约束创建索引时,索引的类型和特征基本上都已经确定了,由用户定制的余地比较小。
当在表上定义主键或者唯一性键约束时,如果表中已经有了使用CREATE INDEX语句创建的标准索引时,那么主键约束或者唯一性键约束创建的索引覆盖以前创建的标准索引。也就是说,主键约束或者唯一性键约束创建的索引的优先级高于使用CREATE INDEX语句创建的索引。
索引的特征
索引有两个特征,即唯一性索引和复合索引。
唯一性索引保证在索引列中的全部数据是唯一的,不会包含冗余数据。如果表中已经有一个主键约束或者唯一性键约束,那么当创建表或者修改表时,SQL Server自动创建一个唯一性索引。然而,如果必须保证唯一性,那么应该创建主键约束或者唯一性键约束,而不是创建一个唯一性索引。当创建唯一性索引时,应该认真考虑这些规则:当在表中创建主键约束或者唯一性键约束时,SQL Server自动创建一个唯一性索引;如果表中已经包含有数据,那么当创建索引时,SQL Server检查表中已有数据的冗余性;每当使用插入语句插入数据或者使用修改语句修改数据时,SQL Server检查数据的冗余性:如果有冗余值,那么SQL Server取消该语句的执行,并且返回一个错误消息;确保表中的每一行数据都有一个唯一值,这样可以确保每一个实体都可以唯一确认;只能在可以保证实体完整性的列上创建唯一性索引,例如,不能在人事表中的姓名列上创建唯一性索引,因为人们可以有相同的姓名。
复合索引就是一个索引创建在两个列或者多个列上。在搜索时,当两个或者多个列作为一个关键值时,最好在这些列上创建复合索引。当创建复合索引时,应该考虑这些规则:最多可以把16个列合并成一个单独的复合索引,构成复合索引的列的总长度不能超过900字节,也就是说复合列的长度不能太长;在复合索引中,所有的列必须来自同一个表中,不能跨表建立复合列;在复合索引中,列的排列顺序是非常重要的,因此要认真排列列的顺序,原则上,应该首先定义最唯一的列,例如在(COL1,COL2)上的索引与在(COL2,COL1)上的索引是不相同的,因为两个索引的列的顺序不同;为了使查询优化器使用复合索引,查询语句中的WHERE子句必须参考复合索引中第一个列;当表中有多个关键列时,复合索引是非常有用的;使用复合索引可以提高查询性能,减少在一个表中所创建的索引数量。
索引的类型
根据索引的顺序与数据表的物理顺序是否相同,可以把索引分成两种类型。一种是数据表的物理顺序与索引顺序相同的聚簇索引,另一种是数据表的物理顺序与索引顺序不相同的非聚簇索引。
聚簇索引的体系结构
索引的结构类似于树状结构,树的顶部称为叶级,树的其它部分称为非叶级,树的根部在非叶级中。同样,在聚簇索引中,聚簇索引的叶级和非叶级构成了一个树状结构,索引的最低级是叶级。在聚簇索引中,表中的数据所在的数据页是叶级,在叶级之上的索引页是非叶级,索引数据所在的索引页是非叶级。在聚簇索引中,数据值的顺序总是按照升序排列。
应该在表中经常搜索的列或者按照顺序访问的列上创建聚簇索引。当创建聚簇索引时,应该考虑这些因素:每一个表只能有一个聚簇索引,因为表中数据的物理顺序只能有一个;表中行的物理顺序和索引中行的物理顺序是相同的,在创建任何非聚簇索引之前创建聚簇索引,这是因为聚簇索引改变了表中行的物理顺序,数据行按照一定的顺序排列,并且自动维护这个顺序;关键值的唯一性要么使用UNIQUE关键字明确维护,要么由一个内部的唯一标识符明确维护,这些唯一性标识符是系统自己使用的,用户不能访问;聚簇索引的平均大小大约是数据表的百分之五,但是,实际的聚簇索引的大小常常根据索引列的大小变化而变化;在索引的创建过程中,SQL Server临时使用当前数据库的磁盘空间,当创建聚簇索引时,需要1.2倍的表空间的大小,因此,一定要保证有足够的空间来创建聚簇索引。
当系统访问表中的数据时,首先确定在相应的列上是否存在有索引和该索引是否对要检索的数据有意义。如果索引存在并且该索引非常有意义,那么系统使用该索引访问表中的记录。系统从索引开始浏览到数据,索引浏览则从树状索引的根部开始。从根部开始,搜索值与每一个关键值相比较,确定搜索值是否大于或者等于关键值。这一步重复进行,直到碰上一个比搜索值大的关键值,或者该搜索值大于或者等于索引页上所有的关键值为止。
非聚簇索引的体系结构
非聚簇索引的结构也是树状结构,与聚簇索引的结构非常类似,但是也有明显的不同。
在非聚簇索引中,叶级仅包含关键值,而没有包含数据行。非聚簇索引表示行的逻辑顺序。 非聚簇索引有两种体系结构:一种体系结构是在没有聚簇索引的表上创建非聚簇索引,另一种体系结构是在有聚簇索引的表上创建非聚簇索引。
如果一个数据表中没有聚簇索引,那么这个数据表也称为数据堆。当非聚簇索引在数据堆的顶部创建时,系统使用索引页中的行标识符指向数据页中的记录。行标识符存储了数据所在位置的信息。数据堆是通过使用索引分配图(IAM)页来维护的。IAM页包含了数据堆所在簇的存储信息。在系统表sysindexes中,有一个指针指向了与数据堆相关的第一个IAM页。系统使用IAM页在数据堆中浏览和寻找可以插入新的记录行的空间。这些数据页和在这些数据页中的记录没有任何的顺序并且也没有链接在一起。在这些数据页之间的唯一的连接是IAM中记录的顺序。当在数据堆上创建了非聚簇索引时,叶级中包含了指向数据页的行标识符。行标识符指定记录行的逻辑顺序,由文件ID、页号和行ID组成。这些行的标识符维持唯一性。非聚簇索引的叶级页的顺序不同于表中数据的物理顺序。这些关键值在叶级中以升序维持。
当非聚簇索引创建在有聚簇索引的表上的时候,系统使用索引页中的指向聚簇索引的聚簇键。聚簇键存储了数据的位置信息。如果某一个表有聚簇索引,那么非聚簇索引的叶级包含了映射到聚簇键的聚簇键值,而不是映射到物理的行标识符。当系统访问有非聚簇索引的表中数据时,并且这种非聚簇索引创建在聚簇索引上,那么它首先从非聚簇索引来找到指向聚簇索引的指针,然后通过使用聚簇索引来找到数据。
当需要以多种方式检索数据时,非聚簇索引是非常有用的。当创建非聚簇索引时,要考虑这些情况:在缺省情况下,所创建的索引是非聚簇索引;在每一个表上面,可以创建不多于249个非聚簇索引,而聚簇索引最多只能有一个。
如果你是全新安装,就可以跳过这一步啦
找到你的Mysql的数据库目录下的 ragnarok 数据库目录,例如我的Mysql安装在
D:\mysql 这个目录下,就到 D:\mysql\data\ 目录下找到 ragnarok 数据库目录
把它拷贝一份到其它地方!
[升级你的ODBC - MySQL ODBC driver ]
首先打开你的控制面版,找到 [添加删除程序] 把旧的MySQL ODBC driver 删除
然后安装MyODBC-3.51.11-1-win.exe
[删除你电脑里的旧版MYSQL服务]
如果你以前安装过旧版的,那就要看看如何完整从你的系统内删除Mysql
在你从电脑里卸载旧的MYSQL数据库服务时
首先先在WINDOWS服务里停掉MYSQL的服务
再到控制面板里的增加删除程序内进行删除
但是你并不能完整的把MYSQL服务删除
那么就要在注册表里清除你的MYSQL服务
有几个地方:(应该有两项,不记得啦,大家查查吧)
1、HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Eventlog\Application\MySQL 目录删除
2、HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Services\Eventlog\Application\MySQL 目录删除
3、HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\MySQL 目录删除
如下图所示:
清除完以后,
还要记得把 C:\WINDOWS\my.ini 这个文件删除哦
然后重新启动计算机
再到你计算机服务里看一下
是不是MYSQL服务已经不见啦,好了可以进行安装新版的MYSQL啦!
[相关软件下载:]
Mysql 4.1.11-win32 - For Windows ( Mysql 4.1.11-win32.exe ) -- 数据库服务
下载
http://down.21sun.net/webtools/mysql-4.1.11-win32.zip
Connector/ODBC - MySQL ODBC driver ( MyODBC-3.51.11-1-win.exe ) -- 数据源
下载
http://down.21sun.net/webtools/MyODBC-3.51.11-1-win.exe
MySQL Control Center ( mysqlcc-0.9.4-win32.zip ) -- 管理工具
下载
http://down.21sun.net/webtools/mysqlcc-0.9.4-win32.zip
[Mysql Server 4.1.11的安装教程]
===============================================================================
1、运行MYSQL Server 4.1 安装包
2、点击(Change..)选择安装路径,建议大家不要装在C盘!
3、我选择了安装到D:\Mysql\目录下,然后点击OK,进入下一步安装
4、选择完安装路径以后点击Next>进入下一步操作!
5、点击Install进行开始安装
6、我们看到安装进度!
7、选择Skip Sign-Up 项,点击Next>继续安装!
8、到这里我们安装已经完成,选上Configure the MySQL Server now后
点击 Finish 进入Mysql的配置工作
9、进入Mysql的配置界面!
10、选择Detailed Configuration 选择后,点击Next>进行下一步!
11、选择Server Machine 然后点击Next>继续!
12、选择Multifunctional Database 然后点击Next 继续!
13、这一步默认即可(让你选择数据库文件的存放地点)建意默认!
14、选上Online Transaction Processing(OLTP)然后点击Next>继续!
15、如下图,继续Next>
16、选择语言的支持!默认为Standard Character Set
17、记得要选上Include Bin Directory In Windows Path 选项,继续
18、如下图,输入密码,继续Next>
19、点击Execute 开始完成配置并启动MYSQL服务!
20、点击Finish 完成你的Mysql的全部安装!
[恢复 cAthena Mysql 数据库的备份]
===============================================================================
把你刚才备份的 ragnarok 目录,拷贝到你的Mysql数据库目录下面,即完成对Mysql版本的升级