﻿<?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>BlogJava-执着的笨蛋-随笔分类-DB</title><link>http://www.blogjava.net/lcs/category/26138.html</link><description>黑暗的SH！灰暗的人生！</description><language>zh-cn</language><lastBuildDate>Fri, 02 May 2008 03:30:30 GMT</lastBuildDate><pubDate>Fri, 02 May 2008 03:30:30 GMT</pubDate><ttl>60</ttl><item><title>数据表损坏的修复方法(终极完美版!!!!!)[转]</title><link>http://www.blogjava.net/lcs/archive/2008/04/25/195835.html</link><dc:creator>lk</dc:creator><author>lk</author><pubDate>Fri, 25 Apr 2008 01:46:00 GMT</pubDate><guid>http://www.blogjava.net/lcs/archive/2008/04/25/195835.html</guid><wfw:comment>http://www.blogjava.net/lcs/comments/195835.html</wfw:comment><comments>http://www.blogjava.net/lcs/archive/2008/04/25/195835.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcs/comments/commentRss/195835.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcs/services/trackbacks/195835.html</trackback:ping><description><![CDATA[原文地址：<font style="background-color: #dee0fe">http://x.discuz.net/183161/viewspace-16039.html</font><br />
<br />
<br />
<font size="3">由于 MySQL 本身的读写及锁定机制等方面的原因，与一些其他数据库软件一样，在特殊情况下的极为频繁读写时，或在服务器掉电、死机等情况下，相关的数据文件可能会发生被损坏的情况，通常可以采用以下的方式加以解决。 <br />
<span style="display: none">.l0E-UQyEO0</span><span style="display: none">SupeSite/X-Space官方站8Eh-S:Cn Nx gs(N</span><br />
一:repair.php 修复工具<br />
<span style="display: none">o^7rU V-uQ0</span>Discuz! 自带了一个使用 PHP 编写的数据表修复工具 repair.php，虚拟主机用户也可使用。该工具位于软件包的 ./utilities 目录中，使用时需要上传到服务器上论坛目录（注意不要连 ./utilities 目录一起上传，否则无法运行），<br />
<span style="display: none">Sj;btNK9u0</span><img title="点击图片可在新窗口打开" style="width: 400px; cursor: pointer" src="http://www.discuz.net/attachments/month_0602/upload_2hBZ9agBdcXo.jpg"  alt="" /><br />
<span style="display: none">1X"|4m&amp;i?6Z v-NmV0</span>upload.jpg<span style="display: none">SupeSite/X-Space官方站]] Jj.G"^</span><br />
在浏览器运行后点击下面的链接即可<br />
<span style="display: none">Rx(m-qy0</span><img title="点击图片可在新窗口打开" style="width: 400px; cursor: pointer" src="http://www.discuz.net/attachments/month_0602/run_ZLKvsVv6Rnk9.jpg"  alt="" /><span style="display: none">SupeSite/X-Space官方站7C3K{~ n%E)c-G"WB</span><br />
run.jpg<span style="display: none">SupeSite/X-Space官方站_N'C _b</span><br />
<span style="display: none">SupeSite/X-Space官方站q4l8l q u C%[K</span><br />
修复以后如果出现下面的画面表示修复成功!!!<span style="display: none">SupeSite/X-Space官方站G iv`*X</span><br />
<br />
<span style="display: none">aM@5A z n'\ ez*A0</span><img title="点击图片可在新窗口打开" style="width: 400px; cursor: pointer" src="http://www.discuz.net/attachments/month_0602/result_1QHvotpMWYR5.jpg"  alt="" /><span style="display: none">SupeSite/X-Space官方站0L `C ZQF0s^-Y</span><br />
result.jpg<br />
<span style="display: none">'qb _H!Q4t)['^/e0</span>这个工具能修复大多数常见的数据库错误，尤其是错误号为 126、127 的错误，对 145 错误也可修复，同时能对数据表在修复之后进行优化。如果一次修复不成功，可以尝试多次，或将数据库重启后再试。 <br />
<span style="display: none">_~yFxm0</span><br />
<span style="display: none">3P` w:e G9S,t2m)V0</span><span style="display: none">SupeSite/X-Space官方站G)Y+N$|:p[J-|*{I&amp;c7e</span><br />
<span style="display: none">SupeSite/X-Space官方站[@N*AfS</span><br />
二 :myisamchk 修复工具<span style="display: none">SupeSite/X-Space官方站E)?E/?F5S&amp;o</span><br />
MySQL 自带了专门用户数据表检查和修复的工具——myisamchk，当 repair.php 多次修复均无法成功时，可以在服务器终端使用 myisamchk 进行修复。在 MySQL 的程序文件目录（见《数据备份与恢复》中的说明）可以找到这个工具。 <span style="display: none">SupeSite/X-Space官方站+k[n+Vq KYW</span><br />
<br />
<span style="display: none">J6g;oB%fy;gG@0</span>常用的修复命令为 myisamchk -r 数据文件目录/数据表名.MYI，如果 -r 参数不能奏效，可以先把数据文件备份（备份可使用直接文件复制的方式，详见《数据备份与恢复》中的说明）后使用 -o 参数,如果-o还不可以的话,就使用-f参数,如果还是无法修复,只有使用你的备份文件来恢复数据了!<font color="red">什么??你没有备份文件<img title="点击图片可在新窗口打开" style="cursor: pointer" src="http://www.discuz.net/images/smilies/shocked.gif" align="absMiddle" border="0"  alt="" />那你就坐到那里哭吧!!开个玩笑,但是网站及时的做备份确实是很重要的,尤其当有一定的规模以后,建议每天都做备份!!</font><span style="display: none">SupeSite/X-Space官方站'^9I J n1?8f!j&amp;w xp:}</span><br />
下面说一下具体的步骤:<span style="display: none">SupeSite/X-Space官方站)[#R"^w}</span><br />
1.<span style="display: none">SupeSite/X-Space官方站r RG'^7^-t+XuO</span><br />
<img title="点击图片可在新窗口打开" style="cursor: pointer" src="http://www.discuz.net/attachments/month_0602/cmd_J9ALgyFrcWu8.jpg"  alt="" /><br />
<span style="display: none">gEVu7B} jK0</span>cmd.jpg<span style="display: none">SupeSite/X-Space官方站r sFS(V.?rH</span><br />
2.更改当前目录到mysql/bin下面,一般情况下只有在这个下面才能运行myisamchk命令<br />
<span style="display: none">;E-}&amp;xJ ^n-V2Q9W#T0</span><span style="display: none">SupeSite/X-Space官方站L5I&amp;ry R4y:j#}+w$[</span><br />
<img title="点击图片可在新窗口打开" style="width: 400px; cursor: pointer" src="http://www.discuz.net/attachments/month_0602/myisamchk_Fkge3aypKMey.jpg"  alt="" /><span style="display: none">SupeSite/X-Space官方站-er5f/?8EB'q0m`</span><br />
myisamchk.jpg<span style="display: none">SupeSite/X-Space官方站GN,}7f5C*V</span><br />
3.修复的结果,如果修复后的情况都如下图所示的话,你就可以<img title="点击图片可在新窗口打开" style="cursor: pointer" src="http://www.discuz.net/images/smilies/lol.gif" align="absMiddle" border="0"  alt="" /><img title="点击图片可在新窗口打开" style="cursor: pointer" src="http://www.discuz.net/images/smilies/lol.gif" align="absMiddle" border="0"  alt="" />了,成功了,继续开启你的网站,运行吧!!<span style="display: none">SupeSite/X-Space官方站UncL.f4f+X t</span><br />
<br />
<span style="display: none">_0O"}}&amp;uY0}0|0</span><img title="点击图片可在新窗口打开" style="width: 400px; cursor: pointer" src="http://www.discuz.net/attachments/month_0602/theresult_BXmCwpZkj538.jpg"  alt="" /><span style="display: none">SupeSite/X-Space官方站p'EwS6@#J L</span><br />
theresult.jpg<span style="display: none">SupeSite/X-Space官方站7u'?5U ~GK+Z6rU1E(t</span><br />
4.别忘了启动你的mysql,要不你的网站还是运行不起来.<img title="点击图片可在新窗口打开" style="cursor: pointer" src="http://www.discuz.net/images/smilies/titter.gif" align="absMiddle" border="0"  alt="" /><br />
<span style="display: none">Dr3C1E}BR)e"X)G0</span><span style="display: none">SupeSite/X-Space官方站Kl.J:n4v+Ha</span><br />
<img title="点击图片可在新窗口打开" style="width: 400px; cursor: pointer" src="http://www.discuz.net/attachments/month_0602/startmysql_CzOGSvzciTzc.jpg"  alt="" /><span style="display: none">SupeSite/X-Space官方站x$[/Vh^</span><br />
startmysql.jpg<br />
<span style="display: none">](e1O{+B5E-s1}!f0</span>ps:下面给的一个是linux下面的修复方法,和上面的基本相同.只是linux下面关闭和启动mysql的方法和windows的不同.一般情况下linux用<br />
<span style="display: none">O3o0].S2EE S0</span><span style="display: none">SupeSite/X-Space官方站@7Dy o!R G$u Y</span><br />
<div style="font: bold 11px Arial, Tahoma; margin-left: 2em; margin-right: 2em">
<div style="float: left">CODE:</div>
<div style="float: right; text-align: right"><a style="font: 11px Arial, Tahoma" href="http://x.discuz.net/183161/viewspace-16039.html###" nclick="copycode(findobj('code14'));"  &#111;>[Copy to clipboard]</a></div>
</div>
<div id="code14" style="clear: both; border-right: #698cc3 1px solid; padding-right: 10px; border-top: #698cc3 1px solid; padding-left: 10px; background: #ffffff; padding-bottom: 10px; margin: 3px 2em 2em; border-left: #698cc3 1px solid; word-break: break-all; padding-top: 5px; border-bottom: #698cc3 1px solid">/etc/init.d/mysql stop&nbsp;&nbsp;service mysqld stop /etc/init.d/mysql start service mysqld start </div>
来关闭和启动mysql<br />
<span style="display: none">f^Zi!y3v1S0</span><br />
<span style="display: none">nB\aV&amp;N0</span><img title="点击图片可在新窗口打开" style="width: 400px; cursor: pointer" src="http://www.discuz.net/attachments/month_0602/linux_AMlD3NCxELqb.jpg"  alt="" /><span style="display: none">SupeSite/X-Space官方站"x!@S"CH0c:`%b:S</span><br />
linux.jpg<br />
<span style="display: none">&amp;j%r.O8~.^E w0o1R0</span><br />
<span style="display: none">{&amp;y7`'P9s"TG0</span>另外 MySQL 官方文档中还提供了针对上面操作均无法奏效时的特殊办法，如先清空重建数据表，然后再用备份的数据文件覆盖等，这种特别复杂的情况用户通常不会碰到，因此这里不再做过于深入的研究。 <span style="display: none">SupeSite/X-Space官方站kH,M:It.s3nD</span><br />
<span style="display: none">SupeSite/X-Space官方站ry O:D.x A|</span><br />
三:数据表经常性损坏的解决方法<span style="display: none">SupeSite/X-Space官方站W"Y$}y)B3O^</span><br />
<br />
<span style="display: none">#DJu*ET\ AN5N0</span>--------------------------------------------------------------------------------<span style="display: none">SupeSite/X-Space官方站 U3m]5uOD-O6kD</span><br />
<span style="display: none">SupeSite/X-Space官方站%|gj%s8G8fr6j</span><br />
首先请确认在服务器硬件不存在问题（如内存工作不稳定、散热条件不好等），且使用中的操作系统版本也没有相关的 BUG 报告或升级补丁。这种情况下，如果数据库仍出现经常性的损坏，请检查是否 MySQL 的编译方式或参数存在问题。通常情况下使用官方提供的编译好的版本是比较稳定的，可以长期使用。如果您钟爱自行编译相关程序，请确认您的语言编译器（如 gcc）和配置的相关参数没有导致不稳定的因素。同时，磁盘分区满也可能是导致数据表经常性损坏的原因。网上提供了一些问题的处理方法（英文），需要时可多参考，并针对您的具体服务器环境制定解决方案。</font> <br />
<img src ="http://www.blogjava.net/lcs/aggbug/195835.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcs/" target="_blank">lk</a> 2008-04-25 09:46 <a href="http://www.blogjava.net/lcs/archive/2008/04/25/195835.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何修复损坏的MySQL数据表[转]</title><link>http://www.blogjava.net/lcs/archive/2008/04/25/195829.html</link><dc:creator>lk</dc:creator><author>lk</author><pubDate>Fri, 25 Apr 2008 01:42:00 GMT</pubDate><guid>http://www.blogjava.net/lcs/archive/2008/04/25/195829.html</guid><wfw:comment>http://www.blogjava.net/lcs/comments/195829.html</wfw:comment><comments>http://www.blogjava.net/lcs/archive/2008/04/25/195829.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcs/comments/commentRss/195829.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcs/services/trackbacks/195829.html</trackback:ping><description><![CDATA[<p>原文地址：<font style="background-color: #dee0fe">http://www.3v.org.cn/article.asp?id=164</font><br />
<font size="3"><br />
由</font>于断电或非正常关机而导致MySQL数据库出现错误是非常常见的问题。有两种方法，一种方法使用mysql的check&nbsp;table和repair&nbsp;table&nbsp;的sql语句，另一种方法是使用MySQL提供的多个myisamchk,&nbsp;isamchk数据检测恢复工具。前者使用起来比较简便。推荐使用。<br />
<br />
1.&nbsp;check&nbsp;table&nbsp;和&nbsp;repair&nbsp;table<br />
登陆mysql&nbsp;终端：<br />
mysql&nbsp;-uxxxxx&nbsp;-p&nbsp;dbname<br />
&gt;&nbsp;check&nbsp;table&nbsp;tabTest;<br />
如果出现的结果说Status是OK，则不用修复，如果有Error，可以用：<br />
&gt;&nbsp;repair&nbsp;table&nbsp;tabTest;<br />
进行修复，修复之后可以在用check&nbsp;table命令来进行检查。在新版本的phpMyAdmin里面也可以使用check/repair的功能。<br />
<br />
2.&nbsp;myisamchk,&nbsp;isamchk<br />
其中myisamchk适用于MYISAM类型的数据表，而isamchk适用于ISAM类型的数据表。这两条命令的主要参数相同，一般新的系统都使用MYISAM作为缺省的数据表类型，这里以myisamchk为例子进行说明。当发现某个数据表出现问题时可以使用：<br />
<br />
myisamchk&nbsp;tablename.MYI<br />
<br />
进行检测，如果需要修复的话，可以使用：<br />
<br />
myisamchk&nbsp;-of&nbsp;tablename.MYI<br />
<br />
关于myisamchk的详细参数说明，可以参见它的使用帮助。需要注意的时在进行修改时必须确保MySQL服务器没有访问这个数据表，保险的情况下是最好在进行检测时把MySQL服务器Shutdown掉。<br />
<br />
－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br />
<br />
另外可以把下面的命令放在你的rc.local里面启动MySQL服务器前：<br />
<br />
[&nbsp;-x&nbsp;/tmp/mysql.sock&nbsp;]&nbsp;&amp;&amp;&nbsp;/pathtochk/myisamchk&nbsp;-of&nbsp;/DATA_DIR/*/*.MYI<br />
<br />
其中的/tmp/mysql.sock是MySQL监听的Sock文件位置，对于使用RPM安装的用户应该是/var/lib/mysql/mysql.sock，对于使用源码安装则是/tmp/mysql.sock可以根据自己的实际情况进行变更，而pathtochk则是myisamchk所在的位置，DATA_DIR是你的MySQL数据库存放的位置。<br />
<br />
需要注意的时，如果你打算把这条命令放在你的rc.local里面，必须确认在执行这条指令时MySQL服务器必须没有启动！&nbsp;<br />
<br />
检测修复所有数据库(表)<br />
mysqlcheck&nbsp;-A&nbsp;-o&nbsp;-r&nbsp;-p&nbsp;<br />
---------------------------------------------------------------------------------<br />
<br />
<br />
示例:<br />
mysql&gt;&nbsp;check&nbsp;table&nbsp;tabFTPAccountInstances;<br />
</p>
<img src ="http://www.blogjava.net/lcs/aggbug/195829.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcs/" target="_blank">lk</a> 2008-04-25 09:42 <a href="http://www.blogjava.net/lcs/archive/2008/04/25/195829.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java执行存储过程</title><link>http://www.blogjava.net/lcs/archive/2008/02/19/180679.html</link><dc:creator>lk</dc:creator><author>lk</author><pubDate>Tue, 19 Feb 2008 06:49:00 GMT</pubDate><guid>http://www.blogjava.net/lcs/archive/2008/02/19/180679.html</guid><wfw:comment>http://www.blogjava.net/lcs/comments/180679.html</wfw:comment><comments>http://www.blogjava.net/lcs/archive/2008/02/19/180679.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcs/comments/commentRss/180679.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcs/services/trackbacks/180679.html</trackback:ping><description><![CDATA[<font face="Times New Roman">conn.prepareCall("{call procedure_name(?,?)}");&nbsp;&nbsp;<br />
<br />
这种调用是用一种换码语法来写的，有两种形式：一种形式带结果参，另一种形式不带结果参数。结果参数是一种输出<font face="Times New Roman"> &nbsp;(OUT) &nbsp;</font>参数，是已储存过程的返回值。两种形式都可带有数量可变的输入（<font face="Times New Roman">IN &nbsp;</font>参数）、输出（<font face="Times New Roman">OUT &nbsp;</font>参数）或输入和输出（<font face="Times New Roman">INOUT &nbsp;</font>参数）的参数。问号将用作参数的占位符。<font face="Times New Roman"> &nbsp;<br />
&nbsp;<br />
</font>　在<font face="Times New Roman"> &nbsp;JDBC &nbsp;</font>中调用已储存过程的语法如下所示。注意，方括号表示其间的内容是可选项；方括号本身并非语法的组成部份。<font face="Times New Roman"> &nbsp;<br />
{call &nbsp;</font>过程名<font face="Times New Roman">[(?, &nbsp;?, &nbsp;...)]} &nbsp;<br />
</font>　　返回结果参数的过程的语法为：<font face="Times New Roman"> &nbsp;<br />
{? &nbsp;= &nbsp;call &nbsp;</font>过程名<font face="Times New Roman">[(?, &nbsp;?, &nbsp;...)]} &nbsp;<br />
</font>　　不带参数的已储存过程的语法类似：<font face="Times New Roman"> &nbsp;<br />
{call &nbsp;</font>过程名<font face="Times New Roman">}&nbsp;&nbsp;<br />
</font><br />
通常，创建<font face="Times New Roman"> &nbsp;CallableStatement &nbsp;</font>对象的人应当知道所用的<font face="Times New Roman"> &nbsp;DBMS &nbsp;</font>是支持已储存过程的，并且知道这些过程都是些什么。然而，如果需要检查，多种<font face="Times New Roman">DatabaseMetaData &nbsp;</font>方法都可以提供这样的信息。例如，如果<font face="Times New Roman"> &nbsp;DBMS &nbsp;</font>支持已储存过程的调用，则<font face="Times New Roman">supportsStoredProcedures &nbsp;</font>方法将返回<font face="Times New Roman"> &nbsp;true</font>，而<font face="Times New Roman">getProcedures &nbsp;</font>方法将返回对已储存过程的描述。<font face="Times New Roman">CallableStatement &nbsp;</font>继承<font face="Times New Roman"> &nbsp;Statement &nbsp;</font>的方法（它们用于处理一般的<font face="Times New Roman"> &nbsp;SQL &nbsp;</font>语句），还继承了<font face="Times New Roman"> &nbsp;PreparedStatement &nbsp;</font>的方法（它们用于处理<font face="Times New Roman"> &nbsp;IN &nbsp;</font>参）。<font face="Times New Roman"> &nbsp;<br />
</font>　　<font face="Times New Roman">CallableStatement &nbsp;</font>中定义的所有方法都用于处理<font face="Times New Roman"> &nbsp;OUT &nbsp;</font>参数或<font face="Times New Roman"> &nbsp;INOUT &nbsp;</font>参数的输出部分：注册<font face="Times New Roman"> &nbsp;OUT &nbsp;</font>参数的<font face="Times New Roman"> &nbsp;JDBC &nbsp;</font>类型（一般<font face="Times New Roman"> &nbsp;SQL &nbsp;</font>类型）、从这些参数中检索结果，或者检查所返回的值是否为<font face="Times New Roman"> &nbsp;JDBC &nbsp;NULL</font>。<font face="Times New Roman"> &nbsp;<br />
1</font>、创建<font face="Times New Roman"> &nbsp;CallableStatement &nbsp;</font>对象<font face="Times New Roman"> &nbsp;<br />
</font>　　<font face="Times New Roman">CallableStatement &nbsp;</font>对象是用<font face="Times New Roman"> &nbsp;Connection &nbsp;</font>方法<font face="Times New Roman"> &nbsp;prepareCall &nbsp;</font>创建的。下例创建<font face="Times New Roman"> &nbsp;CallableStatement &nbsp;</font>的实例，其中含有对已储存过程<font face="Times New Roman"> &nbsp;getTestData &nbsp;</font>调用。该过程有两个变量，但不含结果参数：<font face="Times New Roman"> &nbsp;<br />
CallableStatement &nbsp;cstmt &nbsp;= &nbsp;con.prepareCall("{call &nbsp;getTestData(?, &nbsp;?)}"); &nbsp;<br />
</font>　　其中<font face="Times New Roman">?</font>占位符为<font face="Times New Roman">IN</font>、<font face="Times New Roman">OUT</font>还是<font face="Times New Roman">INOUT</font>参数，取决于已储存过程<font face="Times New Roman">getTestData</font>。<font face="Times New Roman"> &nbsp;<br />
2</font>、<font face="Times New Roman">IN</font>和<font face="Times New Roman">OUT</font>参数<font face="Times New Roman"> &nbsp;<br />
</font>　　将<font face="Times New Roman">IN</font>参数传给<font face="Times New Roman"> &nbsp;CallableStatement &nbsp;</font>对象是通过<font face="Times New Roman"> &nbsp;setXXX &nbsp;</font>方法完成的。该方法继承自<font face="Times New Roman"> &nbsp;PreparedStatement</font>。所传入参数的类型决定了所用的<font face="Times New Roman">setXXX</font>方法（例如，用<font face="Times New Roman"> &nbsp;setFloat &nbsp;</font>来传入<font face="Times New Roman"> &nbsp;float &nbsp;</font>值等）。<font face="Times New Roman"> &nbsp;<br />
</font>　　如果已储存过程返回<font face="Times New Roman"> &nbsp;OUT &nbsp;</font>参数，则在执行<font face="Times New Roman"> &nbsp;CallableStatement &nbsp;</font>对象以前必须先注册每个<font face="Times New Roman"> &nbsp;OUT &nbsp;</font>参数的<font face="Times New Roman"> &nbsp;JDBC &nbsp;</font>类型（这是必需的，因为某些<font face="Times New Roman"> &nbsp;DBMS &nbsp;</font>要求<font face="Times New Roman"> &nbsp;JDBC &nbsp;</font>类型）。注册<font face="Times New Roman"> &nbsp;JDBC &nbsp;</font>类型是用<font face="Times New Roman"> &nbsp;registerOutParameter &nbsp;</font>方法来完成的。语句执行完后，<font face="Times New Roman">CallableStatement &nbsp;</font>的<font face="Times New Roman"> &nbsp;getXXX &nbsp;</font>方法将取回参数值。正确的<font face="Times New Roman"> &nbsp;getXXX &nbsp;</font>方法是为各参数所注册的<font face="Times New Roman"> &nbsp;JDBC &nbsp;</font>类型所对应的<font face="Times New Roman"> &nbsp;Java &nbsp;</font>类型。换言之，<font face="Times New Roman"> &nbsp;registerOutParameter &nbsp;</font>使用的是<font face="Times New Roman"> &nbsp;JDBC &nbsp;</font>类型（因此它与数据库返回的<font face="Times New Roman"> &nbsp;JDBC &nbsp;</font>类型匹配），而<font face="Times New Roman"> &nbsp;getXXX &nbsp;</font>将之转换为<font face="Times New Roman"> &nbsp;Java &nbsp;</font>类型。<font face="Times New Roman"> &nbsp;<br />
</font>　　作为示例，下述代码先注册<font face="Times New Roman"> &nbsp;OUT &nbsp;</font>参数，执行由<font face="Times New Roman"> &nbsp;cstmt &nbsp;</font>所调用的已储存过程，然后检索在<font face="Times New Roman"> &nbsp;OUT &nbsp;</font>参数中返回的值。方法<font face="Times New Roman"> &nbsp;getByte &nbsp;</font>从第一个<font face="Times New Roman"> &nbsp;OUT &nbsp;</font>参数中取出一个<font face="Times New Roman"> &nbsp;Java &nbsp;</font>字节，而<font face="Times New Roman"> &nbsp;getBigDecimal &nbsp;</font>从第二个<font face="Times New Roman"> &nbsp;OUT &nbsp;</font>参数中取出一个<font face="Times New Roman"> &nbsp;BigDecimal &nbsp;</font>对象（小数点后面带三位数）：<font face="Times New Roman"> &nbsp;<br />
CallableStatement &nbsp;cstmt &nbsp;= &nbsp;con.prepareCall("{call &nbsp;getTestData(?, &nbsp;?)}"); &nbsp;<br />
cstmt.registerOutParameter(1, &nbsp;java.sql.Types.TINYINT); &nbsp;<br />
cstmt.registerOutParameter(2, &nbsp;java.sql.Types.DECIMAL, &nbsp;3); &nbsp;<br />
cstmt.executeQuery(); &nbsp;<br />
byte &nbsp;x &nbsp;= &nbsp;cstmt.getByte(1); &nbsp;<br />
java.math.BigDecimal &nbsp;n &nbsp;= &nbsp;cstmt.getBigDecimal(2, &nbsp;3); &nbsp;<br />
&nbsp;<br />
</font>　　<font face="Times New Roman">CallableStatement &nbsp;</font>与<font face="Times New Roman"> &nbsp;ResultSet &nbsp;</font>不同，它不提供用增量方式检索大<font face="Times New Roman"> &nbsp;OUT &nbsp;</font>值的特殊机制。<font face="Times New Roman"> &nbsp;<br />
&nbsp;<br />
3</font>、<font face="Times New Roman">INOUT</font>参数<font face="Times New Roman"> &nbsp;<br />
</font>　　既支持输入又接受输出的参数（<font face="Times New Roman">INOUT &nbsp;</font>参数）除了调用<font face="Times New Roman"> &nbsp;registerOutParameter &nbsp;</font>方法外，还要求调用适当的<font face="Times New Roman"> &nbsp;setXXX &nbsp;</font>方法（该方法是从<font face="Times New Roman"> &nbsp;PreparedStatement &nbsp;</font>继承来的）。<font face="Times New Roman">setXXX &nbsp;</font>方法将参数值设置为输入参数，而<font face="Times New Roman"> &nbsp;registerOutParameter &nbsp;</font>方法将它的<font face="Times New Roman"> &nbsp;JDBC &nbsp;</font>类型注册为输出参数。<font face="Times New Roman">setXXX &nbsp;</font>方法提供一个<font face="Times New Roman"> &nbsp;Java &nbsp;</font>值，而驱动程序先把这个值转换为<font face="Times New Roman"> &nbsp;JDBC &nbsp;</font>值，然后将它送到数据库中。这种<font face="Times New Roman"> &nbsp;IN &nbsp;</font>值的<font face="Times New Roman"> &nbsp;JDBC &nbsp;</font>类型和提供给<font face="Times New Roman"> &nbsp;registerOutParameter &nbsp;</font>方法的<font face="Times New Roman"> &nbsp;JDBC &nbsp;</font>类型应该相同。然后，要检索输出值，就要用对应的<font face="Times New Roman"> &nbsp;getXXX &nbsp;</font>方法。例如，<font face="Times New Roman">Java &nbsp;</font>类型为<font face="Times New Roman">byte &nbsp;</font>的参数应该使用方法<font face="Times New Roman"> &nbsp;setByte &nbsp;</font>来赋输入值。应该给<font face="Times New Roman">registerOutParameter &nbsp;</font>提供类型为<font face="Times New Roman"> &nbsp;TINYINT &nbsp;</font>的<font face="Times New Roman"> &nbsp;JDBC &nbsp;</font>类型，同时应使用<font face="Times New Roman"> &nbsp;getByte &nbsp;</font>来检索输出值。<font face="Times New Roman"> &nbsp;<br />
</font>　　下例假设有一个已储存过程<font face="Times New Roman"> &nbsp;reviseTotal</font>，其唯一参数是<font face="Times New Roman"> &nbsp;INOUT &nbsp;</font>参数。方法<font face="Times New Roman">setByte &nbsp;</font>把此参数设为<font face="Times New Roman"> &nbsp;25</font>，驱动程序将把它作为<font face="Times New Roman"> &nbsp;JDBC &nbsp;TINYINT &nbsp;</font>类型送到数据库中。接着，<font face="Times New Roman">registerOutParameter &nbsp;</font>将该参数注册为<font face="Times New Roman"> &nbsp;JDBC &nbsp;TINYINT</font>。执行完该已储存过程后，将返回一个新的<font face="Times New Roman"> &nbsp;JDBC &nbsp;TINYINT &nbsp;</font>值。方法<font face="Times New Roman"> &nbsp;getByte &nbsp;</font>将把这个新值作为<font face="Times New Roman"> &nbsp;Java &nbsp;byte &nbsp;</font>类型检索。<font face="Times New Roman"> &nbsp;<br />
CallableStatement &nbsp;cstmt &nbsp;= &nbsp;con.prepareCall("{call &nbsp;reviseTotal(?)}"); &nbsp;<br />
cstmt.setByte(1, &nbsp;25); &nbsp;<br />
cstmt.registerOutParameter(1, &nbsp;java.sql.Types.TINYINT); &nbsp;<br />
cstmt.executeUpdate(); &nbsp;<br />
byte &nbsp;x &nbsp;= &nbsp;cstmt.getByte(1); &nbsp;<br />
&nbsp;<br />
4</font>、先检索结果，再检索<font face="Times New Roman"> &nbsp;OUT &nbsp;</font>参数<font face="Times New Roman"> &nbsp;<br />
&nbsp;<br />
</font>　　由于某些<font face="Times New Roman"> &nbsp;DBMS &nbsp;</font>的限制，为了实现最大的可移植性，建议先检索由执行<font face="Times New Roman">CallableStatement &nbsp;</font>对象所产生的结果，然后再用<font face="Times New Roman"> &nbsp;CallableStatement.getXXX &nbsp;</font>方法来检索<font face="Times New Roman"> &nbsp;OUT &nbsp;</font>参数。如果<font face="Times New Roman"> &nbsp;CallableStatement &nbsp;</font>对象返回多个<font face="Times New Roman"> &nbsp;ResultSet &nbsp;</font>对象（通过调用<font face="Times New Roman"> &nbsp;execute &nbsp;</font>方法），在检索<font face="Times New Roman"> &nbsp;OUT &nbsp;</font>参数前应先检索所有的结果。这种情况下，为确保对所有的结果都进行了访问，必须对<font face="Times New Roman"> &nbsp;Statement &nbsp;</font>方法<font face="Times New Roman"> &nbsp;getResultSet</font>、<font face="Times New Roman">getUpdateCount &nbsp;</font>和<font face="Times New Roman">getMoreResults &nbsp;</font>进行调用，直到不再有结果为止。<font face="Times New Roman"> &nbsp;<br />
&nbsp;<br />
</font>　　检索完所有的结果后，就可用<font face="Times New Roman"> &nbsp;CallableStatement.getXXX &nbsp;</font>方法来检索<font face="Times New Roman"> &nbsp;OUT &nbsp;</font>参数中的值。<font face="Times New Roman"> &nbsp;<br />
&nbsp;<br />
5</font>、检索作为<font face="Times New Roman">OUT</font>参数的<font face="Times New Roman">NULL</font>值<font face="Times New Roman"> &nbsp;<br />
&nbsp;<br />
</font>返回到<font face="Times New Roman"> &nbsp;OUT &nbsp;</font>参数中的值可能会是<font face="Times New Roman">JDBC &nbsp;NULL</font>。当出现这种情形时，将对<font face="Times New Roman"> &nbsp;JDBC &nbsp;NULL &nbsp;</font>值进行转换以使<font face="Times New Roman"> &nbsp;getXXX &nbsp;</font>方法所返回的值为<font face="Times New Roman"> &nbsp;null</font>、<font face="Times New Roman">0 &nbsp;</font>或<font face="Times New Roman"> &nbsp;false</font>，这取决于<font face="Times New Roman">getXXX &nbsp;</font>方法类型。对于<font face="Times New Roman"> &nbsp;ResultSet &nbsp;</font>对象，要知道<font face="Times New Roman">0</font>或<font face="Times New Roman">false</font>是否源于<font face="Times New Roman">JDBCNULL</font>的唯一方法，是用方法<font face="Times New Roman">wasNull</font>进行检测。如果<font face="Times New Roman"> &nbsp;getXXX &nbsp;</font>方法读取的最后一个值是<font face="Times New Roman"> &nbsp;JDBC &nbsp;NULL</font>，则该方法返回<font face="Times New Roman"> &nbsp;true</font>，否则返回<font face="Times New Roman"> &nbsp;flase</font>。</font>
<img src ="http://www.blogjava.net/lcs/aggbug/180679.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcs/" target="_blank">lk</a> 2008-02-19 14:49 <a href="http://www.blogjava.net/lcs/archive/2008/02/19/180679.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>海量数据（数据量比较大时）的处理分析</title><link>http://www.blogjava.net/lcs/archive/2008/02/18/180396.html</link><dc:creator>lk</dc:creator><author>lk</author><pubDate>Mon, 18 Feb 2008 02:13:00 GMT</pubDate><guid>http://www.blogjava.net/lcs/archive/2008/02/18/180396.html</guid><wfw:comment>http://www.blogjava.net/lcs/comments/180396.html</wfw:comment><comments>http://www.blogjava.net/lcs/archive/2008/02/18/180396.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcs/comments/commentRss/180396.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcs/services/trackbacks/180396.html</trackback:ping><description><![CDATA[<p>海量数据处理问题是一项艰巨而复杂的任务。原因有以下几个方面：</p>
<p>一、数据量过大，数据中什么情况都可能存在。如果说有10条数据，那么大不了每条去逐一检查，人为处理，如果有上百条数据，也可以考虑，如果数据上到千万级别，甚至过亿，那不是手工能解决的了，必须通过工具或者程序进行处理，尤其海量的数据中，什么情况都可能存在，例如，数据中某处格式出了问题，尤其在程序处理时，前面还能正常处理，突然到了某个地方问题出现了，程序终止了。httpwww.itokit.com</p>
<p>二、软硬件要求高，系统资源占用率高。对海量的数据进行处理，除了好的方法，最重要的就是合理使用工具，合理分配系统资源。一般情况，如果处理的数据过TB级，小型机是要考虑的，普通的机子如果有好的方法可以考虑，不过也必须加大CPU和内存，就象面对着千军万马，光有勇气没有一兵一卒是很难取胜的。</p>
<p>三、要求很高的处理方法和技巧。这也是本文的写作目的所在，好的处理方法是一位工程师长期工作经验的积累，也是个人的经验的总结。没有通用的处理方法，但有通用的原理和规则。</p>
<p><br />
那么处理海量数据有哪些经验和技巧呢，我把我所知道的罗列一下，以供大家参考：</p>
<p>一、选用优秀的数据库工具httpwww.itokit.com<br />
现在的数据库工具厂家比较多，对海量数据的处理对所使用的数据库工具要求比较高，一般使用Oracle或者DB2，微软公司最近发布的SQL Server 2005性能也不错。另外在BI领域：数据库，数据仓库，多维数据库，数据挖掘等相关工具也要进行选择，象好的ETL工具和好的OLAP工具都十分必要，例如Informatic，Eassbase等。笔者在实际数据分析项目中，对每天6000万条的日志数据进行处理，使用SQL Server 2000需要花费6小时，而使用SQL Server 2005则只需要花费3小时。</p>
<p>二、编写优良的程序代码<br />
处理数据离不开优秀的程序代码，尤其在进行复杂数据处理时，必须使用程序。好的程序代码对数据的处理至关重要，这不仅仅是数据处理准确度的问题，更是数据处理效率的问题。良好的程序代码应该包含好的算法，包含好的处理流程，包含好的效率，包含好的异常处理机制等。</p>
<p>三、对海量数据进行分区操作<br />
对海量数据进行分区操作十分必要，例如针对按年份存取的数据，我们可以按年进行分区，不同的数据库有不同的分区方式，不过处理机制大体相同。例如SQL Server的数据库分区是将不同的数据存于不同的文件组下，而不同的文件组存于不同的磁盘分区下，这样将数据分散开，减小磁盘IO，减小了系统负荷，而且还可以将日志，索引等放于不同的分区下。</p>
<p>四、建立广泛的索引<br />
对海量的数据处理，对大表建立索引是必行的，建立索引要考虑到具体情况，例如针对大表的分组、排序等字段，都要建立相应索引，一般还可以建立复合索引，对经常插入的表则建立索引时要小心，笔者在处理数据时，曾经在一个ETL流程中，当插入表时，首先删除索引，然后插入完毕，建立索引，并实施聚合操作，聚合完成后，再次插入前还是删除索引，所以索引要用到好的时机，索引的填充因子和聚集、非聚集索引都要考虑。</p>
<p>五、建立缓存机制httpwww.itokit.com<br />
当数据量增加时，一般的处理工具都要考虑到缓存问题。缓存大小设置的好差也关系到数据处理的成败，例如，笔者在处理2亿条数据聚合操作时，缓存设置为100000条Buffer，这对于这个级别的数据量是可行的。</p>
<p>六、加大虚拟内存<br />
如果系统资源有限，内存提示不足，则可以靠增加虚拟内存来解决。笔者在实际项目中曾经遇到针对18亿条的数据进行处理，内存为1GB，1个P4 2.4G的CPU，对这么大的数据量进行聚合操作是有问题的，提示内存不足，那么采用了加大虚拟内存的方法来解决，在6块磁盘分区上分别建立了6个4096M的磁盘分区，用于虚拟内存，这样虚拟的内存则增加为 40966 + 1024 = 25600 M，解决了数据处理中的内存不足问题。</p>
<p>七、分批处理 <br />
海量数据处理难因为数据量大，那么解决海量数据处理难的问题其中一个技巧是减少数据量。可以对海量数据分批处理，然后处理后的数据再进行合并操作，这样逐个击破，有利于小数据量的处理，不至于面对大数据量带来的问题，不过这种方法也要因时因势进行，如果不允许拆分数据，还需要另想办法。不过一般的数据按天、按月、按年等存储的，都可以采用先分后合的方法，对数据进行分开处理。</p>
<p>八、使用临时表和中间表<br />
数据量增加时，处理中要考虑提前汇总。这样做的目的是化整为零，大表变小表，分块处理完成后，再利用一定的规则进行合并，处理过程中的临时表的使用和中间结果的保存都非常重要，如果对于超海量的数据，大表处理不了，只能拆分为多个小表。如果处理过程中需要多步汇总操作，可按汇总步骤一步步来，不要一条语句完成，一口气吃掉一个胖子。</p>
<p>九、优化查询SQL语句httpwww.itokit.com<br />
在对海量数据进行查询处理过程中，查询的SQL语句的性能对查询效率的影响是非常大的，编写高效优良的SQL脚本和存储过程是数据库工作人员的职责，也是检验数据库工作人员水平的一个标准，在对SQL语句的编写过程中，例如减少关联，少用或不用游标，设计好高效的数据库表结构等都十分必要。笔者在工作中试着对1亿行的数据使用游标，运行3个小时没有出结果，这是一定要改用程序处理了。</p>
<p>十、使用文本格式进行处理<br />
对一般的数据处理可以使用数据库，如果对复杂的数据处理，必须借助程序，那么在程序操作数据库和程序操作文本之间选择，是一定要选择程序操作文本的，原因为：程序操作文本速度快；对文本进行处理不容易出错；文本的存储不受限制等。例如一般的海量的网络日志都是文本格式或者csv格式（文本格式），对它进行处理牵扯到数据清洗，是要利用程序进行处理的，而不建议导入数据库再做清洗。</p>
<p>十一、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 定制强大的清洗规则和出错处理机制<br />
海量数据中存在着不一致性，极有可能出现某处的瑕疵。例如，同样的数据中的时间字段，有的可能为非标准的时间，出现的原因可能为应用程序的错误，系统的错误等，这是在进行数据处理时，必须制定强大的数据清洗规则和出错处理机制。</p>
<p>十二、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 建立视图或者物化视图<br />
视图中的数据来源于基表，对海量数据的处理，可以将数据按一定的规则分散到各个基表中，查询或处理过程中可以基于视图进行，这样分散了磁盘IO，正如10根绳子吊着一根柱子和一根吊着一根柱子的区别。</p>
<p>十三、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 避免使用32位机子（极端情况）<br />
目前的计算机很多都是32位的，那么编写的程序对内存的需要便受限制，而很多的海量数据处理是必须大量消耗内存的，这便要求更好性能的机子，其中对位数的限制也十分重要。</p>
<p>十四、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 考虑操作系统问题<br />
海量数据处理过程中，除了对数据库，处理程序等要求比较高以外，对操作系统的要求也放到了重要的位置，一般是必须使用服务器的，而且对系统的安全性和稳定性等要求也比较高。尤其对操作系统自身的缓存机制，临时空间的处理等问题都需要综合考虑。</p>
<p>十五、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用数据仓库和多维数据库存储<br />
数据量加大是一定要考虑OLAP的，传统的报表可能5、6个小时出来结果，而基于Cube的查询可能只需要几分钟，因此处理海量数据的利器是OLAP多维分析，即建立数据仓库，建立多维数据集，基于多维数据集进行报表展现和数据挖掘等。</p>
<p>十六、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用采样数据，进行数据挖掘<br />
基于海量数据的数据挖掘正在逐步兴起，面对着超海量的数据，一般的挖掘软件或算法往往采用数据抽样的方式进行处理，这样的误差不会很高，大大提高了处理效率和处理的成功率。一般采样时要注意数据的完整性和，防止过大的偏差。笔者曾经对1亿2千万行的表数据进行采样，抽取出400万行，经测试软件测试处理的误差为千分之五，客户可以接受。</p>
<p>还有一些方法，需要在不同的情况和场合下运用，例如使用代理键等操作，这样的好处是加快了聚合时间，因为对数值型的聚合比对字符型的聚合快得多。类似的情况需要针对不同的需求进行处理。<br />
海量数据是发展趋势，对数据分析和挖掘也越来越重要，从海量数据中提取有用信息重要而紧迫，这便要求处理要准确，精度要高，而且处理时间要短，得到有价值信息要快，所以，对海量数据的研究很有前途，也很值得进行广泛深入的研究。</p>
<p>原文地址是：http://www.itokit.combbsviewthread.phptid=1876</p>
<img src ="http://www.blogjava.net/lcs/aggbug/180396.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcs/" target="_blank">lk</a> 2008-02-18 10:13 <a href="http://www.blogjava.net/lcs/archive/2008/02/18/180396.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据库表结构设计方法及原则</title><link>http://www.blogjava.net/lcs/archive/2008/02/18/180392.html</link><dc:creator>lk</dc:creator><author>lk</author><pubDate>Mon, 18 Feb 2008 01:55:00 GMT</pubDate><guid>http://www.blogjava.net/lcs/archive/2008/02/18/180392.html</guid><wfw:comment>http://www.blogjava.net/lcs/comments/180392.html</wfw:comment><comments>http://www.blogjava.net/lcs/archive/2008/02/18/180392.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/lcs/comments/commentRss/180392.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcs/services/trackbacks/180392.html</trackback:ping><description><![CDATA[<p>数据库表结构设计方法及原则<br />
Author: Chancey&nbsp;<br />
&nbsp;<br />
在目前的企业信息系统中，数据库还是最佳的数据存储方式，虽然已经有很多的书籍在指导我们进行数据库设计，但应该那种方式是设计数据库的表结构的最好方法、设计时应遵从什么样的原则、四个范式如何能够用一种方式达到顺畅的应用等是我一直在思考和总结的问题，下文是我针对这几个问题根据自己的设计经历准备总结的一篇文章的提纲，欢迎大家一块进行探讨，集思广益。其中提到了领域建模的概念，但未作详细解释，希望以后能够有时间我们针对这个命题进行深入探讨。</p>
<p><br />
1)不应该针对整个系统进行数据库设计，而应该根据系统架构中的组件划分，针对每个组件所处理的业务进行组件单元的数据库设计；不同组件间所对应的数据库表之间的关联应尽可能减少，如果不同组件间的表需要外键关联也尽量不要创建外键关联，而只是记录关联表的一个主键，确保组件对应的表之间的独立性，为系统或表结构的重构提供可能性。</p>
<p>2)采用领域模型驱动的方式和自顶向下的思路进行数据库设计，首先分析系统业务，根据职责定义对象。对象要符合封装的特性，确保与职责相关的数据项被定义在一个对象之内，这些数据项能够完整描述该职责，不会出现职责描述缺失。并且一个对象有且只有一项职责，如果一个对象要负责两个或两个以上的职责，应进行分拆。</p>
<p>3)根据建立的领域模型进行数据库表的映射，此时应参考数据库设计第二范式：一个表中的所有非关键字属性都依赖于整个关键字。关键字可以是一个属性，也可以是多个属性的集合，不论那种方式，都应确保关键字能够保证唯一性。在确定关键字时，应保证关键字不会参与业务且不会出现更新异常，这时，最优解决方案为采用一个自增数值型属性或一个随机字符串作为表的关键字。</p>
<p>4)由于第一点所述的领域模型驱动的方式设计数据库表结构，领域模型中的每一个对象只有一项职责，所以对象中的数据项不存在传递依赖，所以，这种思路的数据库表结构设计从一开始即满足第三范式：一个表应满足第二范式，且属性间不存在传递依赖。</p>
<p>5)同样，由于对象职责的单一性以及对象之间的关系反映的是业务逻辑之间的关系，所以在领域模型中的对象存在主对象和从对象之分，从对象是从1－N或N－N的角度进一步主对象的业务逻辑，所以从对象及对象关系映射为的表及表关联关系不存在删除和插入异常。</p>
<p>6)在映射后得出的数据库表结构中，应再根据第四范式进行进一步修改，确保不存在多值依赖。这时，应根据反向工程的思路反馈给领域模型。如果表结构中存在多值依赖，则证明领域模型中的对象具有至少两个以上的职责，应根据第一条进行设计修正。第四范式：一个表如果满足BCNF，不应存在多值依赖。</p>
<p>7)在经过分析后确认所有的表都满足二、三、四范式的情况下，表和表之间的关联尽量采用弱关联以便于对表字段和表结构的调整和重构。并且，我认为数据库中的表是用来持久化一个对象实例在特定时间及特定条件下的状态的，只是一个存储介质，所以，表和表之间也不应用强关联来表述业务（数据间的一致性），这一职责应由系统的逻辑层来保证，这种方式也确保了系统对于不正确数据（脏数据）的兼容性。当然，从整个系统的角度来说我们还是要尽最大努力确保系统不会产生脏数据，单从另一个角度来说，脏数据的产生在一定程度上也是不可避免的，我们也要保证系统对这种情况的容错性。这是一个折中的方案。</p>
<p>8)应针对所有表的主键和外键建立索引，有针对性的（针对一些大数据量和常用检索方式）建立组合属性的索引，提高检索效率。虽然建立索引会消耗部分系统资源，但比较起在检索时搜索整张表中的数据尤其时表中的数据量较大时所带来的性能影响，以及无索引时的排序操作所带来的性能影响，这种方式仍然是值得提倡的。</p>
<p>9)尽量少采用存储过程，目前已经有很多技术可以替代存储过程的功能如&#8220;对象/关系映射&#8221;等，将数据一致性的保证放在数据库中，无论对于版本控制、开发和部署、以及数据库的迁移都会带来很大的影响。但不可否认，存储过程具有性能上的优势，所以，当系统可使用的硬件不会得到提升而性能又是非常重要的质量属性时，可经过平衡考虑选用存储过程。</p>
<p>10)当处理表间的关联约束所付出的代价（常常是使用性上的代价）超过了保证不会出现修改、删除、更改异常所付出的代价，并且数据冗余也不是主要的问题时，表设计可以不符合四个范式。四个范式确保了不会出现异常，但也可能由此导致过于纯洁的设计，使得表结构难于使用，所以在设计时需要进行综合判断，但首先确保符合四个范式，然后再进行精化修正是刚刚进入数据库设计领域时可以采用的最好办法。</p>
<p>11)设计出的表要具有较好的使用性，主要体现在查询时是否需要关联多张表且还需使用复杂的SQL技巧。</p>
<p>12)设计出的表要尽可能减少数据冗余，确保数据的准确性，有效的控制冗余有助于提高数据库的性能。</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/lcs/aggbug/180392.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcs/" target="_blank">lk</a> 2008-02-18 09:55 <a href="http://www.blogjava.net/lcs/archive/2008/02/18/180392.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据库设计理论</title><link>http://www.blogjava.net/lcs/archive/2008/02/18/180389.html</link><dc:creator>lk</dc:creator><author>lk</author><pubDate>Mon, 18 Feb 2008 01:47:00 GMT</pubDate><guid>http://www.blogjava.net/lcs/archive/2008/02/18/180389.html</guid><wfw:comment>http://www.blogjava.net/lcs/comments/180389.html</wfw:comment><comments>http://www.blogjava.net/lcs/archive/2008/02/18/180389.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcs/comments/commentRss/180389.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcs/services/trackbacks/180389.html</trackback:ping><description><![CDATA[<p>数据库设计理论</p>
<p>&nbsp;</p>
<p>一、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据库设计的几个原则</p>
<p>一个好的数据库产品不等于就是一个好的应用系统，如果不能设计一个合理的数据库模型，不仅会增加客户端与服务器端的编程和维护难度，而且会影响系统实际运行的性能。因此，要想开发出一款理想的数据库产品应遵循以下设计准则：</p>
<p>（1）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 命名规范化</p>
<p>不同的数据库产品对对象的命名有不同的要求。数据库中的各种对象的命名以及后台程序的代码编写应采用大小写敏感的字母形式，各种对象命名长度不要超过30个字符，这样便于应用系统适应不同的数据库。</p>
<p>（2）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 慎用游标(Cursor)</p>
<p>对多表和大表定义的游标（大的数据集合）而言，使用游标逐行遍历数据很容易使程序进入漫长的等待甚至死机，因此在使用游标时，可以考虑建立一个临时表，将符合条件的数据行转入临时表中，再对临时表定义游标进行操作，这时性能会得到明显提高。</p>
<p>（3）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 索引(Index)的使用</p>
<p>索引一般用于快速访问表中的数据。大型数据库有两种索引，即簇索引和非簇索引。添加任何一种索引均能提高按索引列查询的速度，但会降低插入、更新、删除操作的性能，尤其是当填充因子(Fill Factor)较大时。所以，如果要对索引较多的表进行频繁的插入、更新、删除操作，建立表和索引时应该设置较小的填充因子，以便在各项数据页中留下较多的自由空间，减少页分割及重新重新组织的工作，这样才能够提高性能。</p>
<p>（4）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据的一致性和完整性</p>
<p>为了保证数据库的一致性和完整性，设计人员往往会设计过多的表间关联，尽可能地降低数据的冗余。但是，表间关联是一种强制性措施，建立后，对父表和子表的插入、更新、删除操作均要占用系统的开销。此外，最好不要用Identify属性字段作为主键与子表关联。如果数据冗余低，数据的完整性容易得到保证，但增加了表间连接查询的操作，因此，为了提高系统的响应时间，合理的数据冗余也是必要的。</p>
<p>（5）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 事务的使用</p>
<p>事务是必须一次性完成的一组操作。虽然这些操作是单个的操作，但数据库系统能够保证这组操作要么全部都完成，要么一点都不做。正是大型数据库的这一特性，使得数据的完整性得到了极大的保证。</p>
<p>（6）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据库性能调整</p>
<p>在计算机硬件配置和网络设计确定的情况下，影响到应用系统性能的因素主要是数据库性能和客户端程序设计。大多数数据库设计员采用两步法进行数据库设计：首先进行逻辑设计，而后进行物理设计。数据库逻辑设计去除了所有冗余数据，提高了数据吞吐速度，保证了数据的完整性，清楚地表达数据元素之间的关系。而对于多表之间的关联查询（尤其是大数据表）时，其性能将会降低，同时也提高了客户端程序的编程难度，因此，物理设计需折中考虑，根据业务规则，确定关联表的数据量大小、数据项的访问频度，对此类数据表频繁的关联查询应适当提高数据冗余设计。</p>
<p>（7）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据类型的选择</p>
<p>数据类型的合理选择对于数据库的性能和操作具有很大的影响。</p>
<p>?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Identify字段不要作为表的主键与其他表关联，这将会影响到该表的数据迁移。</p>
<p>?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Text和Image字段属指针型数据，主要用来存放二进制大型对象(BLOB)。这类数据的操作相比其他数据类型较慢，因此要避开使用。</p>
<p>?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 日期型字段的优点是有众多的日期函数支持，因此，在日期的大小比较、加减操作上非常简单。但是，按照日期作为条件的查询操作也要用函数，相比其他数据类型在速度上就慢许多。这是因为用函数作为查询的条件时，服务器无法用先进的性能策略来优化查询，只能进行表扫描遍历每行。</p>
<p>二、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据库设计的基本步骤</p>
<p>对于数据库设计来说，比较统一的看法是分为5个步骤：需求分析，概念结构设计，逻辑结构设计，物理设计，数据实施和维护。</p>
<p>1．&nbsp;&nbsp;&nbsp;&nbsp; 需求分析</p>
<p>要设计一个良好的数据库系统，首先要明确应用环境对系统的要求。因此，对应用环境的需求收集和分析就是数据库设计的第一步。需求阶段收集到的基础数据和一组数据流程图是进行下一步概念设计的基础。需求分析包括以下几个方面：</p>
<p>（1）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 收集资料</p>
<p>收集资料是数据库设计人员和用户共同完成的任务。强调各级用户的参与是数据库应用系统设计的特点之一。</p>
<p>（2）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 分析整理</p>
<p>在大量资料收集完成以后，就要对资料进行分析和整理。分析的过程是对所收集到的数据进行抽象的过程。</p>
<p>（3）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据流程图</p>
<p>在系统分析中通常采用数据流程图(Data Flow Diagram)来描述系统的数据流向和对数据的处理功能。</p>
<p>（4）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据字典(Data Dictionary)</p>
<p>除了一套数据流程图外，还要从原始的数据资料中分析整理出下述数据信息：数据元素的名称、同义词、性质、取值范围、提供者、使用者、控制权限、保密要求、使用频率、数据量、数据之间联系的语义说明、各个部门对数据的要求以及数据处理要求。</p>
<p>（5）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用户确认</p>
<p>数据流程图集和数据字典的内容必须返回给用户，并且用非专业术语与用户交流。</p>
<p>需求分析阶段的成果要形成文档资料，至少包括各项业务的数据流程图及有关说明和对各类数据描述的集合，即数据字典。</p>
<p>2．&nbsp;&nbsp;&nbsp;&nbsp; 概念结构设计</p>
<p>将需求分析得到的用户需求抽象为信息结构设计及概念模型的过程就是概念结构设计，它是整个数据库设计的关键。概念建模的过程包括定义实体集、定义联系和定义属性。当这3种成分确定之后，就可以用E-R方法来进行数据库的概念设计。在设计完全局的E-R图之后，要尽量消除冗余。</p>
<p>3．&nbsp;&nbsp;&nbsp;&nbsp; 逻辑结构设计</p>
<p>数据库逻辑设计的任务是将概念结构设计阶段设计好的基本E-R图，转换成特定DBMS所支持的数据模型的过程。这样开始进入&#8220;实现设计&#8221;，需要考虑具体DBMS的性能，具体的数据模型特点。逻辑设计可分为E-R图向关系模型的转化、数据模型的优化和设计用户子模式3个过程。</p>
<p>4．&nbsp;&nbsp;&nbsp;&nbsp; 物理设计</p>
<p>对于给定的逻辑数据模型选取一个最适合应用环境的物理结构的过程，称为数据库物理设计。数据库的物理设计通常分为两步：确定数据库的物理结构，在关系数据库中主要指存取方法与存储结构：对物理结构进行评价，评价的重点的时间和空间效率。</p>
<p>5．&nbsp;&nbsp;&nbsp;&nbsp; 数据库的实施和维护</p>
<p>数据库的实施和维护过程可分数据的载入和应用程序的调试、数据库的试运行和数据库的维护与运行。</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/lcs/aggbug/180389.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcs/" target="_blank">lk</a> 2008-02-18 09:47 <a href="http://www.blogjava.net/lcs/archive/2008/02/18/180389.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>大型数据库设计原则</title><link>http://www.blogjava.net/lcs/archive/2008/02/18/180387.html</link><dc:creator>lk</dc:creator><author>lk</author><pubDate>Mon, 18 Feb 2008 01:42:00 GMT</pubDate><guid>http://www.blogjava.net/lcs/archive/2008/02/18/180387.html</guid><wfw:comment>http://www.blogjava.net/lcs/comments/180387.html</wfw:comment><comments>http://www.blogjava.net/lcs/archive/2008/02/18/180387.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcs/comments/commentRss/180387.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcs/services/trackbacks/180387.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
<p>一个好的数据库产品不等于就有一个好的应用系统，如果不能设计一个合理的数据库模型，不仅会增加客户端和服务器段程序的编程和维护的难度，而且将会影响系统实际运行的性能。一般来讲，在一个MIS系统分析、设计、测试和试运行阶段，因为数据量较小，设计人员和测试人员往往只注意到功能的实现，而很难注意到性能的薄弱之处，等到系统投入实际运行一段时间后，才发现系统的性能在降低，这时再来考虑提高系统性能则要花费更多的人力物力，而整个系统也不可避免的形成了一个打补丁工程。笔者依据多年来设计和使用数据库的经验，提出以下一些设计准则，供同仁们参考。 </p>
<p>命名的规范</p>
<p>---- 不同的数据库产品对对象的命名有不同的要求，因此，数据库中的各种对象的命名、后台程序的代码编写应采用大小写敏感的形式，各种对象命名长度不要超过30个字符，这样便于应用系统适应不同的数据库。</p>
<p>游标（Cursor）的慎用</p>
<p>---- 游标提供了对特定集合中逐行扫描的手段，一般使用游标逐行遍历数据，根据取出的数据不同条件进行不同的操作。尤其对多表和大表定义的游标（大的数据集合）循环很容易使程序进入一个漫长的等特甚至死机，笔者在某市《住房公积金管理系统》进行日终帐户滚积数计息处理时，对一个10万个帐户的游标处理导致程序进入了一个无限期的等特（后经测算需48个小时才能完成）(硬件环境：Alpha/4000 128Mram ,Sco Unix ,Sybase 11.0)，后根据不同的条件改成用不同的UPDATE语句得以在二十分钟之内完成。示例如下： <br />
Declare Mycursor cursor for select&nbsp; count_no from COUNT<br />
Open Mycursor<br />
Fetch Mycursor into @vcount_no<br />
While (@@sqlstatus=0)<br />
&nbsp;&nbsp; Begin<br />
If&nbsp; @vcount_no=&#8217;&#8217;&nbsp; 条件1<br />
操作1<br />
&nbsp; If&nbsp; @vcount_no=&#8217;&#8217;&nbsp; 条件2<br />
操作2<br />
。。。<br />
Fetch Mycursor into @vcount_no<br />
End<br />
。。。<br />
。。。<br />
改为<br />
Update COUNT set&nbsp; 操作1 for 条件1<br />
Update COUNT set&nbsp; 操作2 for 条件2<br />
。。。<br />
。。。</p>
<p>---- 在有些场合，有时也非得使用游标，此时也可考虑将符合条件的数据行转入临时表中，再对临时表定义游标进行操作，可时性能得到明显提高。笔者在某地市〈电信收费系统〉数据库后台程序设计中，对一个表（3万行中符合条件的30多行数据）进行游标操作(硬件环境：PC服务器，PII266 64Mram ,NT4.0 Ms Sqlserver 6.5)。 示例如下： </p>
<p>Create #tmp&nbsp;&nbsp; /* 定义临时表 */<br />
(字段1<br />
字段2<br />
。。。<br />
)<br />
Insert into #tmp select * from TOTAL where&nbsp; <br />
条件&nbsp; /* TOTAL中3万行 符合条件只有几十行 */<br />
Declare Mycursor cursor for select * from #tmp <br />
/*对临时表定义游标*/<br />
。。。</p>
<p>索引(Index)的使用原则</p>
<p>---- 创建索引一般有以下两个目的：维护被索引列的唯一性和提供快速访问表中数据的策略。大型数据库有两种索引即簇索引和非簇索引，一个没有簇索引的表是按堆结构存储数据，所有的数据均添加在表的尾部，而建立了簇索引的表，其数据在物理上会按照簇索引键的顺序存储，一个表只允许有一个簇索引，因此，根据B树结构，可以理解添加任何一种索引均能提高按索引列查询的速度，但会降低插入、更新、删除操作的性能，尤其是当填充因子（Fill Factor）较大时。所以对索引较多的表进行频繁的插入、更新、删除操作，建表和索引时因设置较小的填充因子，以便在各数据页中留下较多的自由空间，减少页分割及重新组织的工作。</p>
<p>数据的一致性和完整性</p>
<p>---- 为了保证数据库的一致性和完整性，设计人员往往会设计过多的表间关联（Relation），尽可能的降低数据的冗余。表间关联是一种强制性措施，建立后，对父表（Parent Table）和子表(Child Table)的插入、更新、删除操作均要占用系统的开销，另外，最好不要用Identify 属性字段作为主键与子表关联。如果数据冗余低，数据的完整性容易得到保证，但增加了表间连接查询的操作，为了提高系统的响应时间，合理的数据冗余也是必要的。使用规则（Rule）和约束（Check）来防止系统操作人员误输入造成数据的错误是设计人员的另一种常用手段，但是，不必要的规则和约束也会占用系统的不必要开销，需要注意的是，约束对数据的有效性验证要比规则快。所有这些，设计人员在设计阶段应根据系统操作的类型、频度加以均衡考虑。</p>
<p>事务的陷阱</p>
<p>---- 事务是在一次性完成的一组操作。虽然这些操作是单个的操作，SQL Server能够保证这组操作要么全部都完成，要么一点都不做。正是大型数据库的这一特性，使得数据的完整性得到了极大的保证。<br />
---- 众所周知，SQL Server为每个独立的SQL语句都提供了隐含的事务控制，使得每个DML的数据操作得以完整提交或回滚，但是SQL Server还提供了显式事务控制语句 </p>
<p>---- BEGIN TRANSACTION 开始一个事务 </p>
<p>---- COMMIT TRANSACTION 提交一个事务 </p>
<p>---- ROLLBACK TRANSACTION 回滚一个事务 </p>
<p>---- 事务可以嵌套，可以通过全局变量@@trancount检索到连接的事务处理嵌套层次。需要加以特别注意并且极容易使编程人员犯错误的是，每个显示或隐含的事物开始都使得该变量加1，每个事务的提交使该变量减1，每个事务的回滚都会使得该变量置0，而只有当该变量为0时的事务提交（最后一个提交语句时），这时才把物理数据写入磁盘。</p>
<p>数据库性能调整</p>
<p>---- 在计算机硬件配置和网络设计确定的情况下，影响到应用系统性能的因素不外乎为数据库性能和客户端程序设计。而大多数数据库设计员采用两步法进行数据库设计：首先进行逻辑设计，而后进行物理设计。数据库逻辑设计去除了所有冗余数据，提高了数据吞吐速度，保证了数据的完整性，清楚地表达数据元素之间的关系。而对于多表之间的关联查询（尤其是大数据表）时，其性能将会降低，同时也提高了客 户端程序的编程难度，因此，物理设计需折衷考虑，根据业务规则，确定对关联表的数据量大小、数据项的访问频度，对此类数据表频繁的关联查询应适当提高数据冗余设计。</p>
<p>数据类型的选择</p>
<p>---- 数据类型的合理选择对于数据库的性能和操作具有很大的影响，有关这方面的书籍也有不少的阐述，这里主要介绍几点经验。<br />
Identify字段不要作为表的主键与其它表关联，这将会影响到该表的数据迁移。</p>
<p>Text 和Image字段属指针型数据，主要用来存放二进制大型对象（BLOB）。这类数据的操作相比其它数据类型较慢，因此要避开使用。 </p>
<p>日期型字段的优点是有众多的日期函数支持，因此，在日期的大小比较、加减操作上非常简单。但是，在按照日期作为条件的查询操作也要用函数，相比其它数据类型速度上就慢许多,因为用函数作为查询的条件时，服务器无法用先进的性能策略来优化查询而只能进行表扫描遍历每行。 <br />
---- 例如：要从DATA_TAB1中（其中有一个名为DATE的日期字段）查询1998年的所有记录。 <br />
---- Select * from DATA_TAB1 where datepart(yy,DATE)=1998<br />
</p>
<img src ="http://www.blogjava.net/lcs/aggbug/180387.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcs/" target="_blank">lk</a> 2008-02-18 09:42 <a href="http://www.blogjava.net/lcs/archive/2008/02/18/180387.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据库设计的一些有效经验</title><link>http://www.blogjava.net/lcs/archive/2008/02/18/180385.html</link><dc:creator>lk</dc:creator><author>lk</author><pubDate>Mon, 18 Feb 2008 01:31:00 GMT</pubDate><guid>http://www.blogjava.net/lcs/archive/2008/02/18/180385.html</guid><wfw:comment>http://www.blogjava.net/lcs/comments/180385.html</wfw:comment><comments>http://www.blogjava.net/lcs/archive/2008/02/18/180385.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcs/comments/commentRss/180385.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcs/services/trackbacks/180385.html</trackback:ping><description><![CDATA[<p>以下是针对事务型数据库：<br />
1.是否使用联合主键？个人倾向于少采用联合主键。因为这样会降低索引的效率，联合主键一般都要用到至少一个业务字段，往往是字符串型的，而且理论上多字段的索引比单字段的索引要慢些。看上去似乎也不那么清爽。<br />
在实际的设计中，我尽量避免使用联合主键，有些时候&#8220;不得不&#8221;使用联合主键。</p>
<p>2.PK采用无意义的字段（逻辑主键）还是有意义的字段（业务主键）？个人倾向于&#8220;逻辑主键&#8221;，理由是这样设计出的数据库模型结构清晰、关系脉络清楚，往往更符合&#8220;第三范式&#8221;（虽然不是故意的，呵呵）。而且更容易避开&#8220;联合主键&#8221;，而且可以使用索引效率高的字段类型，比如int、long、number。缺点是用无意义的字段建立表间的关系，使跨表查询增多，效率下降。（矛盾无处不在，前面刚说完可以提高效率，这里马上又降低效率）。&#8220;业务主键&#8221;可以提升查询编码的简洁度和效率。<br />
个人使用实际状况，总体来说&#8220;逻辑主键&#8221;比&#8220;业务主键&#8221;执行效率低，但不会低到无法满足需求。采用&#8220;逻辑主键&#8221;比采用&#8220;业务主键&#8221;更利于数据库模型的结构、关系清晰，也更便于维护。<br />
对于分析型数据库，如数据仓库，千万不要这样做。</p>
<p>3.不要使用多对多关系？个人倾向于少使用多对多关系。这个问题其实不是数据库设计的问题了，在数据库设计中，多对多关系也仅仅存在于概念模型（E-R）阶段，物理模型不在有多对多关系，实际数据库中也不会有&#8220;多对多&#8221;关系。这是使用ORM时的问题，比如使用Hibernate，多对多关系有时会使编码看起来灵活一些，代价是效率的明显降低。<br />
个人实际使用中，设计时基本不考虑多对多关系，但编码时总会有小组成员使用一些多对多关系，自己建立多对多的ORM，使自己编码方便些，用在数据量小的地方，影响不大。大数据量，则&#8220;禁止使用&#8221;。</p>
<p>4.为每个表增加一个state字段？我习惯在设计时给每个表设一个state字段，取值0或1，默认值为1，具体业务意义或操作上的意义可以自定义。可以作为一个状态控制字段，如查询、更新、删除条件，单据是否有效（业务单据对应的表会有业务意义上的&#8220;有/无效&#8221;或&#8220;状态&#8221;字段，这种情况下，我还是会再加一个state字段），甚至仅仅是控制一条数据是否&#8220;有效&#8221;（有效的意义你自己定）。在数据迁移（如转入分析用的数据库）时也可能会发挥作用。</p>
<p>5.为每个表设置一些备用字段？没办法，我总是设计不出&#8220;完美&#8221;的数据表，给每个表加几个备用字段（我一般用字符串型，随你）可以应付&#8220;不时之需&#8221;，尤其是需要长期维护的、业务可能有临时性变动的系统。</p>
<p>6.尽量不要在一个表中存入其关联表的字段？建议不存！这样做确实可以提高查询效率，但在一个有很多表，并且关联表多的情况下，很难保持数据的一致性！数据库结构也比较糟糕。而且不存，也不会使效率十分低下。</p>
<p>7.不要去直接修改数据库？个人认为这点很重要，当需要修改时，应该先去修改模型，然后同步物理数据库，尤其是团队开发，否则要多做更多的事情来搞定，也可能会引入更多的错误。&nbsp; </p>
<img src ="http://www.blogjava.net/lcs/aggbug/180385.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcs/" target="_blank">lk</a> 2008-02-18 09:31 <a href="http://www.blogjava.net/lcs/archive/2008/02/18/180385.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据库优化设计方案</title><link>http://www.blogjava.net/lcs/archive/2008/02/15/180072.html</link><dc:creator>lk</dc:creator><author>lk</author><pubDate>Fri, 15 Feb 2008 06:13:00 GMT</pubDate><guid>http://www.blogjava.net/lcs/archive/2008/02/15/180072.html</guid><wfw:comment>http://www.blogjava.net/lcs/comments/180072.html</wfw:comment><comments>http://www.blogjava.net/lcs/archive/2008/02/15/180072.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcs/comments/commentRss/180072.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcs/services/trackbacks/180072.html</trackback:ping><description><![CDATA[<h1>数据库优化设计方案</h1>
<div id="memo">
<p>　　本文首先讨论了基于第三范式的数据库表的基本设计，着重论述了建立主键和索引的策略和方案，然后从数据库表的扩展设计和库表对象的放置等角度概述了数据库管理系统的优化方案。 </p>
<p>　　1 引言 </p>
<p>　　数据库优化的目标无非是避免磁盘I/O瓶颈、减少CPU利用率和减少资源竞争。为了便于读者阅读和理解，笔者参阅了Sybase、Informix和Oracle等大型数据库系统参考资料，基于多年的工程实践经验，从基本表设计、扩展设计和数据库表对象放置等角度进行讨论，着重讨论了如何避免磁盘I/O瓶颈和减少资源竞争，相信读者会一目了然。 </p>
<p>　　2 基于第三范式的基本表设计 </p>
<p>　　在基于表驱动的信息管理系统（MIS）中，基本表的设计规范是第三范式（3NF）。第三范式的基本特征是非主键属性只依赖于主键属性。基于第三范式的数据库表设计具有很多优点：一是消除了冗余数据，节省了磁盘存储空间；二是有良好的数据完整性限制，即基于主外键的参照完整限制和基于主键的实体完整性限制，这使得数据容易维护，也容易移植和更新；三是数据的可逆性好，在做连接（Join）查询或者合并表时不遗漏、也不重复；四是因消除了冗余数据（冗余列）， 在查询（Select）时每个数据页存的数据行就多，这样就有效地减少了逻辑I/O，每个Cash存的页面就多，也减少物理I/O；五是对大多数事务(Transaction)而言，运行性能好；六是物理设计(Physical Design)的机动性较大，能满足日益增长的用户需求。 </p>
<p>　　在基本表设计中，表的主键、外键、索引设计占有非常重要的地位，但系统设计人员往往只注重于满足用户要求，而没有从系统优化的高度来认识和重视它们。实际上，它们与系统的运行性能密切相关。现在从系统数据库优化角度讨论这些基本概念及其重要意义： </p>
<p>　　（1）主键(Primary Key)：主键被用于复杂的SQL语句时，频繁地在数据访问中被用到。一个表只有一个主键。主键应该有固定值（不能为Null或缺省值，要有相对稳定性），不含代码信息，易访问。把常用（众所周知）的列作为主键才有意义。短主键最佳（小于25bytes），主键的长短影响索引的大小，索引的大小影响索引页的大小，从而影响磁盘I/O。主键分为自然主键和人为主键。自然主键由实体的属性构成，自然主键可以是复合性的，在形成复合主键时，主键列不能太多，复合主键使得Join*作复杂化、也增加了外键表的大小。人为主键是，在没有合适的自然属性键、或自然属性复杂或灵敏度高时，人为形成的。人为主键一般是整型值（满足最小化要求），没有实际意义，也略微增加了表的大小；但减少了把它作为外键的表的大小。 </p>
<p>　　（2）外键（Foreign Key）：外键的作用是建立关系型数据库中表之间的关系（参照完整性），主键只能从独立的实体迁移到非独立的实体，成为后者的一个属性，被称为外键。 </p>
<p>　　（3）索引(Index)：利用索引优化系统性能是显而易见的，对所有常用于查询中的Where子句的列和所有用于排序的列创建索引，可以避免整表扫描或访问，在不改变表的物理结构的情况下，直接访问特定的数据列，这样减少数据存取时间；利用索引可以优化或排除耗时的分类*作；把数据分散到不同的页面上，就分散了插入的数据；主键自动建立了唯一索引，因此唯一索引也能确保数据的唯一性（即实体完整性）；索引码越小，定位就越直接；新建的索引效能最好，因此定期更新索引非常必要。索引也有代价：有空间开销，建立它也要花费时间，在进行Insert、Delete和Update*作时，也有维护代价。索引有两种：聚族索引和非聚族索引。一个表只能有一个聚族索引，可有多个非聚族索引。使用聚族索引查询数据要比使用非聚族索引快。在建索引前，应利用数据库系统函数估算索引的大小。 </p>
<p>　　① 聚族索引（Clustered Index）：聚族索引的数据页按物理有序储存，占用空间小。选择策略是，被用于Where子句的列：包括范围查询、模糊查询或高度重复的列（连续磁盘扫描）；被用于连接Join*作的列；被用于Order by和Group by子句的列。聚族索引不利于插入*作，另外没有必要用主键建聚族索引。 </p>
<p>　　② 非聚族索引（Nonclustered Index）：与聚族索引相比，占用空间大，而且效率低。选择策略是，被用于Where子句的列：包括范围查询、模糊查询（在没有聚族索引时）、主键或外键列、点（指针类）或小范围（返回的结果域小于整表数据的20%）查询；被用于连接Join*作的列、主键列（范围查询）；被用于Order by和Group by子句的列；需要被覆盖的列。对只读表建多个非聚族索引有利。索引也有其弊端，一是创建索引要耗费时间，二是索引要占有大量磁盘空间，三是增加了维护代价（在修改带索引的数据列时索引会减缓修改速度）。那么，在哪种情况下不建索引呢？对于小表（数据小于5页）、小到中表（不直接访问单行数据或结果集不用排序）、单值域（返回值密集）、索引列值太长（大于20bitys）、容易变化的列、高度重复的列、Null值列，对没有被用于Where子语句和Join查询的列都不能建索引。另外，对主要用于数据录入的，尽可能少建索引。当然，也要防止建立无效索引，当Where语句中多于5个条件时，维护索引的开销大于索引的效益，这时，建立临时表存储有关数据更有效。 </p>
<p>　　批量导入数据时的注意事项：在实际应用中，大批量的计算（如电信话单计费）用C语言程序做，这种基于主外键关系数据计算而得的批量数据（文本文件），可利用系统的自身功能函数（如Sybase的BCP命令）快速批量导入，在导入数据库表时，可先删除相应库表的索引，这有利于加快导入速度，减少导入时间。在导入后再重建索引以便优化查询。 </p>
<p>　　（4）锁：锁是并行处理的重要机制，能保持数据并发的一致性，即按事务进行处理；系统利用锁，保证数据完整性。因此，我们避免不了死锁，但在设计时可以充分考虑如何避免长事务，减少排它锁时间，减少在事务中与用户的交互，杜绝让用户控制事务的长短；要避免批量数据同时执行，尤其是耗时并用到相同的数据表。锁的征用：一个表同时只能有一个排它锁，一个用户用时，其它用户在等待。若用户数增加，则Server的性能下降，出现&#8220;假死&#8221;现象。如何避免死锁呢？从页级锁到行级锁，减少了锁征用；给小表增加无效记录，从页级锁到行级锁没有影响，若在同一页内竞争有影响，可选择合适的聚族索引把数据分配到不同的页面；创建冗余表；保持事务简短；同一批处理应该没有网络交互。 </p>
<p>　　（5）查询优化规则：在访问数据库表的数据(Access Data)时，要尽可能避免排序（Sort）、连接(Join)和相关子查询*作。经验告诉我们，在优化查询时，必须做到： </p>
<p>　　① 尽可能少的行； </p>
<p>　　② 避免排序或为尽可能少的行排序，若要做大量数据排序，最好将相关数据放在临时表中*作；用简单的键（列）排序，如整型或短字符串排序； </p>
<p>　　③ 避免表内的相关子查询； </p>
<p>　　④ 避免在Where子句中使用复杂的表达式或非起始的子字符串、用长字符串连接； </p>
<p>　　⑤ 在Where子句中多使用&#8220;与&#8221;（And）连接，少使用&#8220;或&#8221;(Or)连接； </p>
<p>　　⑥ 利用临时数据库。在查询多表、有多个连接、查询复杂、数据要过滤时，可以建临时表（索引）以减少I/O。但缺点是增加了空间开销。 </p>
<p>　　除非每个列都有索引支持，否则在有连接的查询时分别找出两个动态索引，放在工作表中重新排序。 </p>
<p>　　3 基本表扩展设计 </p>
<p>　　基于第三范式设计的库表虽然有其优越性（见本文第一部分），然而在实际应用中有时不利于系统运行性能的优化：如需要部分数据时而要扫描整表，许多过程同时竞争同一数据，反复用相同行计算相同的结果，过程从多表获取数据时引发大量的连接*作，当数据来源于多表时的连接*作；这都消耗了磁盘I/O和CPU时间。 </p>
<p>　　尤其在遇到下列情形时，我们要对基本表进行扩展设计：许多过程要频繁访问一个表、子集数据访问、重复计算和冗余数据，有时用户要求一些过程优先或低的响应时间。</p>
<p>　　如何避免这些不利因素呢？根据访问的频繁程度对相关表进行分割处理、存储冗余数据、存储衍生列、合并相关表处理，这些都是克服这些不利因素和优化系统运行的有效途径。 </p>
<p>　　3.1 分割表或储存冗余数据 </p>
<p>　　分割表分为水平分割表和垂直分割表两种。分割表增加了维护数据完整性的代价。 </p>
<p>　　水平分割表：一种是当多个过程频繁访问数据表的不同行时，水平分割表，并消除新表中的冗余数据列；若个别过程要访问整个数据，则要用连接*作，这也无妨分割表；典型案例是电信话单按月分割存放。另一种是当主要过程要重复访问部分行时，最好将被重复访问的这些行单独形成子集表（冗余储存），这在不考虑磁盘空间开销时显得十分重要；但在分割表以后，增加了维护难度，要用触发器立即更新、或存储过程或应用代码批量更新，这也会增加额外的磁盘I/O开销。 </p>
<p>　　垂直分割表（不破坏第三范式），一种是当多个过程频繁访问表的不同列时，可将表垂直分成几个表，减少磁盘I/O（每行的数据列少，每页存的数据行就多，相应占用的页就少），更新时不必考虑锁，没有冗余数据。缺点是要在插入或删除数据时要考虑数据的完整性，用存储过程维护。另一种是当主要过程反复访问部分列时，最好将这部分被频繁访问的列数据单独存为一个子集表（冗余储存），这在不考虑磁盘空间开销时显得十分重要；但这增加了重叠列的维护难度，要用触发器立即更新、或存储过程或应用代码批量更新，这也会增加额外的磁盘I/O开销。垂直分割表可以达到最大化利用Cache的目的。 </p>
<p>　　总之，为主要过程分割表的方法适用于：各个过程需要表的不联结的子集，各个过程需要表的子集，访问频率高的主要过程不需要整表。在主要的、频繁访问的主表需要表的子集而其它主要频繁访问的过程需要整表时则产生冗余子集表。 </p>
<p>　　注意，在分割表以后，要考虑重新建立索引。 </p>
<p>　　3.2 存储衍生数据 </p>
<p>　　对一些要做大量重复性计算的过程而言，若重复计算过程得到的结果相同（源列数据稳定，因此计算结果也不变），或计算牵扯多行数据需额外的磁盘I/O开销，或计算复杂需要大量的CPU时间，就考虑存储计算结果（冗余储存）。现予以分类说明： </p>
<p>　　若在一行内重复计算，就在表内增加列存储结果。但若参与计算的列被更新时，必须要用触发器更新这个新列。 </p>
<p>　　若对表按类进行重复计算，就增加新表（一般而言，存放类和结果两列就可以了）存储相关结果。但若参与计算的列被更新时，就必须要用触发器立即更新、或存储过程或应用代码批量更新这个新表。 </p>
<p>　　若对多行进行重复性计算（如排名次），就在表内增加列存储结果。但若参与计算的列被更新时，必须要用触发器或存储过程更新这个新列。 </p>
<p>　　总之，存储冗余数据有利于加快访问速度；但违反了第三范式，这会增加维护数据完整性的代价，必须用触发器立即更新、或存储过程或应用代码批量更新，以维护数据的完整性。 </p>
<p>　　3.3 消除昂贵结合 </p>
<p>　　对于频繁同时访问多表的一些主要过程，考虑在主表内存储冗余数据，即存储冗余列或衍生列（它不依赖于主键），但破坏了第三范式，也增加了维护难度。在源表的相关列发生变化时，必须要用触发器或存储过程更新这个冗余列。当主要过程总同时访问两个表时可以合并表，这样可以减少磁盘I/O*作，但破坏了第三范式，也增加了维护难度。对父子表和1：1关系表合并方法不同：合并父子表后，产生冗余表；合并1：1关系表后，在表内产生冗余数据。 </p>
<p>　　4 数据库对象的放置策略 </p>
<p>　　数据库对象的放置策略是均匀地把数据分布在系统的磁盘中，平衡I/O访问，避免I/O瓶颈。 </p>
<p>　　⑴ 访问分散到不同的磁盘，即使用户数据尽可能跨越多个设备，多个I/O运转，避免I/O竞争，克服访问瓶颈；分别放置随机访问和连续访问数据。 </p>
<p>　　⑵ 分离系统数据库I/O和应用数据库I/O。把系统审计表和临时库表放在不忙的磁盘上。 </p>
<p>　　⑶ 把事务日志放在单独的磁盘上，减少磁盘I/O开销，这还有利于在障碍后恢复，提高了系统的安全性。 </p>
<p>　　⑷ 把频繁访问的&#8220;活性&#8221;表放在不同的磁盘上；把频繁用的表、频繁做Join*作的表分别放在单独的磁盘上，甚至把把频繁访问的表的字段放在不同的磁盘上，把访问分散到不同的磁盘上，避免I/O争夺； </p>
<p>　　⑸ 利用段分离频繁访问的表及其索引（非聚族的）、分离文本和图像数据。段的目的是平衡I/O，避免瓶颈，增加吞吐量，实现并行扫描，提高并发度，最大化磁盘的吞吐量。利用逻辑段功能，分别放置&#8220;活性&#8221;表及其非聚族索引以平衡I/O。当然最好利用系统的默认段。另外，利用段可以使备份和恢复数据更加灵活，使系统授权更加灵活。</p>
</div>
<!--新闻内容//--><!--评论发布-->
<img src ="http://www.blogjava.net/lcs/aggbug/180072.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcs/" target="_blank">lk</a> 2008-02-15 14:13 <a href="http://www.blogjava.net/lcs/archive/2008/02/15/180072.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>大型数据库的设计原则与开发技巧</title><link>http://www.blogjava.net/lcs/archive/2008/02/15/180067.html</link><dc:creator>lk</dc:creator><author>lk</author><pubDate>Fri, 15 Feb 2008 06:11:00 GMT</pubDate><guid>http://www.blogjava.net/lcs/archive/2008/02/15/180067.html</guid><wfw:comment>http://www.blogjava.net/lcs/comments/180067.html</wfw:comment><comments>http://www.blogjava.net/lcs/archive/2008/02/15/180067.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcs/comments/commentRss/180067.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcs/services/trackbacks/180067.html</trackback:ping><description><![CDATA[<h1>大型数据库的设计原则与开发技巧</h1>
<div id="memo">
<p>　　随着计算机技术越来越广泛地应用于国民经济的各个领域，在计算机硬件不断微型化的同时，应用系统向着复杂化、大型化的方向发展。数据库是整个系统的核心，它的设计直接关系系统执行的效率和系统的稳定性。因此在软件系统开发中，数据库设计应遵循必要的数据库范式理论，以减少冗余、保证数据的完整性与正确性。只有在合适的数据库产品上设计出合理的数据库模型，才能降低整个系统的编程和维护难度，提高系统的实际运行效率。虽然对于小项目或中等规模的项目开发人员可以很容易地利用范式理论设计出一套符合要求的数据库，但对于一个包含大型数据库的软件项目，就必须有一套完整的设计原则与技巧。</p>
<p>　　一、成立数据小组</p>
<p>　　大型数据库数据元素多，在设计上有必要成立专门的数据小组。由于数据库设计者不一定是使用者，对系统设计中的数据元素不可能考虑周全，数据库设计出来后，往往难以找到所需的库表，因此数据小组最好由熟悉业务的项目骨干组成。</p>
<p>　　数据小组的职能并非是设计数据库，而是通过需求分析，在参考其他相似系统的基础上，提取系统的基本数据元素，担负对数据库的审核。审核内容包括审核新的数据库元素是否完全、能否实现全部业务需求;对旧数据库(如果存在旧系统)的分析及数据转换;数据库设计的审核、控制及必要调整。</p>
<p>　　二、设计原则</p>
<p>　　1.规范命名。所有的库名、表名、域名必须遵循统一的命名规则，并进行必要说明，以方便设计、维护、查询。</p>
<p>　　2.控制字段的引用。在设计时，可以选择适当的数据库设计管理工具，以方便开发人员的分布式设计和数据小组的集中审核管理。采用统一的命名规则，如果设计的字段已经存在，可直接引用;否则，应重新设计。</p>
<p>　　3.库表重复控制。在设计过程中，如果发现大部分字段都已存在，开发人员应怀疑所设计的库表是否已存在。通过对字段所在库表及相应设计人员的查询，可以确认库表是否确实重复。</p>
<p>　　4.并发控制。设计中应进行并发控制，即对于同一个库表，在同一时间只有一个人有控制权，其他人只能进行查询。</p>
<p>　　5.必要的讨论。数据库设计完成后，数据小组应与相关人员进行讨论，通过讨论来熟悉数据库，从而对设计中存在的问题进行控制或从中获取数据库设计的必要信息。</p>
<p>　　6.数据小组的审核。库表的定版、修改最终都要通过数据小组的审核，以保证符合必要的要求。</p>
<p>　　7.头文件处理。每次数据修改后，数据小组要对相应的头文件进行修改(可由管理软件自动完成)，并通知相关的开发人员，以便进行相应的程序修改。</p>
<p>　　三、设计技巧</p>
<p>　　1.分类拆分数据量大的表。对于经常使用的表(如某些参数表或代码对照表)，由于其使用频率很高，要尽量减少表中的记录数量。例如，银行的户主账表原来设计成一张表，虽然可以方便程序的设计与维护，但经过分析发现，由于数据量太大，会影响数据的迅速定位。如果将户主账表分别设计为活期户主账、定期户主账及对公户主账等，则可以大大提高查询效率。</p>
<p>　　2.索引设计。对于大的数据库表，合理的索引能够提高整个数据库的操作效率。在索引设计中，索引字段应挑选重复值较少的字段;在对建有复合索引的字段进行检索时，应注意按照复合索引字段建立的顺序进行。例如，如果对一个5万多条记录的流水表以日期和流水号为序建立复合索引，由于在该表中日期的重复值接近整个表的记录数，用流水号进行查询所用的时间接近3秒;而如果以流水号为索引字段建立索引进行相同的查询，所用时间不到1秒。因此在大型数据库设计中，只有进行合理的索引字段选择，才能有效提高整个数据库的操作效率。</p>
<p>　　3.数据操作的优化。在大型数据库中，如何提高数据操作效率值得关注。例如，每在数据库流水表中增加一笔业务，就必须从流水控制表中取出流水号，并将其流水号的数值加一。正常情况下，单笔操作的反应速度尚属正常，但当用它进行批量业务处理时，速度会明显减慢。经过分析发现，每次对流水控制表中的流水号数值加一时都要锁定该表，而该表却是整个系统操作的核心，有可能在操作时被其他进程锁定，因而使整个事务操作速度变慢。对这一问题的解决的办法是，根据批量业务的总笔数批量申请流水号，并对流水控制表进行一次更新，即可提高批量业务处理的速度。另一个例子是对插表的优化。对于大批量的业务处理，如果在插入数据库表时用普通的Insert语句，速度会很慢。其原因在于，每次插表都要进行一次I/O操作，花费较长的时间。改进后，可以用Put语句等缓冲区形式等满页后再进行I/O操作，从而提高效率。对大的数据库表进行删除时，一般会直接用Delete语句，这个语句虽然可以进行小表操作，但对大表却会因带来大事务而导致删除速度很慢甚至失败。解决的方法是去掉事务，但更有效的办法是先进行Drop操作再进行重建。</p>
<p>　　4.数据库参数的调整。数据库参数的调整是一个经验不断积累的过程，应由有经验的系统管理员完成。以Informix数据库为例，记录锁的数目太少会造成锁表的失败;逻辑日志的文件数目太少会造成插入大表失败等，这些问题都应根据实际情况进行必要的调整。</p>
<p>　　5.必要的工具。在整个数据库的开发与设计过程中，可以先开发一些小的应用工具，如自动生成库表的头文件、插入数据的初始化、数据插入的函数封装、错误跟踪或自动显示等，以此提高数据库的设计与开发效率。</p>
<p>　　6.避免长事务。对单个大表的删除或插入操作会带来大事务，解决的办法是对参数进行调整，也可以在插入时对文件进行分割。对于一个由一系列小事务顺序操作共同构成的长事务(如银行交易系统的日终交易)，可以由一系列操作完成整个事务，但其缺点是有可能因整个事务太大而使不能完成，或者，由于偶然的意外而使事务重做所需的时间太长。较好的解决方法是，把整个事务分解成几个较小的事务，再由应用程序控制整个系统的流程。这样，如果其中某个事务不成功，则只需重做该事务，因而既可节约时间，又可避免长事务。</p>
<p>　　7.适当超前。计算机技术发展日新月异，数据库的设计必须具有一定前瞻性，不但要满足当前的应用要求，还要考虑未来的业务发展，同时必须有利于扩展或增加应用系统的处理功能。</p>
<p>　　相对于中小型数据库，大型数据库的设计与开发要复杂得多，因此在设计、开发过程中，除了要遵循数据库范式理论、增加系统的一致性和完整性外，还要在总体上根据具体情况进行分布式设计，紧紧把握集中控制、统一审核的基本原则，保证数据库设计结构紧凑、分布平衡、定位迅速。在数据库操作上，要采用一定的技巧提高整个应用系统的执行效率，并注意适当超前，以适应不断变化的应用及系统发展的要求。</p>
</div>
<!--新闻内容//--><!--评论发布-->
<img src ="http://www.blogjava.net/lcs/aggbug/180067.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcs/" target="_blank">lk</a> 2008-02-15 14:11 <a href="http://www.blogjava.net/lcs/archive/2008/02/15/180067.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据库设计中的14个技巧</title><link>http://www.blogjava.net/lcs/archive/2008/02/15/180065.html</link><dc:creator>lk</dc:creator><author>lk</author><pubDate>Fri, 15 Feb 2008 06:09:00 GMT</pubDate><guid>http://www.blogjava.net/lcs/archive/2008/02/15/180065.html</guid><wfw:comment>http://www.blogjava.net/lcs/comments/180065.html</wfw:comment><comments>http://www.blogjava.net/lcs/archive/2008/02/15/180065.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcs/comments/commentRss/180065.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcs/services/trackbacks/180065.html</trackback:ping><description><![CDATA[<h1>数据库设计中的14个技巧</h1>
<div id="memo">
<p>　　1. 原始单据与实体之间的关系</p>
<p>　　可以是一对一、一对多、多对多的关系。在一般情况下，它们是一对一的关系：即一张原始单据对</p>
<p>　　应且只对应一个实体。在特殊情况下，它们可能是一对多或多对一的关系，即一张原始单证对应多个实</p>
<p>　　体，或多张原始单证对应一个实体。这里的实体可以理解为基本表。明确这种对应关系后，对我们设计</p>
<p>　　录入界面大有好处。</p>
<p>　　〖例1〗：一份员工履历资料，在人力资源信息系统中，就对应三个基本表：员工基本情况表、社会</p>
<p>　　关系表、工作简历表。这就是&#8220;一张原始单证对应多个实体&#8221;的典型例子。</p>
<p>　　2. 主键与外键</p>
<p>　　一般而言，一个实体不能既无主键又无外键。在E—R 图中, 处于叶子部位的实体, 可以定义主键，</p>
<p>　　也可以不定义主键(因为它无子孙), 但必须要有外键(因为它有父亲)。</p>
<p>　　主键与外键的设计，在全局数据库的设计中，占有重要地位。当全局数据库的设计完成以后，有个</p>
<p>　　美国数据库设计专家说：&#8220;键，到处都是键，除了键之外，什么也没有&#8221;，这就是他的数据库设计经验</p>
<p>　　之谈，也反映了他对信息系统核心(数据模型)的高度抽象思想。因为：主键是实体的高度抽象，主键与</p>
<p>　　外键的配对，表示实体之间的连接。</p>
<p>　　3. 基本表的性质</p>
<p>　　基本表与中间表、临时表不同，因为它具有如下四个特性：</p>
<p>　　(1) 原子性。基本表中的字段是不可再分解的。</p>
<p>　　(2) 原始性。基本表中的记录是原始数据（基础数据）的记录。</p>
<p>　　(3) 演绎性。由基本表与代码表中的数据，可以派生出所有的输出数据。</p>
<p>　　(4) 稳定性。基本表的结构是相对稳定的，表中的记录是要长期保存的。</p>
<p>　　理解基本表的性质后，在设计数据库时，就能将基本表与中间表、临时表区分开来。</p>
<p>　　4. 范式标准</p>
<p>　　基本表及其字段之间的关系, 应尽量满足第三范式。但是，满足第三范式的数据库设计，往往不是</p>
<p>　　最好的设计。为了提高数据库的运行效率，常常需要降低范式标准：适当增加冗余，达到以空间换时间</p>
<p>　　的目的。</p>
<p>　　〖例2〗：有一张存放商品的基本表，如表1所示。&#8220;金额&#8221;这个字段的存在，表明该表的设计不满</p>
<p>　　足第三范式，因为&#8220;金额&#8221;可以由&#8220;单价&#8221;乘以&#8220;数量&#8221;得到，说明&#8220;金额&#8221;是冗余字段。但是，增加</p>
<p>　　&#8220;金额&#8221;这个冗余字段，可以提高查询统计的速度，这就是以空间换时间的作法。</p>
<p>　　在Rose 2002中，规定列有两种类型：数据列和计算列。&#8220;金额&#8221;这样的列被称为&#8220;计算列&#8221;，而&#8220;</p>
<p>　　单价&#8221;和&#8220;数量&#8221;这样的列被称为&#8220;数据列&#8221;。</p>
<p>　　表1 商品表的表结构</p>
<p>　　商品名称 商品型号 单价 数量 金额</p>
<p>　　电视机 29吋 2,500 40 100,000</p>
<p>　　</p>
<p>　　5. 通俗地理解三个范式</p>
<p>　　通俗地理解三个范式，对于数据库设计大有好处。在数据库设计中，为了更好地应用三个范式，就</p>
<p>　　必须通俗地理解三个范式(通俗地理解是够用的理解，并不是最科学最准确的理解)：</p>
<p>　　第一范式：1NF是对属性的原子性约束，要求属性具有原子性，不可再分解；</p>
<p>　　第二范式：2NF是对记录的惟一性约束，要求记录有惟一标识，即实体的惟一性；</p>
<p>　　第三范式：3NF是对字段冗余性的约束，即任何字段不能由其他字段派生出来，它要求字段没有冗余</p>
<p>　　。</p>
<p>　　没有冗余的数据库设计可以做到。但是，没有冗余的数据库未必是最好的数据库，有时为了提高运</p>
<p>　　行效率，就必须降低范式标准，适当保留冗余数据。具体做法是：在概念数据模型设计时遵守第三范式</p>
<p>　　，降低范式标准的工作放到物理数据模型设计时考虑。降低范式就是增加字段，允许冗余。</p>
<p>　　6. 要善于识别与正确处理多对多的关系</p>
<p>　　若两个实体之间存在多对多的关系，则应消除这种关系。消除的办法是，在两者之间增加第三个实</p>
<p>　　体。这样，原来一个多对多的关系，现在变为两个一对多的关系。要将原来两个实体的属性合理地分配</p>
<p>　　到三个实体中去。这里的第三个实体，实质上是一个较复杂的关系，它对应一张基本表。一般来讲，数</p>
<p>　　据库设计工具不能识别多对多的关系，但能处理多对多的关系。</p>
<p>　　〖例3〗：在&#8220;图书馆信息系统&#8221;中，&#8220;图书&#8221;是一个实体，&#8220;读者&#8221;也是一个实体。这两个实体之</p>
<p>　　间的关系，是一个典型的多对多关系：一本图书在不同时间可以被多个读者借阅，一个读者又可以借多</p>
<p>　　本图书。为此，要在二者之间增加第三个实体，该实体取名为&#8220;借还书&#8221;，它的属性为：借还时间、借</p>
<p>　　还标志(0表示借书，1表示还书)，另外，它还应该有两个外键(&#8220;图书&#8221;的主键，&#8220;读者&#8221;的主键)，使</p>
<p>　　它能与&#8220;图书&#8221;和&#8220;读者&#8221;连接。</p>
<p>　　7. 主键PK的取值方法</p>
<p>　　PK是供程序员使用的表间连接工具，可以是一无物理意义的数字串, 由程序自动加1来实现。也可</p>
<p>　　以是有物理意义的字段名或字段名的组合。不过前者比后者好。当PK是字段名的组合时，建议字段的个</p>
<p>　　数不要太多，多了不但索引占用空间大，而且速度也慢。</p>
<p>　　8. 正确认识数据冗余</p>
<p>　　主键与外键在多表中的重复出现, 不属于数据冗余，这个概念必须清楚，事实上有许多人还不清楚</p>
<p>　　。非键字段的重复出现, 才是数据冗余！而且是一种低级冗余，即重复性的冗余。高级冗余不是字段的</p>
<p>　　重复出现，而是字段的派生出现。</p>
<p>　　〖例4〗：商品中的&#8220;单价、数量、金额&#8221;三个字段，&#8220;金额&#8221;就是由&#8220;单价&#8221;乘以&#8220;数量&#8221;派生出</p>
<p>　　来的，它就是冗余，而且是一种高级冗余。冗余的目的是为了提高处理速度。只有低级冗余才会增加数</p>
<p>　　据的不一致性，因为同一数据，可能从不同时间、地点、角色上多次录入。因此，我们提倡高级冗余(派</p>
<p>　　生性冗余)，反对低级冗余(重复性冗余)。</p>
<p>　　9. E--R图没有标准答案</p>
<p>　　信息系统的E--R图没有标准答案，因为它的设计与画法不是惟一的，只要它覆盖了系统需求的业务</p>
<p>　　范围和功能内容，就是可行的。反之要修改E--R图。尽管它没有惟一的标准答案，并不意味着可以随意</p>
<p>　　设计。好的E—R图的标准是：结构清晰、关联简洁、实体个数适中、属性分配合理、没有低级冗余。</p>
<p>　　10. 视图技术在数据库设计中很有用</p>
<p>　　与基本表、代码表、中间表不同，视图是一种虚表，它依赖数据源的实表而存在。视图是供程序员</p>
<p>　　使用数据库的一个窗口，是基表数据综合的一种形式, 是数据处理的一种方法，是用户数据保密的一种</p>
<p>　　手段。为了进行复杂处理、提高运算速度和节省存储空间, 视图的定义深度一般不得超过三层。 若三层</p>
<p>　　视图仍不够用, 则应在视图上定义临时表, 在临时表上再定义视图。这样反复交迭定义, 视图的深度就</p>
<p>　　不受限制了。</p>
<p>　　对于某些与国家政治、经济、技术、军事和安全利益有关的信息系统，视图的作用更加重要。这些</p>
<p>　　系统的基本表完成物理设计之后，立即在基本表上建立第一层视图，这层视图的个数和结构，与基本表</p>
<p>　　的个数和结构是完全相同。并且规定，所有的程序员，一律只准在视图上操作。只有数据库管理员，带</p>
<p>　　着多个人员共同掌握的&#8220;安全钥匙&#8221;，才能直接在基本表上操作。请读者想想：这是为什么？</p>
<p>　　11. 中间表、报表和临时表</p>
<p>　　中间表是存放统计数据的表，它是为数据仓库、输出报表或查询结果而设计的，有时它没有主键与</p>
<p>　　外键(数据仓库除外)。临时表是程序员个人设计的，存放临时记录，为个人所用。基表和中间表由DBA维</p>
<p>　　护，临时表由程序员自己用程序自动维护。</p>
<p>　　12. 完整性约束表现在三个方面</p>
<p>　　域的完整性：用Check来实现约束，在数据库设计工具中，对字段的取值范围进行定义时，有一个Ch</p>
<p>　　eck按钮，通过它定义字段的值城。</p>
<p>　　参照完整性：用PK、FK、表级触发器来实现。</p>
<p>　　用户定义完整性：它是一些业务规则，用存储过程和触发器来实现。</p>
<p>　　13. 防止数据库设计打补丁的方法是&#8220;三少原则&#8221;</p>
<p>　　(1) 一个数据库中表的个数越少越好。只有表的个数少了，才能说明系统的E--R图少而精，去掉了</p>
<p>　　重复的多余的实体，形成了对客观世界的高度抽象，进行了系统的数据集成，防止了打补丁式的设计；</p>
<p>　　(2) 一个表中组合主键的字段个数越少越好。因为主键的作用，一是建主键索引，二是做为子表的</p>
<p>　　外键，所以组合主键的字段个数少了，不仅节省了运行时间，而且节省了索引存储空间；</p>
<p>　　(3) 一个表中的字段个数越少越好。只有字段的个数少了，才能说明在系统中不存在数据重复，且</p>
<p>　　很少有数据冗余，更重要的是督促读者学会&#8220;列变行&#8221;，这样就防止了将子表中的字段拉入到主表中去</p>
<p>　　，在主表中留下许多空余的字段。所谓&#8220;列变行&#8221;，就是将主表中的一部分内容拉出去，另外单独建一</p>
<p>　　个子表。这个方法很简单，有的人就是不习惯、不采纳、不执行。</p>
<p>　　数据库设计的实用原则是：在数据冗余和处理速度之间找到合适的平衡点。&#8220;三少&#8221;是一个整体概</p>
<p>　　念，综合观点，不能孤立某一个原则。该原则是相对的，不是绝对的。&#8220;三多&#8221;原则肯定是错误的。试</p>
<p>　　想：若覆盖系统同样的功能，一百个实体(共一千个属性) 的E--R图，肯定比二百个实体(共二千个属性) </p>
<p>　　的E--R图，要好得多。</p>
<p>　　提倡&#8220;三少&#8221;原则，是叫读者学会利用数据库设计技术进行系统的数据集成。数据集成的步骤是将</p>
<p>　　文件系统集成为应用数据库，将应用数据库集成为主题数据库，将主题数据库集成为全局综合数据库。</p>
<p>　　集成的程度越高，数据共享性就越强，信息孤岛现象就越少，整个企业信息系统的全局E—R图中实体的</p>
<p>　　个数、主键的个数、属性的个数就会越少。</p>
<p>　　提倡&#8220;三少&#8221;原则的目的，是防止读者利用打补丁技术，不断地对数据库进行增删改，使企业数据</p>
<p>　　库变成了随意设计数据库表的&#8220;垃圾堆&#8221;，或数据库表的&#8220;大杂院&#8221;，最后造成数据库中的基本表、代</p>
<p>　　码表、中间表、临时表杂乱无章，不计其数，导致企事业单位的信息系统无法维护而瘫痪。</p>
<p>　　&#8220;三多&#8221;原则任何人都可以做到，该原则是&#8220;打补丁方法&#8221;设计数据库的歪理学说。&#8220;三少&#8221;原则</p>
<p>　　是少而精的原则，它要求有较高的数据库设计技巧与艺术，不是任何人都能做到的，因为该原则是杜绝</p>
<p>　　用&#8220;打补丁方法&#8221;设计数据库的理论依据。</p>
<p>　　14. 提高数据库运行效率的办法</p>
<p>　　在给定的系统硬件和系统软件条件下，提高数据库系统的运行效率的办法是：</p>
<p>　　(1) 在数据库物理设计时，降低范式，增加冗余, 少用触发器, 多用存储过程。</p>
<p>　　(2) 当计算非常复杂、而且记录条数非常巨大时(例如一千万条)，复杂计算要先在数据库外面，以</p>
<p>　　文件系统方式用C++语言计算处理完成之后，最后才入库追加到表中去。这是电信计费系统设计的经验。</p>
<p>　　(3) 发现某个表的记录太多，例如超过一千万条，则要对该表进行水平分割。水平分割的做法是，</p>
<p>　　以该表主键PK的某个值为界线，将该表的记录水平分割为两个表。若发现某个表的字段太多，例如超过</p>
<p>　　八十个，则垂直分割该表，将原来的一个表分解为两个表。</p>
<p>　　(4) 对数据库管理系统DBMS进行系统优化，即优化各种系统参数，如缓冲区个数。</p>
<p>　　(5) 在使用面向数据的SQL语言进行程序设计时，尽量采取优化算法。</p>
<p>　　总之，要提高数据库的运行效率，必须从数据库系统级优化、数据库设计级优化、程序实现级优化</p>
<p>　　，这三个层次上同时下功夫。</p>
<p>　　上述十四个技巧，是许多人在大量的数据库分析与设计实践中，逐步总结出来的。对于这些经验的</p>
<p>　　运用，读者不能生帮硬套，死记硬背，而要消化理解，实事求是，灵活掌握。并逐步做到：在应用中发</p>
<p>　　展，在发展中应用。</p>
</div>
<!--新闻内容//--><!--评论发布-->
<img src ="http://www.blogjava.net/lcs/aggbug/180065.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcs/" target="_blank">lk</a> 2008-02-15 14:09 <a href="http://www.blogjava.net/lcs/archive/2008/02/15/180065.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据库性能基准的5个问题</title><link>http://www.blogjava.net/lcs/archive/2008/02/15/180063.html</link><dc:creator>lk</dc:creator><author>lk</author><pubDate>Fri, 15 Feb 2008 06:08:00 GMT</pubDate><guid>http://www.blogjava.net/lcs/archive/2008/02/15/180063.html</guid><wfw:comment>http://www.blogjava.net/lcs/comments/180063.html</wfw:comment><comments>http://www.blogjava.net/lcs/archive/2008/02/15/180063.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcs/comments/commentRss/180063.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcs/services/trackbacks/180063.html</trackback:ping><description><![CDATA[<h1>数据库性能基准的5个问题</h1>
<div id="memo">
<p>　　<strong taggedby="hylanda">简介</strong></p>
<p>　　数据库已经是绝大多数IT应用的核心，各种数据库看上去很大不同，多层体系结构以及SOA的发展，使得应用逻辑的实现前移。数据库的性能，与其功能相比较，变得越来越重要了。因此，性能是衡量数据库的非常重要的方面，我们这里将讨论数据库性能基准的五个常见问题。</p>
<p>　　<strong taggedby="hylanda">1.Windows和Linux，哪个操作系统的性能基准结果更好？</strong></p>
<p>　　这是一个有争议的很难回答的问题。虽然大部分可能认为Linux可能更快一些，但是Windows server平台在过去的几年中已经快速成熟了。下面是图表1,它是在相同的硬件环境下执行得到的在线TPC-C基准结果的图表，使用了32位和64位的Windows 2003 Server Release 2 和 CentOS 4 Update 3 (一个免费Redhat的企业版本)。</p>
<p>　　你可以看到，技术上看来是不分胜负的。因此,你可以按自己意愿选择，或者考虑到培训成本，可以选择拥有较多系统管理员的那个操作系统。</p>
<p align="center">　<img src="http://soft6.com/upload/news/9/95336/1157000013s.jpeg"  alt="" /></p>
<p align="center">　　图1</p>
<p>　　<strong taggedby="hylanda">2. 32位还是64位，哪种更好?这会影响操作系统的选择吗?</strong></p>
<p>　　64位Unix 服务器已经有很多年了,但64位的Windows操作系统才刚刚变成现实。(Windows NT可运行在DEC Alpha上,但一直没有真正进入主流。)很长一段时间，AMD的Athlon-64和Opteron处理器一直很出色。直到2006年中Intel的二代双核CPU的出现，它的表现相当让人惊讶！现在我们可以用更好的价格购买这些硬件。我们将能耗和房间制冷都计算到TCO中。</p>
<p>　　与32位相比，64位真的有明显差异吗?根据图表1,回答是否定的。但那是因为64位提供的主要优势在于增加了可寻址内存。图表2将再次显示TPC-C基准执行的结果，但系统和数据库可以分配的内存的总数量增加了。　</p>
<p align="center">　　<img src="http://soft6.com/upload/news/9/95336/1157000014s.jpeg"  alt="" /></p>
<p align="center">　　图2</p>
<p>　　我们有了这些很清楚的结果。这些数据显示,如果你的服务器有2GB或少一些的内存,在32位和64位的处理下没有明显的差别。但当你的服务器的内存增加到超过2GB以后,64位的优势就会显示出来.尽管诸如Oracle数据库有32位联接选项来欺骗数据库，使之可以访问稍多的内存(知名的巨大内存模型)，这仅仅只能有一点效果。特大内存对系统和数据库来说，可以不断实现性能的改进。</p>
<p>　　一般情况下，服务器的内存大于4GB时，建议使用64位。不过值得注意的是，有时某些类型的硬件（例如驱动器，iSCS）和更新的数据库选项(例如，ASM,OCFS)在32位的Linux上工作得更好。</p>
<p>　　<strong taggedby="hylanda">3.哪个数据库拥有最好的性能基准：Oracle 10g，SQL Server 2005 还是MySQL 5.0?</strong></p>
<p>　　这也是一个有争议的问题。说到它，仅仅是把经常提到最多的三个数据库拿来讨论。（这里并不是有意忽略DB2－UDB，PostgreSQL或所有的其他数据库）。我们知道数据库厂商一般是不欢迎公布性能基准数据的，特别是在它们之间的比较情况。尽管如此，我们来讨论这个常见的问题。图表3显示了在MySQL,SQL Server和Oracle数据库上执行的TPC－C基准的结果。 </p>
<p align="center">　<img src="http://www.soft6.com/upload/news/9/95336/1157000015s.jpeg"  alt="" /></p>
<p align="center">　　图3</p>
<p>　　碰巧的是我们不必冒任何厂商愤怒的风险，因为性能结果显示，它们的技术不分胜负。同样，你可以按照你的意愿选择数据库，或者是哪个数据库管理员多就选择哪一个。</p>
<p>　　当然，在这些厂商之间的花费是不同的，但是因为没有人会按照报价购买产品，所以按照这个因素进行比较TPC-C是很困难的。</p>
<p>　　<strong taggedby="hylanda">4.如何确定一个服务器所能支持的最大并发OLTP用户数?</strong></p>
<p>　　这始终是一个很难回答得问题，因为人们经常想听到，&#8220;Dell 1850能处理多少的并发用户量。&#8221;事实上，即使是同一系列的服务器，有相同的内存容量，但是也会由于CPU的数量、CPU的时钟频率、CPU的内核数、高速缓冲存储器的大小等因素导致能力的差异。比较服务器是很困难的，除非你有看起来几乎一样配置的机器。但是你也需要比较相同的网络和磁盘IO等情况。假设你那样做，问题变成你如何分析这样的基准结果，并准确确定那台服务器的最大并发用户负载。图表4显示了TPC-C基准的结果，只在一台服务器上确定拐点（即用户负载开始对响应时间有负面影响）。</p>
<p align="center">　　<img src="http://soft6.com/upload/news/9/95336/1157000016s.jpeg"  alt="" /></p>
<p align="center">　　图4</p>
<p>　　如果你的最终用户要求响应时间（最常见的指标）少于2秒，那么在200个并发用户这个点你应该停下来。图4显示这个服务器可支持多达250个用户并发直到响应时间达到无法接受的急骤上升的点. 在这种情况下，TPS比率开始趋于平缓或减少，这个例子中碰巧，这两个点同时出现。但是并不总是如此明显;这是因为有时两个拐点并不一定排列的这么整齐。当拿不准时，建议通常关注TPC-C或OLTP类型事务的响应时间。</p>
<p>　　<strong taggedby="hylanda">5.如何确定一个服务器所能支持的最大数据仓库大小?</strong></p>
<p>　　这又是一个很难回答的问题，因为大多数人想听到是，&#8220;处理X千兆字节的数据需要一台Dell 1850。&#8221;上文中提到，比较服务器是不容易的事情，除非你拥有的主机几乎有一样的配置，以及一样的网络和磁盘I/O环境。磁盘I/O在这里是特别重要的，因为TPC-H结果大部分是由磁盘数量来决定的。如果能比较服务器，那么问题就变为如何从基准结果中确定那台指定服务器的最大数据仓库的大小。在图表5中，显示了基于几个强大的Oracle RAC服务器配置的TPC-H基准的测试结果。这些服务器访问分布在多个SAN和超过100个磁盘上的300GB数据。</p>
<p align="center">　　<img src="http://soft6.com/upload/news/9/95336/1157000017s.jpeg"  alt="" /></p>
<p align="center">　　图5</p>
<p>　　在TPC-H中，值得注意的是，应该同时关注整体运行时和间平均响应时间。TPC-H的询问是非常复杂的，通常要花数个小时，或好几天才能完成。</p>
<p>　　根据图表6，最好的硬件配置大运行5小时，平均响应时间约4小时。然而，通过几次运行时间很长的测试，实际的响应时间的变化是很倾斜的。因此，如果你的用户对于高度复杂的决策支持查询能接受运行时间在4个小时的，8个节点的集群将可以满足要求。如果不能接受的话，那么需要购买更多磁盘，而不是增加更多的服务器。对于千兆容量的数据仓库，使用500到1000个磁盘可以达到最佳的效果，这种情况并不少见。</p>
<p align="center">　　<img src="http://soft6.com/upload/news/9/95336/1158000018s.jpeg"  alt="" /></p>
<p align="center">　　图5</p>
</div>
<!--新闻内容//--><!--评论发布-->
<img src ="http://www.blogjava.net/lcs/aggbug/180063.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcs/" target="_blank">lk</a> 2008-02-15 14:08 <a href="http://www.blogjava.net/lcs/archive/2008/02/15/180063.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SQL数据库使用JOIN的优化方法</title><link>http://www.blogjava.net/lcs/archive/2008/02/15/180060.html</link><dc:creator>lk</dc:creator><author>lk</author><pubDate>Fri, 15 Feb 2008 06:02:00 GMT</pubDate><guid>http://www.blogjava.net/lcs/archive/2008/02/15/180060.html</guid><wfw:comment>http://www.blogjava.net/lcs/comments/180060.html</wfw:comment><comments>http://www.blogjava.net/lcs/archive/2008/02/15/180060.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcs/comments/commentRss/180060.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcs/services/trackbacks/180060.html</trackback:ping><description><![CDATA[<h1>SQL数据库使用JOIN的优化方法</h1>
<div id="memo">
<p>　　很早以前，也是一提到SQL Server，就觉得它的性能没法跟Oracle相比，一提到大数据处理就想到Oracle。自己一路走来，在本地blog上记录了很多优化方面的 post，对的错的都有，没有时间系列的整理出来，这篇文章将join方法的概念稍微整理在一起，给大家个参考。通过查资料了解里面提到的各种概念，在实 际中不断验证总结，完全可以对数据库一步步深入理解下去的。</p>
<p>　　我只对SQL Server 2000比较了解，但这并不阻碍我在Oracle、MySql进行SQL调优、产品架构，因为在数据库理论原理上，各大数据库基本出入不大，对数据库的深入理解，也不会影响你架构设计思想变坏，相反给你带来的是更深层次的思考。 </p>
<p>　　关于执行计划的说明</p>
<p>　　在SQL Server查询分析器的Query菜单中选择Show Execution Plan，运行SQL查询语句，在结果窗口中有Grid、Execution Plan、Messages三个Tab。看图形形式的执行计划，顺序是从右到左，这也是执行的顺序。执行计划中的每一个图标表示一个操作，每一个操作都会 有一个或多个输入，也会有一个或多个输出。输入和输出，有可能是一个物理数据表、索引数据结构，或者是执行过程中的一些中间结果集/数据结构。鼠标移动到 图标上，会显示这个操作的具体信息，例如逻辑和物理操作名称、记录的数量和大小、I/O成本、CPU成本、操作的具体表达式（参数Argument）。鼠 标移动到连接箭头上，会显示箭头起始端的操作输出结果集的记录数、记录的大小，一般情况下可以将这个输出结果集理解为箭头结束端的输入。 </p>
<p>　　另 外关于执行计划的一些补充说明：1. 执行计划中显示的信息，都是一个&#8220;评估&#8221;的结果，不是100%准确的信息，例如记录数量是取自统计信息，I/O成本、CPU成本来自执行计划生成过程中基 于统计信息等得出的评估结果。2. 执行计划不一定准确，一方面受SQL Server维护的统计信息准确性的影响，另一方面SQL语句编译时刻与执行时刻的环境（内存使用状况、CPU状况等）可能会不一样。 </p>
<p>　　关于统计信息、I/O成本和CPU成本的评估、SQL语句的编译和执行过程，这里不再深入。另外尽管执行计划不一定准确，但它仍是SQL语句分析最重要的依据，因为你可以理解为，绝大部分情况下，SQL Server是以这种方式来执行的。</p>
<p>　　JOIN方法说明 </p>
<p>　　数据库中，象tableA inner join tableB、tableA left out join tableB这样的SQL语句是如何执行join操作的？就是说SQL Server使用什么算法实现两个表数据的join操作？</p>
<p>　　SQL Server 2000有三种方式：nested loop、merge、hash。Oracle也是使用这三种方式，不过Oracle选择使用nested loop的条件跟SQL Server有点差别，内存管理机制跟SQL Server不一样，因此查看执行计划，Oracle中nested loop运用非常多，而merge和hash方式相对较少，SQL Server中，merge跟hash方式则是非常普遍。</p>
<p>　　以SQL Server 2000为例对这三种方式进行说明，穿插在里面讲解执行计划的一些初级使用。</p>
<p>　　1. nested loop join </p>
<p>　　1.1 示例SQL </p>
<p>　　select ... from tableA inner join tableB on tableA.col1=tableB.col1 where tableA.col2=? and tableB.col2=?tableA中没有建立任何索引，tableB中在col1上有建立一个主键（聚集索引）。 </p>
<p>　　1.2 算法伪代码描述 </p>
<p>　　foreach rowA in tableA where tableA.col2=?{search rowsB from tableB where tableB.col1=rowA.col1 and tableB.col2=? ;if(rowsB.Count＜=0)discard rowA ;elseoutput rowA and rowsB ;} </p>
<p>　　join操作有两个输入，上面例子中tableA是outer input，用于外层循环；tableB是inner input，用于循环内部。下面针对执行计划描述一下SQL Server完成这个操作的具体步骤。 %. ^ g.L </p>
<p>　　2vt [ AhVA </p>
<p>　　1.3 查看执行计划方法</p>
<p>　　移到文章最前面。 </p>
<p>　　1.4 执行步骤 </p>
<p>　　下 面是示例SQL的执行计划图。 nested loop操作的右边，位于上面的是outer input，位于下面的是inner input。你不能够根据join中哪个表出现在前面来确定outer input和inner input关系，而必须从执行计划中来确定，因为SQL Server会自动选择哪个作为inner input。</p>
</div>
<!--新闻内容//--><!--评论发布-->
<img src ="http://www.blogjava.net/lcs/aggbug/180060.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcs/" target="_blank">lk</a> 2008-02-15 14:02 <a href="http://www.blogjava.net/lcs/archive/2008/02/15/180060.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MySQL语句优化的原则</title><link>http://www.blogjava.net/lcs/archive/2008/02/15/180059.html</link><dc:creator>lk</dc:creator><author>lk</author><pubDate>Fri, 15 Feb 2008 06:01:00 GMT</pubDate><guid>http://www.blogjava.net/lcs/archive/2008/02/15/180059.html</guid><wfw:comment>http://www.blogjava.net/lcs/comments/180059.html</wfw:comment><comments>http://www.blogjava.net/lcs/archive/2008/02/15/180059.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcs/comments/commentRss/180059.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcs/services/trackbacks/180059.html</trackback:ping><description><![CDATA[<h1>MySQL语句优化的原则</h1>
<div id="memo">
<p>　　1、使用索引来更快地遍历表。 </p>
<p>　　缺省情况下建立的索引是非群集索引，但有时它并不是最佳的。在非群集索引下，数据在物理上随机存放在数据页上。合理的索引设计要建立在对各种查询的分析和预测上。一般来说： </p>
<p>　　a.有大量重复值、且经常有范围查询（ &gt; ,&lt;，&gt; =,&lt;=）和order by、group by发生的列，可考虑建立群集索引； </p>
<p>　　b.经常同时存取多列，且每列都含有重复值可考虑建立组合索引； </p>
<p>　　c.组合索引要尽量使关键查询形成索引覆盖，其前导列一定是使用最频繁的列。索引虽有助于提高性能但不是索引越多越好，恰好相反过多的索引会导致系统低效。用户在表中每加进一个索引，维护索引集合就要做相应的更新工作。 </p>
<p>　　2、在海量查询时尽量少用格式转换。 </p>
<p>　　3、ORDER BY和GROPU BY使用ORDER BY和GROUP BY短语，任何一种索引都有助于SELECT的性能提高。 </p>
<p>　　4、任何对列的操作都将导致表扫描，它包括数据库函数、计算表达式等等，查询时要尽可能将操作移至等号右边。 </p>
<p>　　5、IN、OR子句常会使用工作表，使索引失效。如果不产生大量重复值，可以考虑把子句拆开。拆开的子句中应该包含索引。 </p>
<p>　　6、只要能满足你的需求，应尽可能使用更小的数据类型：例如使用MEDIUMINT代替INT </p>
<p>　　7、尽量把所有的列设置为NOT NULL，如果你要保存NULL，手动去设置它，而不是把它设为默认值。 </p>
<p>　　8、尽量少用VARCHAR、TEXT、BLOB类型 </p>
<p>　　9、如果你的数据只有你所知的少量的几个。最好使用ENUM类型 </p>
<p>　　10、正如graymice所讲的那样，建立索引。 </p>
<p>　　以下是我做的一个实验，可以发现索引能极大地提高查询的效率： </p>
<p>　　我有一个会员信息表users，里边有37365条用户记录： </p>
<p>　　在不加索引的时候进行查询： </p>
<p>　　sql语句A: </p>
<p>　　select * from users where username like '%许%'; </p>
<p>　　在Mysql-Front中的8次查询时长为：1.40,0.54,0.54,0.54,0.53,0.55,0.54 共找到960条记录 </p>
<p>　　sql语句B: </p>
<p>　　select * from users where username like '许%'; </p>
<p>　　在Mysql-Front中的8次查询时长为：0.53,0.53,0.53,0.54,0.53,0.53,0.54,0.54 共找到836条记录 </p>
<p>　　sql语句C: </p>
<p>　　select * from users where username like '%许'; </p>
<p>　　在Mysql-Front中的8次查询时长为：0.51,0.51,0.52,0.52,0.51,0.51,0.52,0.51 共找到7条记录 </p>
<p>　　为username列添加索引: </p>
<p>　　create index usernameindex on users(username(6)); </p>
<p>　　再次查询： </p>
<p>　　sql语句A: </p>
<p>　　select * from users where username like '%许%'; </p>
<p>　　在Mysql-Front中的8次查询时长为：0.35,0.34,0.34,0.35,0.34,0.34,0.35,0.34 共找到960条记录 </p>
<p>　　sql语句B: </p>
<p>　　select * from users where username like '许%'; </p>
<p>　　在Mysql-Front中的8次查询时长为：0.06,0.07,0.07,0.07,0.07,0.07,0.06,0.06 共找到836条记录 </p>
<p>　　sql语句C: </p>
<p>　　select * from users where username like '%许'; </p>
<p>　　在Mysql-Front中的8次查询时长为：0.32,0.31,0.31,0.32,0.31,0.32,0.31,0.31 共找到7条记录 </p>
<p>　　在实验过程中，我没有另开任何程序，以上的数据说明在单表查询中，建立索引的可以极大地提高查询速度。 </p>
<p>　　另外要说的是如果建立了索引，对于like '许%'类型的查询，速度提升是最明显的。因此，我们在写sql语句的时候也尽量采用这种方式查询。 </p>
<p>　　对于多表查询我们的优化原则是： </p>
<p>　　尽量将索引建立在：left join on/right join on ...　＋条件，的条件语句中所涉及的字段上。 </p>
<p>　　多表查询比单表查询更能体现索引的优势。 </p>
<p>　　11、索引的建立原则： </p>
<p>　　如果一列的中数据的前缀重复值很少，我们最好就只索引这个前缀。Mysql支持这种索引。我在上面用到的索引方法就是对username最左边的6个字符进行索引。索引越短，占用的 磁盘空间越少，在检索过程中花的时间也越少。这方法可以对最多左255个字符进行索引。 </p>
<p>　　在很多场合，我们可以给建立多列数据建立索引。 </p>
<p>　　索引应该建立在查询条件中进行比较的字段上，而不是建立在我们要找出来并且显示的字段上 </p>
<p>　　12、一往情深问到的问题:IN、OR子句常会使用工作表，使索引失效。如果不产生大量重复值，可以考虑把子句拆开。拆开的子句中应该包含索引。 </p>
<p>　　这句话怎么理解决，请举个例子 </p>
<p>　　例子如下: </p>
<p>　　如果在fields1和fields2上同时建立了索引，fields1为主索引 </p>
<p>　　以下sql会用到索引 </p>
<p>　　select * from tablename1 where fields1='value1' and fields2='value2' </p>
<p>　　以下sql不会用到索引 </p>
<p>　　select * from tablename1 where fields1='value1' or fields2='value2' </p>
<p>　　13.索引带来查询上的速度的大大提升,但索引也占用了额外的硬盘空间(当然现在一般硬盘空间不成问题),而且往表中插入新记录时索引也要随着更新这也需要一定时间. </p>
<p>　　有些表如果经常insert,而较少select,就不用加索引了.不然每次写入数据都要重新改写索引,花费时间; 这个视实际情况而定,通常情况下索引是必需的. </p>
<p>　　14.我在对查询效率有怀疑的时候,一般是直接用Mysql的Explain来跟踪查询情况. </p>
<p>　　你用Mysql-Front是通过时长来比较,我觉得如果从查询时扫描字段的次数来比较更精确一些.</p>
</div>
<!--新闻内容//--><!--评论发布-->
<img src ="http://www.blogjava.net/lcs/aggbug/180059.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcs/" target="_blank">lk</a> 2008-02-15 14:01 <a href="http://www.blogjava.net/lcs/archive/2008/02/15/180059.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>完全优化MySQL数据库性能的八大巧方法</title><link>http://www.blogjava.net/lcs/archive/2008/02/15/180056.html</link><dc:creator>lk</dc:creator><author>lk</author><pubDate>Fri, 15 Feb 2008 05:55:00 GMT</pubDate><guid>http://www.blogjava.net/lcs/archive/2008/02/15/180056.html</guid><wfw:comment>http://www.blogjava.net/lcs/comments/180056.html</wfw:comment><comments>http://www.blogjava.net/lcs/archive/2008/02/15/180056.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcs/comments/commentRss/180056.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcs/services/trackbacks/180056.html</trackback:ping><description><![CDATA[<h1>完全优化MySQL数据库性能的八大巧方法</h1>
<div id="memo">
<p>　　1、选取最适用的字段属性</p>
<p>　　MySQL可以很好的支持大数据量的存取，但是一般说来，数据库中的表越小，在它上面执行的查询也就会越快。因此，在创建表的时候，为了获得更好的性能，我们可以将表中字段的宽度设得尽可能小。例如，在定义邮政编码这个字段时，如果将其设置为CHAR(255),显然给数据库增加了不必要的空间，甚至使用VARCHAR这种类型也是多余的，因为CHAR(6)就可以很好的完成任务了。同样的，如果可以的话，我们应该使用MEDIUMINT而不是BIGIN来定义整型字段。</p>
<p>　　另外一个提高效率的方法是在可能的情况下，应该尽量把字段设置为NOT NULL，这样在将来执行查询的时候，数据库不用去比较NULL值。</p>
<p>　　对于某些文本字段，例如&#8220;省份&#8221;或者&#8220;性别&#8221;，我们可以将它们定义为ENUM类型。因为在MySQL中，ENUM类型被当作数值型数据来处理，而数值型数据被处理起来的速度要比文本类型快得多。这样，我们又可以提高数据库的性能。</p>
<p>　　2、使用连接（JOIN）来代替子查询(Sub-Queries)</p>
<p>　　MySQL从4.1开始支持SQL的子查询。这个技术可以使用SELECT语句来创建一个单列的查询结果，然后把这个结果作为过滤条件用在另一个查询中。例如，我们要将客户基本信息表中没有任何订单的客户删除掉，就可以利用子查询先从销售信息表中将所有发出订单的客户ID取出来，然后将结果传递给主查询，如下所示：</p>
<p>　　DELETE FROM customerinfo WHERE CustomerID NOT in (SELECT CustomerID FROM salesinfo )</p>
<p>　　使用子查询可以一次性的完成很多逻辑上需要多个步骤才能完成的SQL操作，同时也可以避免事务或者表锁死，并且写起来也很容易。但是，有些情况下，子查询可以被更有效率的连接（JOIN）.. 替代。例如，假设我们要将所有没有订单记录的用户取出来，可以用下面这个查询完成：</p>
<p>　　SELECT * FROM customerinfo WHERE CustomerID NOT in (SELECT CustomerID FROM salesinfo )</p>
<p>　　如果使用连接（JOIN）.. 来完成这个查询工作，速度将会快很多。尤其是当salesinfo表中对CustomerID建有索引的话，性能将会更好，查询如下：</p>
<p>　　SELECT * FROM customerinfo LEFT JOIN salesinfoON customerinfo.CustomerID=salesinfo. CustomerID WHERE salesinfo.CustomerID IS NULL</p>
<p>　　连接（JOIN）.. 之所以更有效率一些，是因为 MySQL不需要在内存中创建临时表来完成这个逻辑上的需要两个步骤的查询工作。</p>
<p>　　3、使用联合(UNION)来代替手动创建的临时表</p>
<p>　　MySQL 从 4.0 的版本开始支持 UNION 查询，它可以把需要使用临时表的两条或更多的 SELECT 查询合并的一个查询中。在客户端的查询会话结束的时候，临时表会被自动删除，从而保证数据库整齐、高效。使用 UNION 来创建查询的时候，我们只需要用 UNION作为关键字把多个 SELECT 语句连接起来就可以了，要注意的是所有 SELECT 语句中的字段数目要想同。下面的例子就演示了一个使用 UNION的查询。</p>
<p>　　SELECT Name, Phone FROM client UNION SELECT Name, BirthDate FROM author</p>
<p>　　UNION</p>
<p>　　SELECT Name, Supplier FROM product</p>
<p>　　4、事务</p>
<p>　　尽管我们可以使用子查询（Sub-Queries）、连接（JOIN）和联合（UNION）来创建各种各样的查询，但不是所有的数据库操作都可以只用一条或少数几条SQL语句就可以完成的。更多的时候是需要用到一系列的语句来完成某种工作。但是在这种情况下，当这个语句块中的某一条语句运行出错的时候，整个语句块的操作就会变得不确定起来。设想一下，要把某个数据同时插入两个相关联的表中，可能会出现这样的情况：第一个表中成功更新后，数据库突然出现意外状况，造成第二个表中的操作没有完成，这样，就会造成数据的不完整，甚至会破坏数据库中的数据。要避免这种情况，就应该使用事务，它的作用是：要么语句块中每条语句都操作成功，要么都失败。换句话说，就是可以保持数据库中数据的一致性和完整性。事物以BEGIN 关键字开始，COMMIT关键字结束。在这之间的一条SQL操作失败，那么，ROLLBACK命令就可以把数据库恢复到BEGIN开始之前的状态。</p>
<p>　　BEGIN; </p>
<p>　　INSERT INTO salesinfo SET CustomerID=14; </p>
<p>　　UPDATE inventory SET Quantity=11</p>
<p>　　WHERE item='book'; </p>
<p>　　COMMIT; </p>
<p>　　事务的另一个重要作用是当多个用户同时使用相同的数据源时，它可以利用锁定数据库的方法来为用户提供一种安全的访问方式，这样可以保证用户的操作不被其它的用户所干扰。</p>
<p>　　5、锁定表</p>
<p>　　尽管事务是维护数据库完整性的一个非常好的方法，但却因为它的独占性，有时会影响数据库的性能，尤其是在很大的应用系统中。由于在事务执行的过程中，数据库将会被锁定，因此其它的用户请求只能暂时等待直到该事务结束。如果一个数据库系统只有少数几个用户</p>
<p>　　来使用，事务造成的影响不会成为一个太大的问题；但假设有成千上万的用户同时访问一个数据库系统，例如访问一个电子商务网站，就会产生比较严重的响应延迟。</p>
<p>　　其实，有些情况下我们可以通过锁定表的方法来获得更好的性能。下面的例子就用锁定表的方法来完成前面一个例子中事务的功能。</p>
<p>　　LOCK TABLE inventory WRITE</p>
<p>　　SELECT Quantity FROM inventory</p>
<p>　　WHEREItem='book'; </p>
<p>　　...</p>
<p>　　UPDATE inventory SET Quantity=11</p>
<p>　　WHEREItem='book'; </p>
<p>　　UNLOCK TABLES</p>
<p>　　这里，我们用一个 SELECT 语句取出初始数据，通过一些计算，用 UPDATE 语句将新值更新到表中。包含有 WRITE 关键字的 LOCK TABLE 语句可以保证在 UNLOCK TABLES 命令被执行之前，不会有其它的访问来对 inventory 进行插入、更新或者删除的操作。</p>
<p>　　6、使用外键</p>
<p>　　锁定表的方法可以维护数据的完整性，但是它却不能保证数据的关联性。这个时候我们就可以使用外键。例如，外键可以保证每一条销售记录都指向某一个存在的客户。在这里，外键可以把customerinfo 表中的CustomerID映射到salesinfo表中CustomerID，任何一条没有合法CustomerID的记录都不会被更新或插入到salesinfo中。</p>
<p>　　CREATE TABLE customerinfo</p>
<p>　　(</p>
<p>　　CustomerID INT NOT NULL ,</p>
<p>　　PRIMARY KEY ( CustomerID )</p>
<p>　　) TYPE = INNODB; </p>
<p>　　CREATE TABLE salesinfo</p>
<p>　　(</p>
<p>　　SalesID INT NOT NULL,</p>
<p>　　CustomerID INT NOT NULL,</p>
<p>　　PRIMARY KEY(CustomerID, SalesID),</p>
<p>　　FOREIGN KEY (CustomerID) REFERENCES customerinfo</p>
<p>　　(CustomerID) ON DELETECASCADE</p>
<p>　　) TYPE = INNODB; </p>
<p>　　注意例子中的参数&#8220;ON DELETE CASCADE&#8221;。该参数保证当 customerinfo 表中的一条客户记录被删除的时候，salesinfo 表中所有与该客户相关的记录也会被自动删除。如果要在 MySQL 中使用外键，一定要记住在创建表的时候将表的类型定义为事务安全表 InnoDB类型。该类型不是 MySQL 表的默认类型。定义的方法是在 CREATE TABLE 语句中加上 TYPE=INNODB。如例中所示。</p>
<p>　　7、使用索引</p>
<p>　　索引是提高数据库性能的常用方法，它可以令数据库服务器以比没有索引快得多的速度检索特定的行，尤其是在查询语句当中包含有MAX(), MIN()和ORDERBY这些命令的时候，性能提高更为明显。那该对哪些字段建立索引呢？一般说来，索引应建立在那些将用于JOIN, WHERE判断和ORDER BY排序的字段上。尽量不要对数据库中某个含有大量重复的值的字段建立索引。对于一个ENUM类型的字段来说，出现大量重复值是很有可能的情况，例如customerinfo中的&#8220;province&#8221;.. 字段，在这样的字段上建立索引将不会有什么帮助；相反，还有可能降低数据库的性能。我们在创建表的时候可以同时创建合适的索引，也可以使用ALTER TABLE或CREATE INDEX在以后创建索引。此外，MySQL</p>
<p>　　从版本3.23.23开始支持全文索引和搜索。全文索引在MySQL 中是一个FULLTEXT类型索引，但仅能用于MyISAM 类型的表。对于一个大的数据库，将数据装载到一个没有FULLTEXT索引的表中，然后再使用ALTER TABLE或CREATE INDEX创建索引，将是非常快的。但如果将数据装载到一个已经有FULLTEXT索引的表中，执行过程将会非常慢。</p>
<p>　　8、优化的查询语句</p>
<p>　　绝大多数情况下，使用索引可以提高查询的速度，但如果SQL语句使用不恰当的话，索引将无法发挥它应有的作用。下面是应该注意的几个方面。首先，最好是在相同类型的字段间进行比较的操作。在MySQL 3.23版之前，这甚至是一个必须的条件。例如不能将一个建有索引的INT字段和BIGINT字段进行比较；但是作为特殊的情况，在CHAR类型的字段和VARCHAR类型字段的字段大小相同的时候，可以将它们进行比较。其次，在建有索引的字段上尽量不要使用函数进行操作。</p>
<p>　　例如，在一个DATE类型的字段上使用YEAE()函数时，将会使索引不能发挥应有的作用。所以，下面的两个查询虽然返回的结果一样，但后者要比前者快得多。</p>
<p>　　SELECT * FROM order WHERE YEAR(OrderDate)&lt;2001; </p>
<p>　　SELECT * FROM order WHERE OrderDate&lt;"2001-01-01"; </p>
<p>　　同样的情形也会发生在对数值型字段进行计算的时候：</p>
<p>　　SELECT * FROM inventory WHERE Amount/7&lt;24; </p>
<p>　　SELECT * FROM inventory WHERE Amount&lt;24*7; </p>
<p>　　上面的两个查询也是返回相同的结果，但后面的查询将比前面的一个快很多。第三，在搜索字符型字段时，我们有时会使用 LIKE 关键字和通配符，这种做法虽然简单，但却也是以牺牲系统性能为代价的。例如下面的查询将会比较表中的每一条记录。</p>
<p>　　SELECT * FROM books</p>
<p>　　WHERE name like "MySQL%"</p>
<p>　　但是如果换用下面的查询，返回的结果一样，但速度就要快上很多：</p>
<p>　　SELECT * FROM books</p>
<p>　　WHERE name&gt;="MySQL"and name&lt;"mysqm"</p>
<p>　　最后，应该注意避免在查询中让MySQL进行自动类型转换，因为转换过程也会使索引变得不起作用。</p>
</div>
 <img src ="http://www.blogjava.net/lcs/aggbug/180056.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcs/" target="_blank">lk</a> 2008-02-15 13:55 <a href="http://www.blogjava.net/lcs/archive/2008/02/15/180056.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MYSQL使用索引的方法 </title><link>http://www.blogjava.net/lcs/archive/2008/02/01/178852.html</link><dc:creator>lk</dc:creator><author>lk</author><pubDate>Fri, 01 Feb 2008 08:08:00 GMT</pubDate><guid>http://www.blogjava.net/lcs/archive/2008/02/01/178852.html</guid><wfw:comment>http://www.blogjava.net/lcs/comments/178852.html</wfw:comment><comments>http://www.blogjava.net/lcs/archive/2008/02/01/178852.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcs/comments/commentRss/178852.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcs/services/trackbacks/178852.html</trackback:ping><description><![CDATA[<div id="ArticleTitle">MYSQL使用索引的方法 </div>
<div id="AuthorReadMode"><span id="Author">作者：vicki</span> <span id="PublicTime">2006-12-05 16:46:51</span> </div>
<table class="reader_tag" cellspacing="0" cellpadding="0" width="480" align="center" border="0">
    <tbody>
        <tr>
            <td align="right" width="60" height="20">标签：</td>
            <td valign="top" align="center" colspan="4" rowspan="2">
            <div style="clear: both"></div>
            </td>
        </tr>
        <tr>
            <td width="60" height="20">&nbsp;</td>
        </tr>
    </tbody>
</table>
<div onselectstart="return false;" id="Content" style="overflow: hidden; word-break: break-all; word-wrap: break-word">
<div><strong>如何建立索引</strong></div>
<div>&nbsp;</div>
<div>&#183; 索引通常被用于提高WHERE条件的数据行匹配或者执行联结操作时匹配其它表的数据行的搜索速度。所以我们选择索引的列也通常选择出现在WHERE子句、join子句、ORDER BY或GROUP BY子句中的列。</div>
<div>&#183; 选择索引时，需要考虑数据列的基数。所谓基数，是指数据列所包含的不同的数据的个数。如果基数相对于数据表行数较高的话，索引的效果比较好。换句话说，就是指数据列的不同的值越多，索引效果越好。如果一个数据列只包含：0或者1两个值的话，索引的用处就不大。如果值出现的几率几乎相等，那么无论搜索哪个值都可能得到一半的数据行。在这些情况下，最好根本不要使用索引。</div>
<div>&#183; 索引值较短的值，所选择的数据类型也尽可能的要小一些。譬如：如果TEXT能满足需求的话，我们就不需要用MEDIUTEXT。</div>
<div>&#183; 如果建立联合索引的话，譬如对：t1,t2,t3建立联合索引的话，同时也是对t1和t1,t2建立了索引。但是如果单独指定t2、t3、t1t3、t2t3的值的话，都会用不到索引。<br />
</div>
<div>&nbsp;</div>
<div><strong>sql语句中如何避免没有使用索引的情况</strong></div>
<div>&nbsp;</div>
<div>首先先了解一下mysql优化器的工作原理：MySQL查询优化器最主要的目标是尽可能地使用索引，并且使用最严格的索引来消除尽可能多的数据行。所以当我们提交查询语句时，如果优化器排除不符合条件的数据的速度越快，那么查询的结果也会越快。</div>
<div>&#183;尽量比较数据类型相同的数据列。例如，INT与BIGINT是不同的。CHAR(10)被认为是CHAR(10)或VARCHAR(10)，但是与CHAR(12)或VARCHAR(12)不同。</div>
<div>&#183;尽量不要在where子句中对索引列使用表达式或者函数。如果你在索引列使用函数调用或者更复杂的算术表达式，MySQL就不会使用索引，因为它必须计算出每个数据行的表达式值。</div>
<div>&nbsp;&nbsp; WHERE mycol &lt; 4 / 2 使用索引<br />
&nbsp;&nbsp; WHERE mycol * 2 &lt; 4 没有使用索引</div>
<div>&#183; 在使用LIKE时，尽量不要在开头使用通配符。</div>
<div>&nbsp;&nbsp;&nbsp; WHERE col_name LIKE &#8217;%string%&#8217;</div>
<div>&nbsp;&nbsp;&nbsp; WHERE col_name LIKE &#8217;abc%&#8217;</div>
<div>&#183; 不要使用类型转换。如果某个索引列是int型，而在查询时，赋值为字符型，将使用不了索引。</div>
<div>&nbsp;&nbsp;&nbsp; SELECT * FROM mytbl WHERE num_col = 1;使用索引<br />
&nbsp;&nbsp;&nbsp; SELECT * FROM mytbl WHERE num_col = &#8216;1&#8217;;没有使用索引</div>
<div>&#183;在SELECT语句中可以使用STRAIGHT_JOIN关键字来重载优化器的选择。</div>
<div>&nbsp;&nbsp;&nbsp; SELECT STRAIGHT_JOIN ... FROM t1, t2, t3 ... ;<br />
&nbsp;&nbsp;&nbsp; SELECT ... FROM t1 STRAIGHT_JOIN t2 STRAIGHT_JOIN t3 ... ;</div>
</div>
<br />
<br />
http://blog.sina.com.cn/s/reader_46599af7010006rv.html
<img src ="http://www.blogjava.net/lcs/aggbug/178852.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcs/" target="_blank">lk</a> 2008-02-01 16:08 <a href="http://www.blogjava.net/lcs/archive/2008/02/01/178852.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在SQL Server中快速删除重复记录</title><link>http://www.blogjava.net/lcs/archive/2007/11/02/157755.html</link><dc:creator>lk</dc:creator><author>lk</author><pubDate>Fri, 02 Nov 2007 07:22:00 GMT</pubDate><guid>http://www.blogjava.net/lcs/archive/2007/11/02/157755.html</guid><wfw:comment>http://www.blogjava.net/lcs/comments/157755.html</wfw:comment><comments>http://www.blogjava.net/lcs/archive/2007/11/02/157755.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/lcs/comments/commentRss/157755.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcs/services/trackbacks/157755.html</trackback:ping><description><![CDATA[开发人员的噩梦——删除重复记录<br />
<br />
　　想必每一位开发人员都有过类似的经历，在对数据库进行查询或统计的时候不时地会碰到由于表中存在重复的记录而导致查询和统计结果不准确。解决该问题的办法就是将这些重复的记录删除，只保留其中的一条。<br />
<br />
　　在SQL Server中除了对拥有十几条记录的表进行人工删除外，实现删除重复记录一般都是写一段代码，用游标的方法一行一行检查，删除重复的记录。因为这种方法需要对整个表进行遍历，所以对于表中的记录数不是很大的时候还是可行的，如果一张表的数据达到上百万条，用游标的方法来删除简直是个噩梦，因为它会执行相当长的一段时间。 <br />
<br />
　　<strong>四板斧——轻松消除重复记录</strong><br />
<br />
　　殊不知在SQL Server中有一种更为简单的方法，它不需要用游标，只要写一句简单插入语句就能实现删除重复记录的功能。为了能清楚地表述，我们首先假设存在一个产品信息表Products，其表结构如下：<br />
<br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1">
    <tbody>
        <tr>
            <td>CREATE TABLE Products (<br />
            ProductID int,<br />
            ProductName nvarchar (40),<br />
            Unit char(2),<br />
            UnitPrice money<br />
            )</td>
        </tr>
    </tbody>
</table>
<p align="center"><br />
　　表中的数据如图1：<br />
<br />
<a href="http://www.qliy.com/kk/vod/reg.htm" target="_blank"></a><br />
<br />
<img height="375" alt="" src="http://www.blogjava.net/images/blogjava_net/lcs/U74DT20041022101036.jpg" width="500" border="0" /><br />
<span style="color: #333399">图1<br />
</span><br />
　　图1中可以看出，产品Chang和Tofu的记录在产品信息表中存在重复。现在要删除这些重复的记录，只保留其中的一条。步骤如下：<br />
<br />
　　第一板斧——建立一张具有相同结构的临时表<br />
<br />
</p>
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1">
    <tbody>
        <tr>
            <td>CREATE TABLE Products_temp (<br />
            ProductID int,<br />
            ProductName nvarchar (40),<br />
            Unit char(2),<br />
            UnitPrice money<br />
            )</td>
        </tr>
    </tbody>
</table>
<br />
　　第二板斧——为该表加上索引，并使其忽略重复的值<br />
<br />
　　方法是在企业管理器中找到上面建立的临时表Products _temp，单击鼠标右键，选择所有任务，选择管理索引，选择新建。如图2所示。<br />
<br />
　　按照图2中圈出来的地方设置索引选项。<br />
<br />
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><a href="http://www.qliy.com/kk/vod/reg.htm" target="_blank"><br />
            <br />
            <img height="470" alt="" src="http://www.blogjava.net/images/blogjava_net/lcs/U74DT20041022101051.jpg" width="441" border="0" /><br />
            图2</div>
            </a></td>
        </tr>
    </tbody>
</table>
<br />
　　第三板斧——拷贝产品信息到临时表<br />
<br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1">
    <tbody>
        <tr>
            <td>insert into Products_temp Select * from Products</td>
        </tr>
    </tbody>
</table>
<br />
　　此时SQL Server会返回如下提示：<br />
<br />
　　服务器: 消息 3604，级别 16，状态 1，行 1<br />
<br />
　　已忽略重复的键。<br />
<br />
　　它表明在产品信息临时表Products_temp中不会有重复的行出现。<br />
<br />
　　第四板斧——将新的数据导入原表<br />
<br />
　　将原产品信息表Products清空，并将临时表Products_temp中数据导入，最后删除临时表Products_temp。<br />
<br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1">
    <tbody>
        <tr>
            <td>delete Products<br />
            insert into Products select * from Products_temp<br />
            drop table Products_temp</td>
        </tr>
    </tbody>
</table>
<br />
　　这样就完成了对表中重复记录的删除。无论表有多大，它的执行速度都是相当快的，而且因为几乎不用写语句，所以它也是很安全的。<br />
<br />
　　小提示：上述方法中删除重复记录取决于创建唯一索引时选择的字段，在实际的操作过程中读者务必首先确认创建的唯一索引字段是否正确，以免将有用的数据删除。 
<img src ="http://www.blogjava.net/lcs/aggbug/157755.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcs/" target="_blank">lk</a> 2007-11-02 15:22 <a href="http://www.blogjava.net/lcs/archive/2007/11/02/157755.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>查询数据库中的重复记录(集合但没整理)</title><link>http://www.blogjava.net/lcs/archive/2007/11/02/157753.html</link><dc:creator>lk</dc:creator><author>lk</author><pubDate>Fri, 02 Nov 2007 07:18:00 GMT</pubDate><guid>http://www.blogjava.net/lcs/archive/2007/11/02/157753.html</guid><wfw:comment>http://www.blogjava.net/lcs/comments/157753.html</wfw:comment><comments>http://www.blogjava.net/lcs/archive/2007/11/02/157753.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcs/comments/commentRss/157753.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcs/services/trackbacks/157753.html</trackback:ping><description><![CDATA[<div class="entry-body nerr" style="display: block"><br />
&nbsp;</div>
<p class="entry-body nerr" style="display: block">========第一篇=========<br />
在一张表中某个字段下面有重复记录，有很多方法，但是有一个方法，是比较高效的，如下语句：</p>
<p class="entry-body nerr" style="display: block">select data_guid from adam_entity_datas a where a.rowid &gt; (select min(b.rowid) from adam_entity_datas b where b.data_guid = a.data_guid)</p>
<p class="entry-body nerr" style="display: block">如果表中有大量数据，但是重复数据比较少，那么可以用下面的语句提高效率</p>
<p class="entry-body nerr" style="display: block">select data_guid from adam_entity_datas where data_guid in (select data_guid from adam_entity_datas group by data_guid having count(*) &gt; 1)</p>
<p class="entry-body nerr" style="display: block">此方法查询出所有重复记录了，也就是说，只要是重复的就选出来，下面的语句也许更高效</p>
<p class="entry-body nerr" style="display: block">select data_guid from adam_entity_datas where rowid in (select rid from (select rowid rid,row_number()over(partition by data_guid order by rowid) m&nbsp;from adam_entity_datas) where m &lt;&gt; 1)</p>
<p class="entry-body nerr" style="display: block">目前只知道这三种比较有效的方法。</p>
<p class="entry-body nerr" style="display: block" align="left">第一种方法比较好理解，但是最慢，第二种方法最快，但是选出来的记录是所有重复的记录，而不是一个重复记录的列表，第三种方法，我认为最好。<br />
<br />
========第二篇=========<br />
select &nbsp; usercode,count(*)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; from &nbsp; ptype&nbsp;&nbsp;&nbsp;&nbsp; group &nbsp; by &nbsp; usercode&nbsp;&nbsp;&nbsp;&nbsp; having &nbsp; count(*) &nbsp; &gt;1&nbsp;&nbsp; <br />
========第三篇=========<br />
找出重复记录的ID: &nbsp; <br />
&nbsp; select &nbsp; ID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; from&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
(&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; select &nbsp; ID &nbsp; ,count(*) &nbsp; as &nbsp; Cnt &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; from &nbsp; 要消除重复的表 &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; group &nbsp; by &nbsp; ID &nbsp; <br />
&nbsp; ) &nbsp; T1 &nbsp; <br />
&nbsp; where &nbsp; T1.cnt&gt;1&nbsp;&nbsp; <br />
<br />
删除数据库中重复数据的几个方法&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;数据库的使用过程中由于程序方面的问题有时候会碰到重复数据，重复数据导致了数据库部分设置不能正确设置&#8230;&#8230;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
方法一&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;declare &nbsp; @max &nbsp; integer,@id &nbsp; integer&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;declare &nbsp; cur_rows &nbsp; cursor &nbsp; local &nbsp; for &nbsp; select &nbsp; 主字段,count(*) &nbsp; from&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 表名 &nbsp; group &nbsp; by &nbsp; 主字段 &nbsp; having &nbsp; count(*) &nbsp; &gt; &nbsp; 1 &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 　　open &nbsp; cur_rows &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 　　fetch &nbsp; cur_rows &nbsp; into &nbsp; @id,@max &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 　　while &nbsp; @@fetch_status=0 &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 　　begin &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 　　select &nbsp; @max &nbsp; = &nbsp; @max &nbsp; -1 &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 　　set &nbsp; rowcount &nbsp; @max &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 　　delete &nbsp; from &nbsp; 表名 &nbsp; where &nbsp; 主字段 &nbsp; = &nbsp; @id &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 　　fetch &nbsp; cur_rows &nbsp; into &nbsp; @id,@max &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 　　end &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 　　close &nbsp; cur_rows &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 　　set &nbsp; rowcount &nbsp; 0&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp; <br />
方法二&nbsp;&nbsp; <br />
有两个意义上的重复记录，一是完全重复的记录，也即所有字段均重复的记录，二是部分关键字段重复的记录，比如Name字段重复，而其他字段不一定重复或都重复可以忽略。&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp; 1、对于第一种重复，比较容易解决，使用&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;select &nbsp; distinct &nbsp; * &nbsp; from &nbsp; tableName&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp; 就可以得到无重复记录的结果集。&nbsp;&nbsp; <br />
如果该表需要删除重复的记录，可以按以下方法删除&nbsp;&nbsp; <br />
select &nbsp; distinct &nbsp; * &nbsp; into &nbsp; #Tmp &nbsp; from &nbsp; tableName&nbsp;&nbsp; <br />
drop &nbsp; table &nbsp; tableName&nbsp;&nbsp; <br />
select &nbsp; * &nbsp; into &nbsp; tableName &nbsp; from &nbsp; #Tmp&nbsp;&nbsp; <br />
drop &nbsp; table &nbsp; #Tmp&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;2、这类重复问题通常要求保留重复记录中的第一条记录，*作方法如下&nbsp;&nbsp; <br />
假设有重复的字段为Name,Address，要求得到这两个字段唯一的结果集&nbsp;&nbsp; <br />
　select &nbsp; identity(int,1,1) &nbsp; as &nbsp; autoID, &nbsp; * &nbsp; into &nbsp; #Tmp &nbsp; from&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp; tableName&nbsp;&nbsp; <br />
　select &nbsp; min(autoID) &nbsp; as &nbsp; autoID &nbsp; into &nbsp; #Tmp2 &nbsp; from &nbsp; #Tmp &nbsp; group &nbsp; by&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp; Name,autoID&nbsp;&nbsp; <br />
select &nbsp; * &nbsp; from &nbsp; #Tmp &nbsp; where &nbsp; autoID &nbsp; in(select &nbsp; autoID &nbsp; from&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp; #tmp2)&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;最后一个select即得到了Name，Address不重复的结果集&nbsp;&nbsp; <br />
更改数据库中表的所属用户的两个方法&nbsp;&nbsp; <br />
大家可能会经常碰到一个数据库备份还原到另外一台机器结果导致所有的表都不能打开了，原因是建表的时候采用了当时的数据库用户&#8230;&#8230;&nbsp;&nbsp;&nbsp;&nbsp; <br />
========第四篇=========<br />
<strong>如何查询数据库中的重复记录？</strong><br />
<br />
比如说有个表中的数据是这样：<br />
---------<br />
a<br />
a<br />
a<br />
b<br />
b<br />
c<br />
---------<br />
<br />
查询出的结果是：<br />
记录&nbsp;&nbsp;数量<br />
a&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;3<br />
b&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;2<br />
c&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;1<br />
<br />
怎样写这个SQL语句？<br />
-----------------------<br />
select distinct(name),count(*) from tabname group by name;<br />
-------------------------------------<br />
想出来了，这样就可以排序了。<br />
select a1,count(a1)&nbsp;&nbsp;as total from tablename group by a1 order by total desc<br />
--------------------------------------<br />
select distinct(a1),count(a1) as total from tablename group by a1 order by total desc<br />
加个distinct更有效率<br />
--------------------------------------------------------------<br />
select p.*, m.* from table1 p left join table2 m on p.item1=m.item2 where p.item3='#$#@%$@' order by p.item3 asc limit 10<br />
就类似这么写<br />
========第五篇=========<br />
如何查找数据库中的重复记录?&nbsp;能在Access中用的方法 <br />
----------------------------------------------------------------------<br />
select&nbsp;* <br />
from&nbsp;表&nbsp;A&nbsp;inner&nbsp;join&nbsp;(select&nbsp;字段1,字段2&nbsp;from&nbsp;表&nbsp;group&nbsp;by&nbsp;字段1,字段2&nbsp;having&nbsp;Count(*)&gt;1)&nbsp;B&nbsp;on&nbsp;A.字段1=B.字段1&nbsp;and&nbsp;A.字段2=B.字段2 <br />
--------------------------------------------------------<br />
问题：<br />
&nbsp;根据其中几个字段判断重复，只保留一条记录，但是要显示全部字段，怎么查询，谢谢！！ <br />
比如 <br />
字段1&nbsp;字段2&nbsp;字段3&nbsp;字段4 <br />
a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1 <br />
a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1 <br />
<br />
a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2 <br />
a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3 <br />
<br />
b&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2 <br />
<br />
想得到的结果为 <br />
a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1 <br />
a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2（或者3） <br />
b&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;d&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2 <br />
说明，根据字段1，2,3组合不重复，字段4&nbsp;不考虑，得到了3个记录 <br />
但是也要显示字段4。&nbsp;<br />
&nbsp; 方法一：&nbsp;&nbsp; <br />
可以用临时表的方法来解决： <br />
CurrentProject.Connection.Execute&nbsp;"drop&nbsp;table&nbsp;temptable" <br />
CurrentProject.Connection.Execute&nbsp;"select&nbsp;*&nbsp;into&nbsp;temptable&nbsp;from&nbsp;表2&nbsp;where&nbsp;1=2" <br />
CurrentProject.Connection.Execute&nbsp;"insert&nbsp;into&nbsp;temptable(字段1,字段2,字段3)&nbsp;SELECT&nbsp;DISTINCT&nbsp;表2.字段1,&nbsp;表2.字段2,&nbsp;表2.字段3&nbsp;FROM&nbsp;表2;" <br />
CurrentProject.Connection.Execute&nbsp;"UPDATE&nbsp;temptable&nbsp;INNER&nbsp;JOIN&nbsp;表2&nbsp;ON&nbsp;(表2.字段1&nbsp;=&nbsp;temptable.字段1)&nbsp;AND&nbsp;(表2.字段2&nbsp;=&nbsp;temptable.字段2)&nbsp;AND&nbsp;(表2.字段3&nbsp;=&nbsp;temptable.字段3)&nbsp;SET&nbsp;temptable.字段4&nbsp;=&nbsp;[表2].[字段4];"&nbsp; <br />
方法二： <br />
可以直接使用一个SELECT查询筛选出需要的数据： <br />
可以假定第四字段都选值最小的 <br />
SELECT&nbsp;[1],[2],&nbsp;[3],&nbsp;Min([4])&nbsp;AS&nbsp;Min4 <br />
FROM&nbsp;表1 <br />
GROUP&nbsp;BY&nbsp;表1.[1],&nbsp;表1.[2],&nbsp;表1.[3];&nbsp; <br />
<br />
问题：<br />
&nbsp;表2 <br />
<br />
id&nbsp;&nbsp;NAME&nbsp;&nbsp;r1&nbsp;&nbsp;&nbsp;r2 <br />
1&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;w&nbsp;&nbsp;&nbsp;&nbsp;ee <br />
1&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;1232 <br />
1&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;123&nbsp;&nbsp;123 <br />
1&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;12&nbsp;&nbsp;&nbsp;434 <br />
1&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;123&nbsp;&nbsp;123 <br />
2&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;123&nbsp;&nbsp;123 <br />
<br />
ID&nbsp;为数值，NAME&nbsp;为字符。每条记录没有唯一标识。 <br />
要求取得&nbsp;ID&nbsp;和&nbsp;NAME&nbsp;合并后不重复的记录，如有重复保留其中一条即可，但要显示所有记录。&nbsp;<br />
&nbsp; 回答：&nbsp;<br />
&nbsp;SELECT&nbsp;a.*,&nbsp;(select&nbsp;top&nbsp;1&nbsp;r1&nbsp;from&nbsp;表2&nbsp;as&nbsp;a1&nbsp;where&nbsp;a1.id=a.id&nbsp;and&nbsp;a1.name=a.name)&nbsp;AS&nbsp;r1,&nbsp;(select&nbsp;top&nbsp;1&nbsp;r2&nbsp;from&nbsp;表2&nbsp;as&nbsp;a2&nbsp;where&nbsp;a2.id=a.id&nbsp;and&nbsp;a2.name=a.name)&nbsp;AS&nbsp;r2 <br />
FROM&nbsp;[SELECT&nbsp;DISTINCT&nbsp;表2.id,&nbsp;表2.NAME <br />
FROM&nbsp;表2].&nbsp;AS&nbsp;a;&nbsp; <br />
<br />
SELECT&nbsp;a.*,&nbsp;dlookup("r1","表2","id="&nbsp;&amp;&nbsp;a.id&nbsp;&nbsp;&amp;&nbsp;"&nbsp;and&nbsp;name='"&amp;&nbsp;a.name&nbsp;&amp;&nbsp;"'")&nbsp;AS&nbsp;r1,&nbsp;dlookup("r2","表2","id="&nbsp;&amp;&nbsp;a.id&nbsp;&nbsp;&amp;&nbsp;"&nbsp;and&nbsp;name='"&amp;&nbsp;a.name&nbsp;&amp;&nbsp;"'")&nbsp;AS&nbsp;r2 <br />
FROM&nbsp;[SELECT&nbsp;DISTINCT&nbsp;表2.id,&nbsp;表2.NAME <br />
FROM&nbsp;表2].&nbsp;AS&nbsp;a;&nbsp; <br />
<br />
注意，上述代码中由于没有唯一标识列，因此显示的&nbsp;R1&nbsp;R2&nbsp;的先后次序无从确定，一般是按输入的先后顺序，但是微软没有官方资料说明到底按哪个顺序，请网友注意。 <br />
<br />
请注意，上述表2为没有唯一标识字段，如果现在再建立一个自动编号字段&#8220;主键&#8221;则可以用以下代码 <br />
<br />
SELECT&nbsp;a.ID,&nbsp;a.name,&nbsp;b.r1,&nbsp;b.r2,&nbsp;b.主键 <br />
FROM&nbsp;(SELECT&nbsp;表2.id,&nbsp;表2.NAME,&nbsp;Min(表2.主键)&nbsp;AS&nbsp;主键 <br />
FROM&nbsp;表2 <br />
GROUP&nbsp;BY&nbsp;表2.id,&nbsp;表2.NAME)&nbsp;AS&nbsp;a&nbsp;inner&nbsp;JOIN&nbsp;表2&nbsp;AS&nbsp;b&nbsp;ON&nbsp;a.主键=b.主键;&nbsp; <br />
<br />
========第六篇=========<br />
1.查询数据库中重复的记录:<br />
select realname,count(*) from users group by realname having count(*)&gt;1 <br />
========第七篇=========<br />
SELECT &nbsp; T0.ItemCode, &nbsp; T0.ItemName &nbsp; FROM &nbsp; OITM &nbsp; T0 &nbsp; WHERE &nbsp; exists &nbsp; (select &nbsp; 1 &nbsp; from &nbsp; OITM &nbsp; A &nbsp; where &nbsp; A.CODEBARS &nbsp; = &nbsp; TO.CODEBARS &nbsp; And &nbsp; A.ItemCode &nbsp; &lt; &gt; &nbsp; TO.ItemCode)<br />
========第八篇=========<br />
&nbsp;相信很多人在查询数据库时都会碰到检索某表中不重复记录的时候,提到检索不重复记录,马上想到的肯定是Distinct或者Group By分组,<br />
小弟在初次使用的时候碰到了一些麻烦,这里拿出来与大家分享,希望对更多的朋友有所帮助!<br />
<br />
&nbsp;&nbsp;&nbsp; 先看看数据库表结构：<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 表名: TEST&nbsp; 字段: Id,A,B,C,D<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 其中B字段包含重复值;<br />
<br />
<table class="MsoTableGrid" style="border-right: medium none; border-top: medium none; background: rgb(204,255,204) 0% 50%; margin-left: 6.75pt; border-left: medium none; margin-right: 6.75pt; border-bottom: medium none; border-collapse: collapse; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial" height="141" cellspacing="0" cellpadding="0" width="664" align="left" border="1">
    <tbody>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 85.2pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: red">Id<O:P></O:P></span></p>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">A<O:P></O:P></span></p>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: rgb(153,51,0)">B<O:P></O:P></span></p>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">C<O:P></O:P></span></p>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">D<O:P></O:P></span></p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: 1pt solid; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: red">1<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">11<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: rgb(153,51,0)">a<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">34<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">bvb<O:P></O:P></span></p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: 1pt solid; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: red">2<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">22<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: rgb(153,51,0)">a<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">35<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">fgfg<O:P></O:P></span></p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: 1pt solid; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: red">3<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">33<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: rgb(153,51,0)">d<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">ht<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">sdf<O:P></O:P></span></p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: 1pt solid; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: red">4<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">44<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: rgb(153,51,0)">a<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">345<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">de<O:P></O:P></span></p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: 1pt solid; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: red">5<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">55<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: rgb(153,51,0)">c<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">sfsf<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">sscv<O:P></O:P></span></p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: 1pt solid; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: red">6<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">66<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: rgb(153,51,0)">b<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">rt<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">fg<O:P></O:P></span></p>
            </td>
        </tr>
    </tbody>
</table>
<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; <br />
<br />
<br />
<br />
<br />
<br />
&nbsp;<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp; <br />
<br />
<font color="#ff0000">下面我们来看看用什么样的SQL语句检索出不含重复记录的数据:</font><br />
&nbsp;使用Distinct关键字<br />
&nbsp;&nbsp;&nbsp; &nbsp; Distinct关键字主要用来在SELECT查询记录中根据某指定字段的值去除重复记录<br />
&nbsp;&nbsp;&nbsp; &nbsp;<font color="#ff0000"><font color="#0000ff">SELECT DISTINCT [字段名] FROM [表名] WHERE [检索条件字句]</font></font><br />
<br />
&nbsp;&nbsp;&nbsp; 所以用这样一句SQL就可以去掉重复项了:<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp; </p>
<div style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: rgb(204,204,204) 1px solid; width: 98%; padding-top: 4px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: rgb(0,0,255)">SELECT</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">DISTINCT</span><span style="color: rgb(0,0,0)">&nbsp;(B)&nbsp;</span><span style="color: rgb(0,0,255)">FROM</span><span style="color: rgb(0,0,0)">&nbsp;TEST</span></div>
<p class="entry-body nerr" style="display: block" align="left"><br />
&nbsp;&nbsp;&nbsp; <font color="#ff0000">但是:<br />
<br />
</font>&nbsp;&nbsp;&nbsp; &nbsp; 这里有一个非常非常需要注意的地方：<br />
&nbsp;&nbsp;&nbsp; &nbsp; SELECT DISTINCT [字段名]后面不能再跟其他的字段，否则检索出来的记录仍然会含有重复项；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 错误写法：<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <font color="#0000ff">SELECT DISTINCT [字段名] ，[其他字段名] FROM [表名] WHERE [检索条件字句]</font><br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 实际上,我们上面SQL语句结果集里就只有B字段;(一般情况下,这种结果应该是很难满足需求的)<br />
<br />
<br />
&nbsp;&nbsp;&nbsp; <font color="#ff0000">如果我们的记录集里还需要有其他字段值,那怎么办呢?<br />
<br />
</font>实际上,我们完全可以用另一种办法来解决问题;只是需要用到子查询而已!<br />
<br />
使用GROUP BY 分组<br />
&nbsp;&nbsp;&nbsp; 有一点需要注意:<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; <font color="#0000ff">使用带有GROUP BY字句的查询语句时,在SELECT列表指定的列要么是GROUP BY 指定的列,要么包含聚合组函数</font><br />
<br />
&nbsp;&nbsp;&nbsp; 所以用这样一句SQL就可以去掉重复项了:<br />
<br />
</p>
<div style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: rgb(204,204,204) 1px solid; width: 98%; padding-top: 4px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: rgb(0,0,255)">SELECT</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(128,128,128)">*</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">FROM</span><span style="color: rgb(0,0,0)">&nbsp;TEST&nbsp;</span><span style="color: rgb(0,0,255)">WHERE</span><span style="color: rgb(0,0,0)">&nbsp;id&nbsp;</span><span style="color: rgb(128,128,128)">in</span><span style="color: rgb(0,0,0)">&nbsp;(</span><span style="color: rgb(0,0,255)">SELECT</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(255,0,255)">MIN</span><span style="color: rgb(0,0,0)">(id)&nbsp;</span><span style="color: rgb(0,0,255)">FROM</span><span style="color: rgb(0,0,0)">&nbsp;TEST&nbsp;</span><span style="color: rgb(0,0,255)">GROUP</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">BY</span><span style="color: rgb(0,0,0)">&nbsp;B)</span></div>
<p class="entry-body nerr" style="display: block" align="left"><br />
&nbsp;&nbsp;&nbsp; 这样就得到我们想要的结果集了:<br />
&nbsp;&nbsp;&nbsp;
<table class="MsoTableGrid" style="border-right: medium none; border-top: medium none; background: rgb(204,255,204) 0% 50%; margin-left: 6.75pt; border-left: medium none; margin-right: 6.75pt; border-bottom: medium none; border-collapse: collapse; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial" cellspacing="0" cellpadding="0" align="left" border="1">
    <tbody>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 85.2pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: red">Id<O:P></O:P></span></p>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">A<O:P></O:P></span></p>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: rgb(153,51,0)">B<O:P></O:P></span></p>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">C<O:P></O:P></span></p>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">D<O:P></O:P></span></p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: 1pt solid; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: red">1<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">11<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: rgb(153,51,0)">a<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">34<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">bvb<O:P></O:P></span></p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: 1pt solid; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: red">3<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">33<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: rgb(153,51,0)">d<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">ht<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">sdf<O:P></O:P></span></p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: 1pt solid; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: red">5<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">55<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: rgb(153,51,0)">c<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">sfsf<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">sscv<O:P></O:P></span></p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: 1pt solid; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: red">6<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">66<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.2pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US" style="color: rgb(153,51,0)">b<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">rt<O:P></O:P></span></p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 85.25pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="114">
            <p class="MsoNormal"><span lang="EN-US">fg<O:P></O:P></span></p>
            </td>
        </tr>
    </tbody>
</table>
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
<br />
<br />
<br />
<br />
<br />
<br />
========第九篇======mysql===<br />
----------------------------------------------------------------------<br />
<br />
我的mysql表中的帐号是8位的随机数,我现在想查帐号有没有重复的,应该怎样操作, <br />
<br />
<br />
----------------------------------------------------------------------<br />
<br />
select&nbsp;count(*)&nbsp;as&nbsp;num,帐号&nbsp;from&nbsp;TABLE&nbsp;GROUP&nbsp;BY&nbsp;帐号 <br />
num&nbsp;&gt;&nbsp;1&nbsp;就有重复! <br />
<br />
========第十篇====（着急的人直接看红字）=====<br />
在使用mysql时，有时需要查询出某个字段不重复的记录，虽然mysql提供有distinct这个关键字来过滤掉多余的重复记录只保留一条，但往往只用它来返回不重复记录的条数，而不是用它来返回不重记录的所有值。其原因是distinct只能返回它的目标字段，而无法返回其它字段，这个问题让我困扰了很久，用distinct不能解决的话，我只有用二重循环查询来解决，而这样对于一个数据量非常大的站来说，无疑是会直接影响到效率的。所以我花了很多时间来研究这个问题，网上也查不到解决方案，期间把容容拉来帮忙，结果是我们两人都郁闷了。。。。。。。。。<br />
<br />
下面先来看看例子：<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;table<br />
&nbsp;&nbsp;id name<br />
&nbsp;&nbsp;1 a<br />
&nbsp;&nbsp;2 b<br />
&nbsp;&nbsp;3 c<br />
&nbsp;&nbsp;4 c<br />
&nbsp;&nbsp;5 b<br />
<br />
库结构大概这样，这只是一个简单的例子，实际情况会复杂得多。<br />
<br />
比如我想用一条语句查询得到name不重复的所有数据，那就必须使用distinct去掉多余的重复记录。<br />
<br />
select distinct name from table<br />
得到的结果是:<br />
<br />
&nbsp;&nbsp;name<br />
&nbsp;&nbsp;a<br />
&nbsp;&nbsp;b<br />
&nbsp;&nbsp;c<br />
<br />
好像达到效果了，可是，我想要得到的是id值呢？改一下查询语句吧:<br />
<br />
select distinct name, id from table<br />
<br />
结果会是:<br />
<br />
&nbsp;&nbsp;id name<br />
&nbsp;&nbsp;1 a<br />
&nbsp;&nbsp;2 b<br />
&nbsp;&nbsp;3 c<br />
&nbsp;&nbsp;4 c<br />
&nbsp;&nbsp;5 b<br />
<br />
distinct怎么没起作用？作用是起了的，不过他同时作用了两个字段，也就是必须得id与name都相同的才会被排除。。。。。。。<br />
<br />
我们再改改查询语句:<br />
<br />
select id, distinct name from table<br />
<br />
很遗憾，除了错误信息你什么也得不到，distinct必须放在开头。难到不能把distinct放到where条件里？能，照样报错。。。。。。。<br />
<br />
很麻烦吧？确实，费尽心思都没能解决这个问题。没办法，继续找人问。<br />
<br />
拉住公司里一JAVA程序员，他给我演示了oracle里使用distinct之后，也没找到mysql里的解决方案，最后下班之前他建议我试试group by。<br />
<br />
试了半天，也不行，最后在mysql手册里找到一个用法，用group_concat(distinct name)配合group by name实现了我所需要的功能，兴奋，天佑我也，赶快试试。<br />
<br />
报错。。。。。。。。。。。。郁闷。。。。。。。连mysql手册也跟我过不去，先给了我希望，然后又把我推向失望，好狠哪。。。。<br />
<br />
再仔细一查，group_concat函数是4.1支持，晕，我4.0的。没办法，升级，升完级一试，成功。。。。。。<br />
<br />
终于搞定了，不过这样一来，又必须要求客户也升级了。<br />
<br />
突然灵机一闪，既然可以使用group_concat函数，那其它函数能行吗？<br />
<br />
赶紧用count函数一试，成功，我。。。。。。。想哭啊，费了这么多工夫。。。。。。。。原来就这么简单。。。。。。<br />
<br />
现在将完整语句放出:<br />
<br />
select *, count(distinct name) from table group by name<br />
<br />
结果:<br />
<br />
&nbsp;&nbsp;id name count(distinct name)<br />
&nbsp;&nbsp;1 a 1<br />
&nbsp;&nbsp;2 b 1<br />
&nbsp;&nbsp;3 c 1<br />
<br />
最后一项是多余的，不用管就行了，目的达到。。。。。<br />
<br />
唉，原来mysql这么笨，轻轻一下就把他骗过去了，郁闷也就我吧（对了，还有容容那家伙），现在拿出来希望大家不要被这问题折腾。<br />
<br />
哦，对，再顺便说一句，group by 必须放在 order by 和 limit之前，不然会报错，差不多了，发给容容放网站上去，我继续忙碌。。。。。。<br />
<br />
-----------------------------------------------------------------------------------------<br />
<br />
<br />
<span style="color: red">更郁闷的事情发生了，在准备提交时容容发现，有更简单的解决方法。。。。。。<br />
<br />
select id, name from table group by name<br />
select * from table group by name<br />
<br />
</span><br />
========第十一篇=========<br />
</p>
<div class="tpc_content">查询及删除重复记录的方法<br />
(一)<br />
1、查找表中多余的重复记录，重复记录是根据单个字段（peopleId）来判断<br />
select * from people<br />
where peopleId in (select&nbsp; peopleId&nbsp; from&nbsp; people&nbsp; group&nbsp; by&nbsp; peopleId&nbsp; having&nbsp; count(peopleId) &gt; 1)<br />
<br />
2、删除表中多余的重复记录，重复记录是根据单个字段（peopleId）来判断，只留有rowid最小的记录<br />
delete from people <br />
where peopleId&nbsp; in (select&nbsp; peopleId&nbsp; from people&nbsp; group&nbsp; by&nbsp; peopleId&nbsp; having&nbsp; count(peopleId) &gt; 1)<br />
and rowid not in (select min(rowid) from&nbsp; people&nbsp; group by peopleId&nbsp; having count(peopleId )&gt;1)<br />
<br />
3、查找表中多余的重复记录（多个字段） <br />
select * from vitae a<br />
where (a.peopleId,a.seq) in&nbsp; (select peopleId,seq from vitae group by peopleId,seq&nbsp; having count(*) &gt; 1)<br />
<br />
4、删除表中多余的重复记录（多个字段），只留有rowid最小的记录<br />
delete from vitae a<br />
where (a.peopleId,a.seq) in&nbsp; (select peopleId,seq from vitae group by peopleId,seq having count(*) &gt; 1)<br />
and rowid not in (select min(rowid) from vitae group by peopleId,seq having count(*)&gt;1)<br />
<br />
<br />
5、查找表中多余的重复记录（多个字段），不包含rowid最小的记录<br />
select * from vitae a<br />
where (a.peopleId,a.seq) in&nbsp; (select peopleId,seq from vitae group by peopleId,seq having count(*) &gt; 1)<br />
and rowid not in (select min(rowid) from vitae group by peopleId,seq having count(*)&gt;1)<br />
<br />
(二)<br />
比方说<br />
在A表中存在一个字段&#8220;name&#8221;，<br />
而且不同记录之间的&#8220;name&#8221;值有可能会相同，<br />
现在就是需要查询出在该表中的各记录之间，&#8220;name&#8221;值存在重复的项；<br />
Select Name,Count(*) From A Group By Name Having Count(*) &gt; 1<br />
<br />
如果还查性别也相同大则如下:<br />
Select Name,sex,Count(*) From A Group By Name,sex Having Count(*) &gt; 1<br />
<br />
<br />
(三)<br />
方法一<br />
<br />
declare @max integer,@id integer<br />
<br />
declare cur_rows cursor local for select 主字段,count(*) from 表名 group by 主字段 having count(*) &gt;； 1<br />
<br />
open cur_rows<br />
<br />
fetch cur_rows into @id,@max<br />
<br />
while @@fetch_status=0<br />
<br />
begin<br />
<br />
select @max = @max -1<br />
<br />
set rowcount @max<br />
<br />
delete from 表名 where 主字段 = @id<br />
<br />
fetch cur_rows into @id,@max<br />
<br />
end<br />
<br />
close cur_rows<br />
<br />
set rowcount 0<br />
<br />
　　方法二<br />
<br />
　　有两个意义上的重复记录，一是完全重复的记录，也即所有字段均重复的记录，二是部分关键字段重复的记录，比如Name字段重复，而其他字段不一定重复或都重复可以忽略。<br />
<br />
　　1、对于第一种重复，比较容易解决，使用<br />
<br />
select distinct * from tableName<br />
<br />
　　就可以得到无重复记录的结果集。<br />
<br />
　　如果该表需要删除重复的记录（重复记录保留1条），可以按以下方法删除<br />
<br />
select distinct * into #Tmp from tableName<br />
<br />
drop table tableName<br />
<br />
select * into tableName from #Tmp<br />
<br />
drop table #Tmp<br />
<br />
　　发生这种重复的原因是表设计不周产生的，增加唯一索引列即可解决。<br />
<br />
　　2、这类重复问题通常要求保留重复记录中的第一条记录，操作方法如下<br />
<br />
　　假设有重复的字段为Name,Address，要求得到这两个字段唯一的结果集<br />
<br />
select identity(int,1,1) as autoID, * into #Tmp from tableName<br />
<br />
select min(autoID) as autoID into #Tmp2 from #Tmp group by Name,autoID<br />
<br />
select * from #Tmp where autoID in(select autoID from #tmp2)<br />
<br />
　　最后一个select即得到了Name，Address不重复的结果集（但多了一个autoID字段，实际写时可以写在select子句中省去此列）<br />
<br />
(四)<br />
查询重复<br />
<br />
select * from tablename where id in (<br />
<br />
select id from tablename <br />
<br />
group by id <br />
<br />
having count(id) &gt; 1<br />
<br />
)</div>
<p class="entry-body nerr" style="display: block" align="left"><br />
========第二篇=========<br />
<br />
========第二篇=========<br />
========第二篇=========</p>
<img src ="http://www.blogjava.net/lcs/aggbug/157753.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcs/" target="_blank">lk</a> 2007-11-02 15:18 <a href="http://www.blogjava.net/lcs/archive/2007/11/02/157753.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ODBC方式动态连接数据库</title><link>http://www.blogjava.net/lcs/archive/2007/09/29/149419.html</link><dc:creator>lk</dc:creator><author>lk</author><pubDate>Sat, 29 Sep 2007 01:03:00 GMT</pubDate><guid>http://www.blogjava.net/lcs/archive/2007/09/29/149419.html</guid><wfw:comment>http://www.blogjava.net/lcs/comments/149419.html</wfw:comment><comments>http://www.blogjava.net/lcs/archive/2007/09/29/149419.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcs/comments/commentRss/149419.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcs/services/trackbacks/149419.html</trackback:ping><description><![CDATA[嘿嘿嘿！！现眼了！！！<br />
<br />
这可能是到今天（2007-9-29）为止我唯一原创的东西，自己写的ODBC动态连接数据库的方法！<br />
<br />
这样就可以不用建立数据源了。<br />
<br />
public void set_ConnectDB() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; con = DriverManager.getConnection("jdbc:odbc:driver={Microsoft Access Driver (*.mdb)};DBQ=F://database/user.mdb");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; con.setAutoCommit(false);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stm = con.createStatement();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (Exception ex) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ex.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
这是我从连接类里截取的，大家都是高手，我就不用写con和stm都是什么意思了就java人都知道！！<br />
<img src ="http://www.blogjava.net/lcs/aggbug/149419.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcs/" target="_blank">lk</a> 2007-09-29 09:03 <a href="http://www.blogjava.net/lcs/archive/2007/09/29/149419.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>mysql 5.0存储过程学习总结（转）</title><link>http://www.blogjava.net/lcs/archive/2007/09/25/148019.html</link><dc:creator>lk</dc:creator><author>lk</author><pubDate>Tue, 25 Sep 2007 04:02:00 GMT</pubDate><guid>http://www.blogjava.net/lcs/archive/2007/09/25/148019.html</guid><wfw:comment>http://www.blogjava.net/lcs/comments/148019.html</wfw:comment><comments>http://www.blogjava.net/lcs/archive/2007/09/25/148019.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcs/comments/commentRss/148019.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcs/services/trackbacks/148019.html</trackback:ping><description><![CDATA[<div class="con_sample">
<p>mysql存储过程的创建，删除，调用及其他常用命令</p>
</div>
<div class="con_all">
<div style="text-align: center">
<h1>mysql 5.0存储过程学习总结</h1>
</div>
<p><span style="font-weight: bold">一.创建存储过程</span></p>
<div style="margin-left: 40px">1.基本语法：
<p>&nbsp;</p>
<div style="margin-left: 40px">create procedure sp_name()<br />
begin<br />
&#8230;&#8230;&#8230;<br />
end</div>
<p>2.参数传递</p>
</div>
<p><span style="font-weight: bold">二.调用存储过程</span></p>
<div style="margin-left: 40px">1.基本语法：call sp_name()<br />
注意：存储过程名称后面必须加括号，哪怕该存储过程没有参数传递</div>
<p><span style="font-weight: bold">三.删除存储过程</span></p>
<div style="margin-left: 40px">1.基本语法：<br />
drop procedure sp_name//<br />
2.注意事项<br />
(1)不能在一个存储过程中删除另一个存储过程，只能调用另一个存储过程</div>
<p><span style="font-weight: bold">四.区块，条件，循环<br />
</span></p>
<div style="margin-left: 40px">1.区块定义，常用<br />
begin<br />
&#8230;&#8230;<br />
end;<br />
也可以给区块起别名，如：<br />
lable:begin<br />
&#8230;&#8230;&#8230;..<br />
end lable;<br />
可以用leave lable;跳出区块，执行区块以后的代码<br />
2.条件语句
<p>&nbsp;</p>
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: rgb(230,230,230) 0% 50%; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; padding-top: 4px; border-bottom: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">&nbsp;条件&nbsp;</span><span style="color: rgb(0,0,255)">then</span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />statement<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,0,255)">else</span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />statement<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,0,255)">end</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">;</span></div>
</div>
<p>3.循环语句<br />
(1).while循环</p>
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: rgb(230,230,230) 0% 50%; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; padding-top: 4px; border-bottom: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: rgb(255,0,0)">[</span><span style="color: rgb(255,0,0)">label:</span><span style="color: rgb(255,0,0)">]</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">WHILE</span><span style="color: rgb(0,0,0)">&nbsp;expression&nbsp;DO<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />statements<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,0,255)">END</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">WHILE</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(255,0,0)">[</span><span style="color: rgb(255,0,0)">label</span><span style="color: rgb(255,0,0)">]</span><span style="color: rgb(0,0,0)">&nbsp;;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span></div>
</div>
<p>&nbsp;</p>
</div>
<div style="margin-left: 40px">(2).loop循环
<p>&nbsp;</p>
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: rgb(230,230,230) 0% 50%; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; padding-top: 4px; border-bottom: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: rgb(255,0,0)">[</span><span style="color: rgb(255,0,0)">label:</span><span style="color: rgb(255,0,0)">]</span><span style="color: rgb(0,0,0)">&nbsp;LOOP<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />statements<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,0,255)">END</span><span style="color: rgb(0,0,0)">&nbsp;LOOP&nbsp;</span><span style="color: rgb(255,0,0)">[</span><span style="color: rgb(255,0,0)">label</span><span style="color: rgb(255,0,0)">]</span><span style="color: rgb(0,0,0)">;</span></div>
</div>
<p>&nbsp;</p>
</div>
<div style="margin-left: 40px">(3).repeat until循环
<p>&nbsp;</p>
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: rgb(230,230,230) 0% 50%; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; padding-top: 4px; border-bottom: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: rgb(255,0,0)">[</span><span style="color: rgb(255,0,0)">label:</span><span style="color: rgb(255,0,0)">]</span><span style="color: rgb(0,0,0)">&nbsp;REPEAT<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />statements<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />UNTIL&nbsp;expression<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,0,255)">END</span><span style="color: rgb(0,0,0)">&nbsp;REPEAT&nbsp;</span><span style="color: rgb(255,0,0)">[</span><span style="color: rgb(255,0,0)">label</span><span style="color: rgb(255,0,0)">]</span><span style="color: rgb(0,0,0)">&nbsp;;</span></div>
</div>
<p>&nbsp;</p>
</div>
<p><span style="font-weight: bold">五.其他常用命令</span></p>
<div style="margin-left: 40px">1.show procedure status<br />
显示数据库中所有存储的存储过程基本信息，包括所属数据库，存储过程名称，创建时间等<br />
2.show create procedure sp_name<br />
显示某一个存储过程的详细信息</div>
<p>&nbsp;</p>
</div>
<div class="con_sample">
<p>mysql存储过程中要用到的运算符</p>
</div>
<div class="con_all">
<div style="text-align: center">
<h2>mysql存储过程学习总结－操作符</h2>
</div>
<p><strong>算术运算符</strong></p>
<p style="margin-left: 40px">+&nbsp;&nbsp;&nbsp;&nbsp; 加&nbsp;&nbsp; SET var1=2+2;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4<br />
-&nbsp;&nbsp;&nbsp;&nbsp; 减&nbsp;&nbsp; SET var2=3-2;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1<br />
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;乘&nbsp;&nbsp; SET var3=3*2;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6<br />
/&nbsp;&nbsp;&nbsp;&nbsp; 除&nbsp;&nbsp; SET var4=10/3;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3.3333<br />
DIV&nbsp;&nbsp; 整除&nbsp;SET var5=10 DIV 3;&nbsp; 3<br />
%&nbsp;&nbsp;&nbsp;&nbsp; 取模&nbsp;SET var6=10%3 ;&nbsp;&nbsp;&nbsp;&nbsp; 1</p>
<p><strong>比较运算符</strong></p>
<div style="margin-left: 40px">&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 大于&nbsp;1&gt;2&nbsp;False<br />
&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 小于&nbsp;2&lt;1&nbsp;False<br />
&lt;=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 小于等于&nbsp;2&lt;=2&nbsp;True<br />
&gt;=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 大于等于&nbsp;3&gt;=2&nbsp;True<br />
BETWEEN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在两值之间&nbsp;5 BETWEEN 1 AND 10&nbsp;True<br />
NOT BETWEEN&nbsp; 不在两值之间&nbsp;5 NOT BETWEEN 1 AND 10&nbsp;False<br />
IN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在集合中&nbsp;5 IN (1,2,3,4)&nbsp;False<br />
NOT IN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不在集合中&nbsp;5 NOT IN (1,2,3,4)&nbsp;True<br />
=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;等于&nbsp;2=3&nbsp;False<br />
&lt;&gt;, !=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不等于&nbsp;2&lt;&gt;3&nbsp;False<br />
&lt;=&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 严格比较两个NULL值是否相等&nbsp;NULL&lt;=&gt;NULL&nbsp;True<br />
LIKE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;简单模式匹配&nbsp;"Guy Harrison" LIKE "Guy%"&nbsp;True<br />
REGEXP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 正则式匹配&nbsp;"Guy Harrison" REGEXP "[Gg]reg"&nbsp;False<br />
IS NULL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为空&nbsp;0 IS NULL&nbsp;False<br />
IS NOT NULL&nbsp; 不为空&nbsp;0 IS NOT NULL&nbsp;True</div>
<p><strong>逻辑运算符</strong></p>
<p><strong>与</strong>(AND)</p>
<p style="margin-left: 40px"><br />
<br />
<meta content="OpenOffice.org 2.0  (Linux)" name="GENERATOR" /><br />
<meta content="20061101;13545200" name="CREATED" /><br />
<meta content="16010101;0" name="CHANGED" /><br />
<style type="text/css">
<!-- @page { size: 8.5in 11in; margin: 0.79in }
		TD P { margin-bottom: 0in }
		TH P { margin-bottom: 0in; font-style: italic }
		P { margin-bottom: 0.08in }
	-->
