﻿<?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>C++博客-编程之道-随笔分类-数据库</title><link>http://www.cppblog.com/ispfcn/category/1307.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 22 May 2008 03:06:43 GMT</lastBuildDate><pubDate>Thu, 22 May 2008 03:06:43 GMT</pubDate><ttl>60</ttl><item><title>使用 C 语言操作 MySQL</title><link>http://www.cppblog.com/ispfcn/archive/2006/04/06/5110.html</link><dc:creator>编程之道</dc:creator><author>编程之道</author><pubDate>Thu, 06 Apr 2006 06:29:00 GMT</pubDate><guid>http://www.cppblog.com/ispfcn/archive/2006/04/06/5110.html</guid><wfw:comment>http://www.cppblog.com/ispfcn/comments/5110.html</wfw:comment><comments>http://www.cppblog.com/ispfcn/archive/2006/04/06/5110.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/ispfcn/comments/commentRss/5110.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/ispfcn/services/trackbacks/5110.html</trackback:ping><description><![CDATA[发现了一篇文章，感觉还不错，不过没测试，是不是在linux下能用<br /><a href="http://www.unix-cd.com/unixcd12/article_view.asp?id=4138">http://www.unix-cd.com/unixcd12/article_view.asp?id=4138</a><br />贴一段以前在windows上使用mysql的代码。<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080"> 1</span><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000">#include </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 2</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 3</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">winsock2.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 4</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">mysql.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 5</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><br /></span><span style="COLOR: #008080"> 6</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#pragma comment(lib,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">libmySQL.lib</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)<br /></span><span style="COLOR: #008080"> 7</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><br /></span><span style="COLOR: #008080"> 8</span><span style="COLOR: #000000"><img id="Codehighlighter1_129_1183_Open_Image" onclick="this.style.display='none'; Codehighlighter1_129_1183_Open_Text.style.display='none'; Codehighlighter1_129_1183_Closed_Image.style.display='inline'; Codehighlighter1_129_1183_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_129_1183_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_129_1183_Closed_Text.style.display='none'; Codehighlighter1_129_1183_Open_Image.style.display='inline'; Codehighlighter1_129_1183_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> main()</span><span id="Codehighlighter1_129_1183_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_129_1183_Open_Text"><span style="COLOR: #000000">{<br /></span><span style="COLOR: #008080"> 9</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />   MYSQL </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">mysql;<br /></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />   MYSQL_RES </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">res;<br /></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />   MYSQL_ROW row;<br /></span><span style="COLOR: #008080">12</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />   </span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">query;<br /></span><span style="COLOR: #008080">13</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />   </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> t,r;<br /></span><span style="COLOR: #008080">14</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />   <br /></span><span style="COLOR: #008080">15</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /></span><span style="COLOR: #008080">16</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />   mysql</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">mysql_init(mysql);<br /></span><span style="COLOR: #008080">17</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />   </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (</span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">mysql_real_connect(mysql,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">localhost</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">root</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ceshi</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,NULL,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">))<br /></span><span style="COLOR: #008080">18</span><span style="COLOR: #000000"><img id="Codehighlighter1_323_402_Open_Image" onclick="this.style.display='none'; Codehighlighter1_323_402_Open_Text.style.display='none'; Codehighlighter1_323_402_Closed_Image.style.display='inline'; Codehighlighter1_323_402_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_323_402_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_323_402_Closed_Text.style.display='none'; Codehighlighter1_323_402_Open_Image.style.display='inline'; Codehighlighter1_323_402_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />   </span><span id="Codehighlighter1_323_402_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_323_402_Open_Text"><span style="COLOR: #000000">{<br /></span><span style="COLOR: #008080">19</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />       printf( </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Error connecting to database: %s\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,mysql_error(mysql));<br /></span><span style="COLOR: #008080">20</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />   }</span></span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080">21</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />   </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080">22</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />       printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Connected<img src="http://www.cppblog.com/images/dot.gif" />\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /></span><span style="COLOR: #008080">23</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /></span><span style="COLOR: #008080">24</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />   query</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Insert Into admin(username,password) values('whoami','iampf')</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br /></span><span style="COLOR: #008080">25</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />   t</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">mysql_real_query(mysql,query,(unsigned </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">)strlen(query));<br /></span><span style="COLOR: #008080">26</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />   </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(t)<br /></span><span style="COLOR: #008080">27</span><span style="COLOR: #000000"><img id="Codehighlighter1_594_652_Open_Image" onclick="this.style.display='none'; Codehighlighter1_594_652_Open_Text.style.display='none'; Codehighlighter1_594_652_Closed_Image.style.display='inline'; Codehighlighter1_594_652_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_594_652_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_594_652_Closed_Text.style.display='none'; Codehighlighter1_594_652_Open_Image.style.display='inline'; Codehighlighter1_594_652_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />   </span><span id="Codehighlighter1_594_652_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_594_652_Open_Text"><span style="COLOR: #000000">{<br /></span><span style="COLOR: #008080">28</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />       printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Insert Error:%s\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,mysql_error(mysql));<br /></span><span style="COLOR: #008080">29</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />   }</span></span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080">30</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /></span><span style="COLOR: #008080">31</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />   query</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">select * from admin</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br /></span><span style="COLOR: #008080">32</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />   t</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">mysql_real_query(mysql,query,(unsigned </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">) strlen(query));<br /></span><span style="COLOR: #008080">33</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />   </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (t)<br /></span><span style="COLOR: #008080">34</span><span style="COLOR: #000000"><img id="Codehighlighter1_765_847_Open_Image" onclick="this.style.display='none'; Codehighlighter1_765_847_Open_Text.style.display='none'; Codehighlighter1_765_847_Closed_Image.style.display='inline'; Codehighlighter1_765_847_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_765_847_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_765_847_Closed_Text.style.display='none'; Codehighlighter1_765_847_Open_Image.style.display='inline'; Codehighlighter1_765_847_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />   </span><span id="Codehighlighter1_765_847_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_765_847_Open_Text"><span style="COLOR: #000000">{<br /></span><span style="COLOR: #008080">35</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />      printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Error making query: %s\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,<br /></span><span style="COLOR: #008080">36</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />              mysql_error(mysql));<br /></span><span style="COLOR: #008080">37</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />   }</span></span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080">38</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />   </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Query made<img src="http://www.cppblog.com/images/dot.gif" />\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /></span><span style="COLOR: #008080">39</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />   res</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">mysql_use_result(mysql);<br /></span><span style="COLOR: #008080">40</span><span style="COLOR: #000000"><img id="Codehighlighter1_959_1158_Open_Image" onclick="this.style.display='none'; Codehighlighter1_959_1158_Open_Text.style.display='none'; Codehighlighter1_959_1158_Closed_Image.style.display='inline'; Codehighlighter1_959_1158_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_959_1158_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_959_1158_Closed_Text.style.display='none'; Codehighlighter1_959_1158_Open_Image.style.display='inline'; Codehighlighter1_959_1158_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />   </span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(r</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;r</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">mysql_field_count(mysql);r</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)</span><span id="Codehighlighter1_959_1158_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_959_1158_Open_Text"><span style="COLOR: #000000">{<br /></span><span style="COLOR: #008080">41</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />           row</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">mysql_fetch_row(res);<br /></span><span style="COLOR: #008080">42</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />           </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(row</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">) </span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br /></span><span style="COLOR: #008080">43</span><span style="COLOR: #000000"><img id="Codehighlighter1_1073_1127_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1073_1127_Open_Text.style.display='none'; Codehighlighter1_1073_1127_Closed_Image.style.display='inline'; Codehighlighter1_1073_1127_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_1073_1127_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1073_1127_Closed_Text.style.display='none'; Codehighlighter1_1073_1127_Open_Image.style.display='inline'; Codehighlighter1_1073_1127_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />           </span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(t</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;t</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">mysql_num_fields(res);t</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)</span><span id="Codehighlighter1_1073_1127_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_1073_1127_Open_Text"><span style="COLOR: #000000">{<br /></span><span style="COLOR: #008080">44</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />                   printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%s </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,row[t]);<br /></span><span style="COLOR: #008080">45</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />           }</span></span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080">46</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />           printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /></span><span style="COLOR: #008080">47</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />   }</span></span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080">48</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />   mysql_close(mysql);<br /></span><span style="COLOR: #008080">49</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080">50</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><br /></span><span style="COLOR: #008080">51</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span></div><img src ="http://www.cppblog.com/ispfcn/aggbug/5110.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ispfcn/" target="_blank">编程之道</a> 2006-04-06 14:29 <a href="http://www.cppblog.com/ispfcn/archive/2006/04/06/5110.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows上的MySQL UDF开发</title><link>http://www.cppblog.com/ispfcn/archive/2006/04/06/5075.html</link><dc:creator>编程之道</dc:creator><author>编程之道</author><pubDate>Thu, 06 Apr 2006 04:02:00 GMT</pubDate><guid>http://www.cppblog.com/ispfcn/archive/2006/04/06/5075.html</guid><wfw:comment>http://www.cppblog.com/ispfcn/comments/5075.html</wfw:comment><comments>http://www.cppblog.com/ispfcn/archive/2006/04/06/5075.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/ispfcn/comments/commentRss/5075.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/ispfcn/services/trackbacks/5075.html</trackback:ping><description><![CDATA[
		<p>终于发现了篇不错的Mysql开发的文章<br />曾以为Windows版本的MySQL存在不能使用UDF的BUG诸提交了一个bug报告。不过<br />似乎发现是我搞错了，MySQL的技术支持人员给了非常完美的解答，同大家分享<br />一下。下边是原文回复 :)<br /><br />Sorry this isn't a bug.<br />Below I pasted a sample I did sometime ago for another user:<br /><br />Ok. Assuming you have VC++ and the source distribution and a server<br />running,<br />I will create a UDF that returns a name:<br /><br />Note: the sample is ugly, but the purpose here is to show you how<br />to handle the UDF.<br /><br />- Open the mysqld.dsw workspace.<br />- Add New project to the workspace<br />- Project name: my_udf<br />- Select Win32 Dynamic-Link Library<br />- Click OK<br />- Select An Empty DLL project<br />- Click Finish<br />- Click OK<br />- Add a new file called my_udf.cpp to the project:<br /><br />#include &lt;stdlib.h&gt;<br />#include &lt;winsock.h&gt;<br />#include &lt;mysql.h&gt;<br /><br />extern "C" {<br />char *my_name(UDF_INIT *initid, UDF_ARGS *args, char *is_null,<br />char *error);<br />}<br /><br />char *my_name(UDF_INIT *initid, UDF_ARGS *args, char *is_null,<br />char *error)<br />{<br />char * me = "my name";<br /><br />return me;<br />}<br /><br />- Type Ctrl+N for to create a new file.<br />- Select text type<br />- File name: my_udf.def<br />- Edit the above file with the below contents:<br />LIBRARY UDF_EXAMPLE<br />DESCRIPTION 'Example Using UDF with VC++'<br />VERSION 1.0<br />EXPORTS<br />my_name<br /><br />- Right Click the my_udf project and select Settings<br />- Click the C/C++ tab<br />- Select General in the Category Combo<br />- Add the macro HAVE_DLOPEN to the PreProcessor definition<br />- Select Preprocessor in the Category Combo<br />- Add the include path to the text box: Additional Include directories<br />e.g: ../include<br />- Press F7 for to build the DLL.<br /><br />- Copy the my_udf.dll to the environment path directory:<br />\winnt\system32 for example.<br /><br />- Start the mysql client and issue:<br /><br />C:\mysql-udf\bin&gt;mysql -uroot -p<br />Enter password:<br />Welcome to the MySQL monitor. Commands end with ; or \g.<br />Your MySQL connection id is 2 to server version: 3.23.52-max-nt<br /><br />Type 'help;' or '\h' for help. Type '\c' to clear the buffer.<br /><br />mysql&gt; CREATE FUNCTION my_name RETURNS STRING SONAME "my_udf.dll";<br />Query OK, 0 rows affected (0.08 sec)<br /><br />mysql&gt; select my_name();<br /><br />mysql&gt; drop function my_name;<br />Query OK, 0 rows affected (0.00 sec)<br /><br />画蛇添足的作下简要中文说明。<br /><br />抱歉，这并不是一个bug。下面我粘贴一个以前为某个客户做的简例，假设你有了<br />VC++,源码分发，并且有一个正常运行的MySQL服务器。<br /><br />我将创建一个UDF它将一个名字：<br />注意：例子非常简陋，目的是让你了解该如何处理手头的UDF。<br /><br />- 打开 mysqld.dsw 工作区。<br />- 添加新项目到这个工作区<br />- Project name: my_udf // 项目名称:my_udf<br />- 选择 Win32 Dynamic-Link Library // Win32动态连接库<br />- 点击 OK<br />- 选择 An Empty DLL project // 一个空DLL项目<br />- 点击 Finish<br />- 点击 OK<br />- 添加新文件 my_udf.cpp 到项目中:<br />#include &lt;stdlib.h&gt;<br />#include &lt;winsock.h&gt;<br />#include &lt;mysql.h&gt;<br /><br />extern "C" {<br />char *my_name(UDF_INIT *initid, UDF_ARGS *args, char *is_null,<br />char *error);<br />// 兼容C<br />}<br /><br />char *my_name(UDF_INIT *initid, UDF_ARGS *args, char *is_null,<br />char *error)<br />{<br />char * me = "my name";<br /><br />return me;<br />// 调用此UDF将返回 my name<br />}<br />- 按 Ctrl+N 来创建一个新文件。<br />- 选择 text 类型<br />- File name: my_udf.def file://文件名：my_udf.def<br />- 按照下边的内容编辑文件。<br />LIBRARY UDF_EXAMPLE<br />DESCRIPTION 'Example Using UDF with VC++'<br />VERSION 1.0<br />EXPORTS<br />my_name<br /><br />- 右击my_udf项目并选择Settings<br />- 点 C/C++ 选项卡<br />- 选择 General<br />- 添加宏 HAVE_DLOPE 到预处理器定义<br />- 选择 Preprocessor<br />- 添加头文件路径: Additional Include directories<br />例如: ../include<br />- 按 F7 去编译成 DLL.<br /><br />- 复制 my_udf.dll 到环境变量path定义过的目录<br />比如 \winnt\system32 。<br /><br />- 打开mysql客户端<br /><br />C:\mysql-udf\bin&gt;mysql -uroot -p<br />Enter password:<br />Welcome to the MySQL monitor. Commands end with ; or \g.<br />Your MySQL connection id is 2 to server version: 3.23.52-max-nt<br /><br />Type 'help;' or '\h' for help. Type '\c' to clear the buffer.<br /><br />mysql&gt; CREATE FUNCTION my_name RETURNS STRING SONAME "my_udf.dll";<br />Query OK, 0 rows affected (0.08 sec)<br /><br />mysql&gt; select my_name();<br /><br />mysql&gt; drop function my_name;<br />Query OK, 0 rows affected (0.00 sec)<br /><br /><br />ok!欢迎大家来MySQL板交流UDF设计经验！我的电子邮件是HeartIcy@163.com，<br />手机13706410308。同时，我们MySQL板准备开始系统化持续性翻译MySQL文档，<br />希望大家多多支持共同完成这一项目。<br /><br />HeartIcy<br />2003年5月17日于中国济南<br /></p>