</style>
<p>
<center>
<p>&nbsp;</p>
<table bordercolor="#000000" cellspacing="0" cellpadding="4" width="464" border="1">
    <colgroup>
    <col width="107"></col>
    <col width="108"></col>
    <col width="108"></col>
    <col width="107"></col>
    <p>&nbsp;</p>
    <thead>
        <tr valign="top">
            <th width="107">
            <p><font size="1">AND</font></p>
            </th>
            <th width="108">
            <p><font size="1">TRUE</font></p>
            </th>
            <th width="108">
            <p><font size="1">FALSE</font></p>
            </th>
            <th width="107">
            <p><font size="1">NULL</font></p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr valign="top">
            <td width="107">
            <p align="left"><font size="1">TRUE</font></p>
            </td>
            <td width="108">
            <p align="left"><font size="1">TRUE</font></p>
            </td>
            <td width="108">
            <p align="left"><font size="1">FALSE</font></p>
            </td>
            <td width="107">
            <p align="left"><font size="1">NULL</font></p>
            </td>
        </tr>
        <tr valign="top">
            <td width="107">
            <p align="left"><font size="1">FALSE</font></p>
            </td>
            <td width="108">
            <p align="left"><font size="1">FALSE</font></p>
            </td>
            <td width="108">
            <p align="left"><font size="1">FALSE</font></p>
            </td>
            <td width="107">
            <p align="left"><font size="1">NULL</font></p>
            </td>
        </tr>
        <tr valign="top">
            <td width="107">
            <p align="left"><font size="1">NULL</font></p>
            </td>
            <td width="108">
            <p align="left"><font size="1">NULL</font></p>
            </td>
            <td width="108">
            <p align="left"><font size="1">NULL</font></p>
            </td>
            <td width="107">
            <p align="left"><font size="1">NULL</font></p>
            </td>
        </tr>
    </tbody>
</table>
<p></center></p>
<p><strong>或(OR)</strong> </p>
<div style="margin-left: 40px">
<style type="text/css">
<!-- @page { size: 8.5in 11in; margin: 0.79in }
		TD P { margin-bottom: 0in }
		TH P { margin-bottom: 0in; font-style: italic }
		P { margin-bottom: 0.08in }
	-->
</style>
<p>
<center>
<p>&nbsp;</p>
<table bordercolor="#000000" cellspacing="0" cellpadding="4" width="464" border="1">
    <colgroup>
    <col width="107"></col>
    <col width="108"></col>
    <col width="108"></col>
    <col width="107"></col>
    <p>&nbsp;</p>
    <thead>
        <tr valign="top">
            <th width="107">
            <p><font size="1">OR</font></p>
            </th>
            <th width="108">
            <p><font size="1">TRUE</font></p>
            </th>
            <th width="108">
            <p><font size="1">FALSE</font></p>
            </th>
            <th width="107">
            <p><font size="1">NULL</font></p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr valign="top">
            <td width="107">
            <p align="left"><font size="1">TRUE</font></p>
            </td>
            <td width="108">
            <p align="left"><font size="1">TRUE</font></p>
            </td>
            <td width="108">
            <p align="left"><font size="1">TRUE</font></p>
            </td>
            <td width="107">
            <p align="left"><font size="1">TRUE</font></p>
            </td>
        </tr>
        <tr valign="top">
            <td width="107">
            <p align="left"><font size="1">FALSE</font></p>
            </td>
            <td width="108">
            <p align="left"><font size="1">TRUE</font></p>
            </td>
            <td width="108">
            <p align="left"><font size="1">FALSE</font></p>
            </td>
            <td width="107">
            <p align="left"><font size="1">NULL</font></p>
            </td>
        </tr>
        <tr valign="top">
            <td width="107">
            <p align="left"><font size="1">NULL</font></p>
            </td>
            <td width="108">
            <p align="left"><font size="1">TRUE</font></p>
            </td>
            <td width="108">
            <p align="left"><font size="1">NULL</font></p>
            </td>
            <td width="107">
            <p align="left"><font size="1">NULL</font></p>
            </td>
        </tr>
    </tbody>