<img src ="http://www.cppblog.com/ispfcn/aggbug/5075.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ispfcn/" target="_blank">编程之道</a> 2006-04-06 12:02 <a href="http://www.cppblog.com/ispfcn/archive/2006/04/06/5075.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>提高mysql性能的方法</title><link>http://www.cppblog.com/ispfcn/archive/2006/04/04/4998.html</link><dc:creator>编程之道</dc:creator><author>编程之道</author><pubDate>Tue, 04 Apr 2006 08:42:00 GMT</pubDate><guid>http://www.cppblog.com/ispfcn/archive/2006/04/04/4998.html</guid><wfw:comment>http://www.cppblog.com/ispfcn/comments/4998.html</wfw:comment><comments>http://www.cppblog.com/ispfcn/archive/2006/04/04/4998.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/ispfcn/comments/commentRss/4998.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/ispfcn/services/trackbacks/4998.html</trackback:ping><description><![CDATA[一、问题的提出<br />在应用系统开发初期，由于开发数据库数据比较少，对于查询SQL语句，复杂视图的的编写等体会不出SQL语句各种写法的性能优劣，但是如果将应用系统提交实际应用后，随着数据库中数据的增加，系统的响应速度就成为目前系统需要解决的最主要的问题之一。系统优化中一个很重要的方面就是SQL语句的优化。对于海量数据，劣质SQL语句和优质SQL语句之间的速度差别可以达到上百倍，可见对于一个系统不是简单地能实现其功能就可，而是要写出高质量的 SQL语句，提高系统的可用性。<br /><br />在多数情况下，Oracle使用索引来更快地遍历表，优化器主要根据定义的索引来提高性能。但是，如果在SQL语句的where子句中写的SQL 代码不合理，就会造成优化器删去索引而使用全表扫描，一般就这种SQL语句就是所谓的劣质SQL语句。在编写SQL语句时我们应清楚优化器根据何种原则来删除索引，这有助于写出高性能的SQL语句。<br /><br />二、SQL语句编写注意问题<br />下面就某些SQL语句的where子句编写中需要注意的问题作详细介绍。在这些where子句中，即使某些列存在索引，但是由于编写了劣质的SQL，系统在运行该SQL语句时也不能使用该索引，而同样使用全表扫描，这就造成了响应速度的极大降低。<br /><br />1. IS NULL 与 IS NOT NULL<br />不能用null作索引，任何包含null值的列都将不会被包含在索引中。即使索引有多列这样的情况下，只要这些列中有一列含有null，该列就会从索引中排除。也就是说如果某列存在空值，即使对该列建索引也不会提高性能。<br /><br />任何在where子句中使用is null或is not null的语句优化器是不允许使用索引的。<br /><br />2. 联接列<br /><br />对于有联接的列，即使最后的联接值为一个静态值，优化器是不会使用索引的。我们一起来看一个例子，假定有一个职工表（employee），对于一个职工的姓和名分成两列存放（FIRST_NAME和LAST_NAME），现在要查询一个叫比尔.克林顿（Bill Cliton）的职工。<br /><br />下面是一个采用联接查询的SQL语句，<br /><br />select * from employss<br />where<br />first_name||''||last_name ='Beill Cliton' <br /><br />上面这条语句完全可以查询出是否有Bill Cliton这个员工，但是这里需要注意，系统优化器对基于last_name创建的索引没有使用。<br /><br />当采用下面这种SQL语句的编写，Oracle系统就可以采用基于last_name创建的索引。<br /><br />Select * from employee<br />where<br />first_name ='Beill' and last_name ='Cliton' <br /><br />遇到下面这种情况又如何处理呢？如果一个变量（name）中存放着Bill Cliton这个员工的姓名，对于这种情况我们又如何避免全程遍历，使用索引呢？可以使用一个函数，将变量name中的姓和名分开就可以了，但是有一点需要注意，这个函数是不能作用在索引列上。下面是SQL查询脚本：<br /><br />select * from employee<br />where<br />first_name = SUBSTR('&amp;&amp;name',1,INSTR('&amp;&amp;name',' ')-1)<br />and<br />last_name = SUBSTR('&amp;&amp;name',INSTR('&amp;&amp;name’,' ')+1) <br /><br />3. 带通配符（%）的like语句<br /><br />同样以上面的例子来看这种情况。目前的需求是这样的，要求在职工表中查询名字中包含cliton的人。可以采用如下的查询SQL语句：<br /><br />select * from employee where last_name like '%cliton%' <br /><br />这里由于通配符（%）在搜寻词首出现，所以Oracle系统不使用last_name的索引。在很多情况下可能无法避免这种情况，但是一定要心中有底，通配符如此使用会降低查询速度。然而当通配符出现在字符串其他位置时，优化器就能利用索引。在下面的查询中索引得到了使用：<br /><br />select * from employee where last_name like 'c%' <br /><br />4. Order by语句<br /><br />ORDER BY语句决定了Oracle如何将返回的查询结果排序。Order by语句对要排序的列没有什么特别的限制，也可以将函数加入列中（象联接或者附加等）。任何在Order by语句的非索引项或者有计算表达式都将降低查询速度。<br /><br />仔细检查order by语句以找出非索引项或者表达式，它们会降低性能。解决这个问题的办法就是重写order by语句以使用索引，也可以为所使用的列建立另外一个索引，同时应绝对避免在order by子句中使用表达式。<br /><br />5. NOT<br /><br />我们在查询时经常在where子句使用一些逻辑表达式，如大于、小于、等于以及不等于等等，也可以使用and（与）、or（或）以及not（非）。NOT可用来对任何逻辑运算符号取反。下面是一个NOT子句的例子：<br /><br />... where not (status ='VALID') <br /><br />如果要使用NOT，则应在取反的短语前面加上括号，并在短语前面加上NOT运算符。NOT运算符包含在另外一个逻辑运算符中，这就是不等于（&lt;&gt;）运算符。换句话说，即使不在查询where子句中显式地加入NOT词，NOT仍在运算符中，见下例：<br /><br />... where status &lt;&gt;'INVALID' <br /><br />再看下面这个例子：<br /><br />select * from employee where salary&lt;&gt;3000; <br /><br />对这个查询，可以改写为不使用NOT：<br /><br />select * from employee where salary&lt;3000 or salary&gt;3000; <br /><br />虽然这两种查询的结果一样，但是第二种查询方案会比第一种查询方案更快些。第二种查询允许Oracle对salary列使用索引，而第一种查询则不能使用索引。<br /><br />6. IN和EXISTS<br /><br />有时候会将一列和一系列值相比较。最简单的办法就是在where子句中使用子查询。在where子句中可以使用两种格式的子查询。<br /><br />第一种格式是使用IN操作符：<br /><br />... where column in(select * from ... where ...); <br /><br />第二种格式是使用EXIST操作符：<br /><br />... where exists (select 'X' from ...where ...); <br /><br />我相信绝大多数人会使用第一种格式，因为它比较容易编写，而实际上第二种格式要远比第一种格式的效率高。在Oracle中可以几乎将所有的IN操作符子查询改写为使用EXISTS的子查询。<br /><br />第二种格式中，子查询以‘select 'X'开始。运用EXISTS子句不管子查询从表中抽取什么数据它只查看where子句。这样优化器就不必遍历整个表而仅根据索引就可完成工作（这里假定在where语句中使用的列存在索引）。相对于IN子句来说，EXISTS使用相连子查询，构造起来要比 IN子查询困难一些。<br /><br />通过使用EXIST，Oracle系统会首先检查主查询，然后运行子查询直到它找到第一个匹配项，这就节省了时间。Oracle系统在执行IN子查询时，首先执行子查询，并将获得的结果列表存放在在一个加了索引的临时表中。在执行子查询之前，系统先将主查询挂起，待子查询执行完毕，存放在临时表中以后再执行主查询。这也就是使用EXISTS比使用IN通常查询速度快的原因。<br /><br />同时应尽可能使用NOT EXISTS来代替NOT IN，尽管二者都使用了NOT（不能使用索引而降低速度），NOT EXISTS要比NOT IN查询效率更高。<br /><img src ="http://www.cppblog.com/ispfcn/aggbug/4998.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ispfcn/" target="_blank">编程之道</a> 2006-04-04 16:42 <a href="http://www.cppblog.com/ispfcn/archive/2006/04/04/4998.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何编写高效的MySQL应用</title><link>http://www.cppblog.com/ispfcn/archive/2006/04/04/4992.html</link><dc:creator>编程之道</dc:creator><author>编程之道</author><pubDate>Tue, 04 Apr 2006 06:10:00 GMT</pubDate><guid>http://www.cppblog.com/ispfcn/archive/2006/04/04/4992.html</guid><wfw:comment>http://www.cppblog.com/ispfcn/comments/4992.html</wfw:comment><comments>http://www.cppblog.com/ispfcn/archive/2006/04/04/4992.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/ispfcn/comments/commentRss/4992.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/ispfcn/services/trackbacks/4992.html</trackback:ping><description><![CDATA[借助诸如Apach、Perl、PHP和Python等工具，构建一个MySQL应用时很容易的。然而确保它们运行快速，则需要一点洞察力。本文就是你需要知道的东西。<i></i>  
<p></p><p>MySQL对于成为一个非常快速的数据库服务器有着当之无愧的名声，它也非常容易设置和使用。随着它作为网站后端数据库得声望日增，其效果在去年开始有明显提高。但是很多MySQL用户更多地知道如何创建一个数据库并编写对它的查询。就像成千上万的人通过载闲暇时用Linux做实验来学习Unix那样，很多人通过玩MySQL学习关系数据库。这些MySQL新手的大多数既没有关系数据库理论的背景，又没有时间阅读MySQL手册全文。<i></i> </p><p>因此，我们决定研究某些方法，你可以用针对优化性能来调节MySQL。在读完本文后，你将理解一些帮助你设计你的MySQL数据库和查询的技术，值得你的应用很有效率。我们将假定你熟悉MySQL和SQL基础，但不假定你有这两方面的广博知识。</p><p>只存储你需要的信息</p><p>这听上去是常识，但人们常常采取“厨房下水道”的方式进行数据库设计。他们认为可能项要得每样东西都要存储并设计数据库保存所有者这些数据。你需要对你的需求现实些，并确定取确实需要什么信息。你常常能随意产生一些数据而不把它存在数据库表中。在这种情况下，从一个应用开发者的角度看也有道理这样做。</p><p>例如，在线目录的产品表可能包含各种产品的名称、介绍、尺寸、重量和价格。除了价格，你可能想存储每个项目相关的税和运输成本。但实际上不必这样做。首先税和运输成本可以方便地（由你的应用或MySQL）计算出来。其次，如果税和运输成本改变了，你可能必须编写必要的查询更新每个产品记录中的税和运输的费率。</p><p>有时人们认为这太难不能在以后往数据库表中加入字段，所以他们感觉不得不定义尽可能多的列。这是明显的概念错误。在MySQL中，你可以用ALTER<i></i> TABLE命令方便地修改表定义以适应你改变的需求。</p><p>例如，如果你突然认识到你需要给你的产品表增加一个级别列（可能你想允许用户在你的目录中给产品评级），你可以这样做：</p><p>ALTER<i></i> TABLE<i></i> products<i></i> ADD<i></i> rank<i></i> INTEGER<i></i> <i></i> <i></i> </p><p>这给你的产品表增加了一个整数类型的级别列，你能用ALTER<i></i> TABLE做什么的完整介绍参见MySQL手册。</p><p>只要求你需要的东西--要清晰</p><p>就像说“只存储你需要的东西”那样，这可能看来是常识，但这一点常常被忽视，为什么呢？因为在一个应用开发时，需求经常改变，所以很多查询最终看来是这样：</p><p>SELECT<i></i> *<i></i> FROM<i></i> sometable<i></i> <i></i> <i></i> </p><p>当你不能肯定你将需要哪一列时，要求所有列明显是最省力的事情，然而随着你的表不断增大和修改，这可能变成一个性能问题。最好是在你的最初开发完成后再花些时间并确定你真正从你的查询中需要什么：</p><p>SELECT<i></i> name,<i></i> rank,<i></i> description<i></i> FROM<i></i> products<i></i> <br />　<i></i> </p><p>这带来了一个相关的观点，即代码维护比性能更重要。大多数变成语言（Perl、Python、PHP、Java等）允许通过字段名和数字编号访问一条查询的结果，这意味着你可以访问命名字段或字段０都可以得到相同的数据。</p><p>长期看，最好使用列名而不是其编号位置，为什么？因为一个表中或一条查询中地列的相对位置可以改变。它们在表中可能因为重复使用ALTER<i></i> TABLE而改变，它们在查询中将因重写了查询而忘记更新应用逻辑来匹配而改变。</p><p>当然，你仍然需要小心改变列名！但如果你使用列名而非标号位置，如列名改变，你可以用grep搜索源代码或使用编辑器的搜索能力查找你需要修改的代码。</p><p>规范化你的表结构</p><p>如果你以前从未听说过“数据规范化”，不要害怕。规范化可能是一个复杂的专题，你可以从只理解最基本的规范化概念中正真正获益。</p><p>理解它的最容易的方法是认为你的表是一个电子报表。如果你想以一个报表跟踪你的CD收藏，你可以如图１种那样进行设计：</p><p>图１</p><p>album<i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> track1<i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> track2<i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> track10<br />-----<i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> ------<i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> ------<i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> -------<br />Billboard<i></i> Top<i></i> Hits<i></i> -<i></i> 1984<i></i> <i></i> Loverboy<i></i> <i></i> <i></i> <i></i> <i></i> <i></i> Shout<i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> St.<i></i> Elmo's<i></i> Fire<br /><i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> (Billy<i></i> Ocean)<i></i> (Tears<i></i> for<i></i> Fears)<i></i> (John<i></i> Parr)</p><p><i></i> </p><p>这看上去很合理。大多数CD只有10首曲子，对否？不尽然。如果你拥有一张有100首曲子的CD且几张超过20首改怎么办。这意味着用这种方法，在极端的情况下，你将需要一个非常宽的表格（或一个超过100个字段的表）来保存所有的数据。</p><p>规范化表结构的目标是使“空单元”的数量最少，在上述CD表的情况下，如果你允许CD可能包含100首曲子，你会有很多这样的空单元。不管你何时处理可能扩展到类似该CD表那样数量的字段列表，它是你需要将你的数据分割成2个或更多表的标志，然后你一起访问并获得你需要的数据。</p><p>很多关系数据库的新手不真正知道关系数据库管理系统中关系是什么。简单地说，就像一组信息存在可以基于共性数据联结（JOIN）在一起的不同表中，很不幸，这听上去更学术化和含糊，但CD数据库提出了一个具体情况，我们可以研究如何规范数据。</p><p>每个CD列表有一个固定的属性（标题、艺术家、年份、分类）集和一个不定的属性（曲目表）集的理解给了我们一些如何分成成能相互关联的表的思路。</p><p>你可以创建一个所有专辑及其固定属性的表，另一个包含这些专辑的所有曲目的表。这样不是水平思考（像表格），你垂直思考--就好像你创建列表而不是行--并建立一个如图2的表结构：<br /><img height="197" alt="r_2.jpg" src="http://www.cppblog.com/images/cppblog_com/ispfcn/1308/r_2.jpg" width="640" border="0" /><br /><font face="宋体" size="2">专辑的编号（MySQL镜自动为你生成，因为我们在列上使用了AUTO_INCREMENT属性）关联不同曲目到一给定专辑，tracks表中的album_id字段匹配专辑表中的一个id。这样要获得给定专辑的所有曲目，你应该用如下查询：</font></p><p>　SELECT<i></i> tracks.num,<i></i> tracks.name<br /><i></i> <i></i> <i></i> FROM<i></i> albums,<i></i> tracks<br /><i></i> <i></i> <i></i> WHERE<i></i> albums.title<i></i> =<i></i> 'Billboard<i></i> Top<i></i> Hits<i></i> -<i></i> 1984'<br /><i></i> <i></i> <i></i> AND<i></i> albums.id<i></i> =<i></i> tracks.album_id<br />　<i></i> </p><p>该结构即灵活又有效。灵活性来自你可以在以后将数据加入系统而不必重新你已完整的工作的事实。例如，如果你想增加每一张专辑的艺术家信息，你可以床架一个artists表，关联到albums表，就像tracks那样。你无需修改现有的结构--只是增加它。</p><p>有效性来自于在你的数据中没有明显的数据重复且没有大量的空洞（空单元）的实施。这样MySQL在你的数据库表中既不存储多余的数据，也不比花额外的精力搜索大量空区域。</p><p>如果你对关系数据库是新手，规范化你的数据看起来有点奇怪，但在存储和检索数据时，它使MySQL非常有效，并给予你扩展和伸缩你的应用却不必多次重构你的数据库的灵活性。尽可能早的花时间想清楚数据库设计，并考虑你的需求怎样随时间增长，前期花的时间永远是值得的。</p><p>复合索引</p><p>复合索引（有时称组合索引）是急于多个列的单一索引。MySQL在处理一条查询时每个表只使用一个索引，这意味着如果你有多个经常出现在WHERE子句中的列，你可能要通过创建一个复合索引来加快这些查询。</p><p>考虑下列表结构片断：</p><p>　CREATE<i></i> TABLE<i></i> people<i></i> (<br /><i></i> <i></i> <i></i> last_name<i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> VARCHAR(50)<i></i> NOT<i></i> NULL,<br /><i></i> <i></i> <i></i> first_name<i></i> <i></i> <i></i> <i></i> <i></i> <i></i> VARCHAR(50)<i></i> NOT<i></i> NULL,<br /><i></i> <i></i> <i></i> favorite_color<i></i> <i></i> VARCHAR(10)<i></i> NOT<i></i> NULL,<br /><i></i> <i></i> <i></i> .<br /><i></i> <i></i> <i></i> .<br /><i></i> <i></i> <i></i> .<br />);</p><p>　<i></i> </p><p>如果你常常基于last_name和first_name查询表，你可以从last_name和first_name的复合索引中获益：</p><p>INDEX<i></i> last_first<i></i> (last_name,<i></i> first_name)<i></i> </p><p>由于MySQL构建复合索引的方式，它可以使用last_first索引来回答基于last_name本身或last_name与first_name两者的索引。这是因为如果列涉及复合索引的“最左前缀”的形式，MySQL将只使用一个复合索引。</p><p>所以如果一个复合索引有多个列合成：</p><p>INDEX<i></i> big_index<i></i> (a,<i></i> b,<i></i> c,<i></i> d,<i></i> e,<i></i> f,<i></i> g,<i></i> h,<i></i> i)<i></i> </p><p>MySQL可以用它来回答基于a、或a和b、或a和b和c、或a和b和c和d的查询。但它不能使用big_index处理基于e、或c和f、或g和i的查询，因为这些序列没有一个是从索引的最左边开始的。</p><p>复合索引尝被用于加快某些复杂查询，但你需要理解起局限，而且你永远应该进行一些测试，而不是简单地假设这样一个索引将会有帮助。</p><p><br /><i></i> <br />　<i></i> <br />使用索引加快查询</p><p>当MySQL试图回达一条查询时，它查看有关你的数据的各种统计，并决定如何以最快的速度找出你想要的数据。对于前小节的查询，MySQL将读取albums表的所有titles并把它们与“Billboard<i></i> Top<i></i> Hits<i></i> --1984”进行比较看是否匹配。它一旦找到一个匹配还不能停止，因为有相同曲目的专辑不止一个（如你可以有12张CD标有“Greatest<i></i> Hits”），结果MySQL必须读取表中的每一行。这常称为“全表扫描”且可以避免。</p><p>你应该避免全表扫描，因为：</p><p>CPU开销：如果你没有很多专辑，检查所有这些标题的处理相对快些。但如果你需要在你的数据库中存储很多专辑呢？你有的专辑越多，花的时间越长。在专辑数量或检查它们所花的时间时间存在一种线性关系。<i></i> <br />并发性：在MySQL正在从表中读取数据时，它锁定表使得没有其他人可以写入，但可以读取。当MySQL更新或删除表中的行时，它锁定表使得没有其他人可以从它读取。<i></i> <br />磁盘开销：在一个大数据表上，一次全表扫描将消耗大量磁盘I/O。这可能明显地减慢你的数据库服务器<i></i> --<i></i> 特别是如果你的服务器是较慢的IDE驱动器。<i></i> <br />最好是让全表扫描将到最少<i></i> --　特别是你的应用需要以规模或用户数伸缩。MySQL最新版确实有几个并发性方面的改善（BDB、InnoDB和Gemini表类型）。</p><p>在这里索引可以帮助你，简单地放一个，一个索引允许MySQL很快地确定任何给定值如“Billboard<i></i> Top<i></i> Hits<i></i> --<i></i> 1984”是否将匹配表中的任何行。</p><p>怎样做到的呢？当你告诉MySQL索引一个特定列时，它在幕后创建另一个数据结构（索引）并用它存储关于被索引列中的值的某些额外信息（被索引的值常称为健码）。这是一种简化，MySQL将所有键码存储在一个树状数据结构中。该数据结构允许MySQL非常快速地找到特定键码。</p><p>当MySQL发现列上有一个索引，它将使用索引而不是执行一个全表扫描。这节省了CPU时间（不必读取所有可能的值）和磁盘I/O，而且它改善了并发性，因为MySQL只锁定表足够长的时间来获得所需的行（基于它在索引中找什么）。当你在表中有大量的数据，最终的改善可能非常明显。</p><p>对图3的albums表的CREATE<i></i> TABLE语句的改进：</p><p>图3</p><p>CREATE<i></i> TABLE<i></i> albums<i></i> (<br /><i></i> <i></i> <i></i> <i></i> id<i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> <i></i> INTEGER<i></i> <i></i> <i></i> <i></i> <i></i> <i></i> NOT<i></i> NULL<i></i> AUTO_INCREMENT<i></i> PRIMARY<i></i> KEY,<br /><i></i> <i></i> <i></i> <i></i> title<i></i> <i></i> <i></i> <i></i> <i></i> VARCHAR(80)NOT<i></i> NULL,<br /><i></i> <i></i> <i></i> <i></i> <br /><i></i> <i></i> <i></i> <i></i> INDEX<i></i> title_idx<i></i> (title)<br />);</p><p><i></i> </p><p>正如你所见的，语句只是简单地在定义后增加了一个INDEX行告诉MySQL在albums表中的title列上创建名为title_idx的索引。你可以给一个表增加多个索引，就像你可在表中有多个列一样。单个索引也可以有多个列合成。</p><p>要给现有的表加上一个索引而不是重建表，你可以用ALTER<i></i> TABLE命令：</p><p>ALTER<i></i> TABLE<i></i> albums<i></i> ADD<i></i> INDEX<i></i> title_idx<i></i> (title)<i></i> <i></i> </p><p>查询处理</p><p>如果你的查询复杂，MySQL用于精确确定如何获取数据的原则可能变得难于理解。幸运的是，有几个一般原则和一条命令允许你获得正在做什么的更好的理解。首先，原则是：</p><p>如果MySQL确定了简单地扫描全表更快些，则它L将不使用索引。一般地，如果一个索引告诉MySQL访问表中大概30%的行，它放弃索引并简单地执行全表扫描。<i></i> <br />如果多索引可以用来满足查询，MySQL将使用最严格的一个<i></i> --<i></i> 即导致最少的行被提取的那个。<i></i> <br />如果你正在选择的列是一个索引的所有部分，MySQL可以直接从索引中读取锁需的数据，绝不接触（或锁定）表本身。<i></i> <br />当联结几个表时，MySQL将首先从可能返回最少行的表中读取数据。你指定表的次序可能与MySQL使用它们的次序不同，这也影响到最终返回给你的行的次序，所以如果你需要行以特定的次序出现，要保证在你的查询中使用一个ORDER子句。<i></i> <br />已经说了很多了，重要的是认识到MySQL所做的一些决策实际上是基于猜测，就像人类进行大量猜测一样，偶尔也会出错。<i></i> </p><p>如果你怀疑已经发生或只是想理解MySQL怎样处理一条查询，你可以使用EXPLAIN命令。简单地在你的查询前面加上EXPLAIN这个字，并要求MySQL执行它，MySQL不执行查询，相反将报告有助于查询的候选索引列表和所知道的有关它们的一切。</p><p>EXPLAIN输出的完整讨论参见MySQL参考手册。<br /><i></i> </p><p><br />不要过分使用索引</p><p>已经知道索引使查询更快，你可能倾向于索引你表中的每个列。但是得益于索引的性能提高是有代价的，在表中每次执行INSERT、UPDATE、REPLACE或DELETE，MySQL不得不更新表上的每个索引以反映变化。</p><p>那么你如何确定何时食用它们呢？最常见的答案是“看情况”。它依赖你运行的查询类型和你运行它们的频度，它依赖于你的数据，它依赖于你的期望和需求。你得到了答案<i></i> --<i></i> 它依赖于很多事情。</p><p>在列上有索引的理由是MySQL缩窄其搜索范围以便尽可能会的匹配行（且避免全表扫描）。你可以认为索引是对列中的每个唯一值只包含一项。在索引中，MySQL必须考虑任何重复值，这些重复值稍微降低效率和索引的用途。</p><p>所以在索引一个列之前，考虑数据重复的百分比，如果该百分比太高，你可能觉察不到用索引带来的任何性能改善。</p><p>要以更简明的术语描述，它清楚地知道在albums表中索引曲目字段，因为有可能有大量不同的值，而且重复非常少。但如果在albums表中有一个分类列，索引它则可能价值不大，一般的CD收集包含多少不同的类型呢？将会有很多重复的类型值。</p><p>另一件要考虑的事情是你的查询可能使用的频度。MySQL只能对出现在一条查询种的WHERE子句中的特定列使用索引，试图回答查询：</p><p>SELECT<i></i> *<i></i> FROM<i></i> albums<i></i> WHERE<i></i> id<i></i> =<i></i> 500<i></i> <i></i> <i></i> </p><p>MySQL不能使用在title上的查询，该查询要求MySQL基于其id查找记录而不是其title。<i></i> </p><p>如果你很少使用查询中WHERE子句中的一个列，它可能不值得索引该列。可能在极少的情况下容人全表扫描比要求MySQL在每次修改时保持索引更新总体上更有效些。.</p><p>有疑问时，进行测试。你总能运行某些到索引或不带索引的基准测试看哪一个更快，只要试图让你的基准测试逼真些。如果你的查询有20%是UPDATE，80%是SLEECT，肯定你的基准测试能发映出来，详见MySQL参考手册。</p><p>使用REPLACE查询</p><p>有可能你想往表中插入一条记录，除非它已经存在。如果记录已经存在，你想UPDATE它。不是重写代码中做这件事的逻辑，并需运行多个查询，而是MySQL使用REPLACE来做此项工作。</p><p>如果id是6的专辑假定有曲目“Shaking<i></i> the<i></i> Tree”，你可以这样写查询：</p><p>REPLACE<i></i> INTO<i></i> albums<i></i> valueS<i></i> (6,<i></i> 'Shaking<i></i> the<i></i> Tree')<i></i> <i></i> <i></i> </p><p>重要的是理解REPLACE如何确定一条记录是否在表中存在。MySQL将在表上使用PRIMARY<i></i> KEY或UNIQUE<i></i> KEY来执行检查，如果都不存在，REPLACE效果上变成了INSERT。</p><p>使用临时表</p><p>当工作在非常大的表上时，你可能偶尔需要运行很多查询获得一个大量数据的小的子集，不是对整个表运行这些查询，而是让MySQL每次找出所需的少数记录，将记录选择到一个临时表可能更快些，然后多这些表运行查询。</p><p>创建临时表很容易，给正常的CREATE<i></i> TABLE语句加上TEMPORARY关键字：</p><p>CREATE<i></i> TEMPORARY<i></i> TABLE<i></i> tmp_table<i></i> (<br /><i></i> <i></i> <i></i> name<i></i> <i></i> <i></i> <i></i> VARCHAR(10)<i></i> NOT<i></i> NULL,<br /><i></i> <i></i> <i></i> value<i></i> <i></i> <i></i> INTEGER<i></i> <i></i> <i></i> <i></i> <i></i> NOT<i></i> NULL<br />)</p><p>临时表将在你连接MySQL期间存在。当你断开时，MySQL将自动删除表并释放所用的空间。当然你可以在仍然连接的时候删除表并释放空间。</p><p>DROP<i></i> TABLE<i></i> tmp_table<i></i> <i></i> <i></i> </p><p>如果在你创建名为tmp_table临时表时名为tmp_table的表在数据库中已经存在，临时表将有必要屏蔽（隐藏）非临时表tmp_table。</p><p>如果你声明临时表是一个HEAP表，MySQL也允许你指定在内存中创建它：</p><p>　CREATE<i></i> TEMPORARY<i></i> TABLE<i></i> tmp_table<i></i> (<br /><i></i> <i></i> <i></i> name<i></i> <i></i> <i></i> <i></i> VARCHAR(10)<i></i> NOT<i></i> NULL,<br /><i></i> <i></i> <i></i> value<i></i> <i></i> <i></i> INTEGER<i></i> <i></i> <i></i> <i></i> <i></i> NOT<i></i> NULL<br />)<i></i> TYPE<i></i> =<i></i> HEAP<br />　<i></i> </p><p>因为HEAP表存储在内存中，你对它运行的查询可能比磁盘上的临时表快些。然而，HEAP表与一般的表有些不同，且有自身的限制。详见MySQL参考手册。</p><p>正如前面的建议，你应该测试临时表看看它们是否真的比对大量数据库运行查询快。如果数据很好地索引，临时表可能一点不快。</p><p>临时表在MySQL<i></i> 3.23.0和更新版才有。</p><p>只用最新版的MySQL</p><p>2001年一月中旬，MySQL<i></i> 3.23宣布稳定。除了后很多新功能外，它也比3.22系列更快和更具伸缩性。</p><p>MySQL的更新版不断推出。如果你控制着你的MySQL服务器，最好是尝试保持版本相对最新。除了有最新功能和错误修正，你常常会看到较新的MySQL发行有明显的性能提高。</p><p>其他资源</p><p>除了阅读MySQL手册，你也可以咨询：</p><p>你的DBA：如果你在一个共享服务器上使用MySQL，某个人被指定为数据库管理员（DBA），这是一个好机会。如果你的DBA非常熟悉MySQL，它可能可以在分析和优化你的表结构和查询上帮你一下。<i></i> <br />MySQL用户邮件列表：有非常活跃的邮件列表，在其中MySQL用户经常彼此寻求帮助。新手和老手愿意分享其知识并彼此帮助解决共同的问题。实际上，有些MySQL开发团队成员很好地监视着邮件列表。<i></i> <i></i> <br />MySQL书籍：不要与MySQL参考手册混淆，Paul<i></i> DuBois写了一本极好的书名为《MySQL》的书（有中文译本）。 </p><img src ="http://www.cppblog.com/ispfcn/aggbug/4992.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ispfcn/" target="_blank">编程之道</a> 2006-04-04 14:10 <a href="http://www.cppblog.com/ispfcn/archive/2006/04/04/4992.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>