</table>
<p></center></p>
</div>
<p><strong>异或(XOR)</strong> </p>
<div style="margin-left: 40px">
<style type="text/css">
<!-- @page { size: 8.5in 11in; margin: 0.79in }
		TD P { margin-bottom: 0in }
		TH P { margin-bottom: 0in; font-style: italic }
		P { margin-bottom: 0.08in }
	-->
</style>
<p>
<center>
<p>&nbsp;</p>
<table bordercolor="#000000" cellspacing="0" cellpadding="4" width="464" align="center" summary="" border="1">
    <colgroup>
    <col width="107"></col>
    <col width="108"></col>
    <col width="108"></col>
    <col width="107"></col>
    <p>&nbsp;</p>
    <thead>
        <tr valign="top">
            <th width="107">
            <p><font size="1">XOR</font></p>
            </th>
            <th width="108">
            <p><font size="1">TRUE</font></p>
            </th>
            <th width="108">
            <p><font size="1">FALSE</font></p>
            </th>
            <th width="107">
            <p><font size="1">NULL</font></p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr valign="top">
            <td width="107">
            <p align="left"><font size="1">TRUE</font></p>
            </td>
            <td width="108">
            <p align="left"><font size="1">FALSE</font></p>
            </td>
            <td width="108">
            <p align="left"><font size="1">TRUE</font></p>
            </td>
            <td width="107">
            <p align="left"><font size="1">NULL</font></p>
            </td>
        </tr>
        <tr valign="top">
            <td width="107">
            <p align="left"><font size="1">FALSE</font></p>
            </td>
            <td width="108">
            <p align="left"><font size="1">TRUE</font></p>
            </td>
            <td width="108">
            <p align="left"><font size="1">FALSE</font></p>
            </td>
            <td width="107">
            <p align="left"><font size="1">NULL</font></p>
            </td>
        </tr>
        <tr valign="top">
            <td width="107">
            <p align="left"><font size="1">NULL</font></p>
            </td>
            <td width="108">
            <p align="left"><font size="1">NULL</font></p>
            </td>
            <td width="108">
            <p align="left"><font size="1">NULL</font></p>
            </td>
            <td width="107">
            <p align="left"><font size="1">NULL</font></p>
            </td>
        </tr>
    </tbody>
</table>
<p></center></p>
</div>
<p><strong>位运算符</strong></p>
<p style="margin-left: 40px">|&nbsp;&nbsp; 位或<br />
&amp;&nbsp;&nbsp; 位与<br />
&lt;&lt;&nbsp; 左移位<br />
&gt;&gt;&nbsp; 右移位<br />
~&nbsp;&nbsp; 位非(单目运算，按位取反)</p>
<p>&nbsp;</p>
</div>
<div class="con_sample">
<p>mysq存储过程中常用的函数，字符串类型操作，数学类，日期时间类。</p>
</div>
<div class="con_all">
<div style="text-align: center">
<h1>mysql存储过程基本函数</h1>
</div>
<p><span style="font-weight: bold">一.字符串类</span>&nbsp;</p>
<div style="margin-left: 40px">CHARSET(str) //返回字串字符集<br />
CONCAT (string2&nbsp; [,&#8230; ]) //连接字串<br />
INSTR (string ,substring ) //返回substring首次在string中出现的位置,不存在返回0<br />
LCASE (string2 ) //转换成小写<br />
LEFT (string2 ,length ) //从string2中的左边起取length个字符<br />
LENGTH (string ) //string长度<br />
LOAD_FILE (file_name ) //从文件读取内容<br />
LOCATE (substring , string&nbsp; [,start_position ] ) 同INSTR,但可指定开始位置<br />
LPAD (string2 ,length ,pad ) //重复用pad加在string开头,直到字串长度为length<br />
LTRIM (string2 ) //去除前端空格<br />
REPEAT (string2 ,count ) //重复count次<br />
REPLACE (str ,search_str ,replace_str ) //在str中用replace_str替换search_str<br />
RPAD (string2 ,length ,pad) //在str后用pad补充,直到长度为length<br />
RTRIM (string2 ) //去除后端空格<br />
STRCMP (string1 ,string2 ) //逐字符比较两字串大小,<br />
SUBSTRING (str , position&nbsp; [,length ]) //从str的position开始,取length个字符,<br />
<span style="color: rgb(255,0,0)">注：mysql中处理字符串时，默认第一个字符下标为1</span>，即参数position必须大于等于1
<p>&nbsp;</p>
<div style="margin-left: 40px">mysql&gt; select substring(&#8217;abcd&#8217;,0,2);<br />
+———————&#8211;+<br />
| substring(&#8217;abcd&#8217;,0,2) |<br />
+———————&#8211;+<br />
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
+———————&#8211;+<br />
1 row in set (0.00 sec)
<p>&nbsp;</p>
</div>
<div style="margin-left: 40px">mysql&gt; select substring(&#8217;abcd&#8217;,1,2);<br />
+———————&#8211;+<br />
| substring(&#8217;abcd&#8217;,1,2) |<br />
+———————&#8211;+<br />
| ab&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
+———————&#8211;+<br />
1 row in set (0.02 sec)</div>
<p>TRIM([[BOTH|LEADING|TRAILING] [padding] FROM]string2) //去除指定位置的指定字符<br />
UCASE (string2 ) //转换成大写<br />
RIGHT(string2,length) //取string2最后length个字符<br />
SPACE(count) //生成count个空格&nbsp;</p>
</div>
<p><span style="font-weight: bold">二.数学类</span></p>
<div style="margin-left: 40px">ABS (number2 ) //绝对值<br />
BIN (decimal_number ) //十进制转二进制<br />
CEILING (number2 ) //向上取整<br />
CONV(number2,from_base,to_base) //进制转换<br />
FLOOR (number2 ) //向下取整<br />
FORMAT (number,decimal_places ) //保留小数位数<br />
HEX (DecimalNumber ) //转十六进制<br />
注：HEX()中可传入字符串，则返回其ASC-11码，如HEX(&#8217;DEF&#8217;)返回4142143<br />
也可以传入十进制整数，返回其十六进制编码，如HEX(25)返回19<br />
LEAST (number , number2&nbsp; [,..]) //求最小值<br />
MOD (numerator ,denominator ) //求余<br />
POWER (number ,power ) //求指数<br />
RAND([seed]) //随机数<br />
ROUND (number&nbsp; [,decimals ]) //四舍五入,decimals为小数位数]
<p>&nbsp;</p>
<div style="margin-left: 40px">注：返回类型并非均为整数，如：<br />
(1)默认变为整形值<br />
mysql&gt; select round(1.23);<br />
+————-+<br />
| round(1.23) |<br />
+————-+<br />
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1 |<br />
+————-+<br />
1 row in set (0.00 sec)
<p>&nbsp;</p>
<p>mysql&gt; select round(1.56);<br />
+————-+<br />
| round(1.56) |<br />
+————-+<br />
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2 |<br />
+————-+<br />
1 row in set (0.00 sec)</p>
<p><span style="color: rgb(255,0,0)">(2)可以设定小数位数，返回浮点型数据</span><br />
mysql&gt; select round(1.567,2);<br />
+—————-+<br />
| round(1.567,2) |<br />
+—————-+<br />
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.57 |<br />
+—————-+<br />
1 row in set (0.00 sec)</p>
</div>
<p>SIGN (number2 ) //返回符号,正负或0<br />
SQRT(number2) //开平方</p>
</div>
<p>&nbsp;<br />
<span style="font-weight: bold">三.日期时间类</span><br />
&nbsp;</p>
<div style="margin-left: 40px">ADDTIME (date2 ,time_interval ) //将time_interval加到date2<br />
CONVERT_TZ (datetime2 ,fromTZ ,toTZ ) //转换时区<br />
CURRENT_DATE (&nbsp; ) //当前日期<br />
CURRENT_TIME (&nbsp; ) //当前时间<br />
CURRENT_TIMESTAMP (&nbsp; ) //当前时间戳<br />
DATE (datetime ) //返回datetime的日期部分<br />
DATE_ADD (date2 , INTERVAL d_value d_type ) //在date2中加上日期或时间<br />
DATE_FORMAT (datetime ,FormatCodes ) //使用formatcodes格式显示datetime<br />
DATE_SUB (date2 , INTERVAL d_value d_type ) //在date2上减去一个时间<br />
DATEDIFF (date1 ,date2 ) //两个日期差<br />
DAY (date ) //返回日期的天<br />
DAYNAME (date ) //英文星期<br />
DAYOFWEEK (date ) //星期(1-7) ,1为星期天<br />
DAYOFYEAR (date ) //一年中的第几天<br />
EXTRACT (interval_name&nbsp; FROM date ) //从date中提取日期的指定部分<br />
MAKEDATE (year ,day ) //给出年及年中的第几天,生成日期串<br />
MAKETIME (hour ,minute ,second ) //生成时间串<br />
MONTHNAME (date ) //英文月份名<br />
NOW (&nbsp; ) //当前时间<br />
SEC_TO_TIME (seconds ) //秒数转成时间<br />
STR_TO_DATE (string ,format ) //字串转成时间,以format格式显示<br />
TIMEDIFF (datetime1 ,datetime2 ) //两个时间差<br />
TIME_TO_SEC (time ) //时间转秒数]<br />
WEEK (date_time [,start_of_week ]) //第几周<br />
YEAR (datetime ) //年份<br />
DAYOFMONTH(datetime) //月的第几天<br />
HOUR(datetime) //小时<br />
LAST_DAY(date) //date的月的最后日期<br />
MICROSECOND(datetime) //微秒<br />
MONTH(datetime) //月<br />
MINUTE(datetime) //分</div>
<p>&nbsp;</p>
<div style="margin-left: 40px">附:可用在INTERVAL中的类型<br />
DAY ,DAY_HOUR ,DAY_MINUTE ,DAY_SECOND ,HOUR ,HOUR_MINUTE ,HOUR_SECOND ,MINUTE ,MINUTE_SECOND,MONTH ,SECOND ,YEAR&nbsp; </div>
</div>
<img src ="http://www.blogjava.net/lcs/aggbug/148019.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcs/" target="_blank">lk</a> 2007-09-25 12:02 <a href="http://www.blogjava.net/lcs/archive/2007/09/25/148019.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>mysql 语法（陆续补充）</title><link>http://www.blogjava.net/lcs/archive/2007/09/25/148016.html</link><dc:creator>lk</dc:creator><author>lk</author><pubDate>Tue, 25 Sep 2007 03:48:00 GMT</pubDate><guid>http://www.blogjava.net/lcs/archive/2007/09/25/148016.html</guid><wfw:comment>http://www.blogjava.net/lcs/comments/148016.html</wfw:comment><comments>http://www.blogjava.net/lcs/archive/2007/09/25/148016.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lcs/comments/commentRss/148016.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lcs/services/trackbacks/148016.html</trackback:ping><description><![CDATA[查询MySQL版本，有两种方法：<br />
<p class="code">SHOW VARIABLES LIKE 'version';<br />
or<br />
SELECT VERSION();<br />
&nbsp;<br />
SHOW &nbsp; TABLES &nbsp; FROM &nbsp; database;&nbsp;&nbsp;&nbsp;&nbsp; 查看数据库里面所有的表，<br />
执行&nbsp;&nbsp;&nbsp; desc &nbsp; table_name;&nbsp;&nbsp;&nbsp;&nbsp; 或者&nbsp;&nbsp;&nbsp;&nbsp; <br />
show &nbsp; columns &nbsp; from &nbsp; talbe_name;&nbsp;&nbsp;&nbsp;&nbsp; 查看表中的所有的列<br />
<br />
查看数据库<br />
show&nbsp;databases;<br />
查看表<br />
show&nbsp;tables; <br />
show&nbsp;create&nbsp;table&nbsp;table_name; <br />
<br />
统计一个表的字段数</p>
select &nbsp; count(*) &nbsp; from &nbsp; syscolumns &nbsp; A &nbsp; inner &nbsp; join &nbsp; sysobjects &nbsp; B &nbsp; on &nbsp; A.id=B.id &nbsp; &nbsp; <br />
&nbsp; where &nbsp; B.name='表名'<br />
(<span style="color: red">注：这个lcs没看懂，有明白的请给解释一下</span>)<br />
<br />
=======================<br />
<p>1.如何给标识列插入值</p>
<p>表中第一个字段id为标识列<br />
insert into table values (null,'aa',1)</p>
<p>2.如果表存在删除表</p>
<p>drop table if exists tablename</p>
<p>3.date too long for column 解决方法</p>
<p>我用的是5.1，昨天把mysql,php,phpmyadmin的字符集都改成utf8后，用load data infile 命令插入数据时总是出现这样的错误提示：data too long for column 'cname' at row 1;网上搜一下，大都说set character_set=utf8之类的，但还是不行，最后找到了一个：<br />
修改my.ini文件，将<br />
sql-mode=STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION<br />
注释掉，ok！<br />
Update:mysql5在phpmyadmin无法连接时执行的语句：<br />
SET PASSWORD FOR &#8216;root&#8217;@'localhost&#8217; = OLD_PASSWORD(&#8217;[newpassword]&#8216;);</p>
<p>刚才在导入数据的时候，navicat报错:<br />
Data too long for column &#8216;ip&#8217; at row 1<br />
提示数据对于ip字段太长</p>
<p>如果数据类型不正确,也会出错,而不像4.*那样自动转换:<br />
sendQuery:Incorrect datetime value: &#8216;未知&#8217; for column &#8216;date&#8217; at row 1</p>
<p>如果是数据x (int 11)类型的可能有些奇怪:<br />
insert into a (x) values (&#8217;a')<br />
出现:<br />
Out of range value adjusted for column &#8216;x&#8217; at row 1</p>
<p>insert into a (x) values (&#8217;11a&#8217;)<br />
出现:<br />
Data truncated for column &#8216;x&#8217; at row 1</p>
<p>解决办法:<br />
在my.ini里找到<br />
sql-mode=&#8221;STRICT_TRANS_TABLES,NO_AUTO_Create_USER,NO_ENGINE_SUBSTITUTION&#8221;<br />
把其中的<br />
STRICT_TRANS_TABLES,<br />
去掉,然后重启mysql就ok了</p>
<p>4.分页语句<br />
select * from table where ... order by ... limit n,n</p>
<p>5.mysql 5.0 中文乱码问题<br />
解决mysql5.0的中文乱码问题，只要按下面三步做就可以了：<br />
　1.第一步，修改MySql的配置文件my.ini：<br />
&nbsp;&nbsp;&nbsp;&nbsp; 在安装好Mysql后，在Mysql所在的目录下有一个my.ini文件，修改这个my.ini文件，修改方式如下：<br />
　　　1.1 在[client] 的后面加一条 default-character-set=gb2312<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.2 把[mysql] 的后面 default-character-set=latin1 改成 default-character-set=gb2312<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.3 把[mysqd] 的后面 default-character-set=latin1 改成 default-character-set=gb2312<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.4 在改了上面三处后，后面还一个default-character-set=latin1,这个default-character-set的作用是指定在创建新的表或数据库</p>
<p>时，所使用的默认字符编码,为了方便创建新的表或数据库，建议把定个 default-character-set也改成gb2312。</p>
<p>&nbsp; 2.第二步，设置与数据库连接的字符串：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在连接字符串(URL)后加上?useUnicode=true&amp;amp;characterEncoding=gb2312这一句，具体如下：<br />
　　&lt;bean id="dataSource"<br />
&nbsp; class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt;<br />
&nbsp; &lt;property name="driverClassName"&gt;<br />
&nbsp;&nbsp; &lt;value&gt;com.mysql.jdbc.Driver&lt;/value&gt;<br />
&nbsp; &lt;/property&gt;<br />
&nbsp; &lt;property name="url"&gt;<br />
&nbsp;&nbsp; &lt;value&gt;jdbc:mysql://localhost:3306/数据库名?useUnicode=true&amp;amp;characterEncoding=gb2312&lt;/value&gt;<br />
&nbsp; &lt;/property&gt;<br />
&nbsp; &lt;property name="username"&gt;<br />
&nbsp;&nbsp; &lt;value&gt;用户名&lt;/value&gt;<br />
&nbsp; &lt;/property&gt;<br />
&nbsp; &lt;property name="password"&gt;<br />
&nbsp;&nbsp; &lt;value&gt;密码&lt;/value&gt;<br />
&nbsp; &lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;<br />
&nbsp;&nbsp; 3.第三步，在java代码，把SQL语句转换成gb2312的编码，然后再执行该SQL.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3.1 把字符串转换成gb2312的编码的方式如下：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static String GB2312Converter(String str) {<br />
&nbsp; if (str == null) {<br />
&nbsp;&nbsp; str = "";<br />
&nbsp; } else {<br />
&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp; str = new String(str.getBytes("gb2312"), "gb2312");<br />
&nbsp;&nbsp; } catch (Exception ex) {<br />
&nbsp;&nbsp;&nbsp; ex.printStackTrace();<br />
&nbsp;&nbsp; }<br />
&nbsp; }<br />
&nbsp; return str;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3.2 获取gb2312编码的sql语句：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String sql = "select name from user ";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sql = GB2312Converter(sql); // 获取gb2312编码的sql语句,然后就可以执行该sql语句了。</p>
<p>&nbsp;</p>
<br />
<br />
===============<br />
Show index from b (subs)<br />
<br />
------<br />
EXPLAIN SELECT *<br />
FROM items, subs<br />
WHERE items.channel_id = subs.channel_id<br />
AND subs.user_id =3<br />
ORDER BY items.created_at<br />
LIMIT 20 ;<br />
<br />
=============================<br />
一句话实现乱序查询<br />
<br />
select * from a ORDER by rand()<br />
<br />
<img src ="http://www.blogjava.net/lcs/aggbug/148016.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lcs/" target="_blank">lk</a> 2007-09-25 11:48 <a href="http://www.blogjava.net/lcs/archive/2007/09/25/148016.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>