<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://jackxiang.com/post//</link>
<title><![CDATA[[Mysql相关]The MySQL C API 编程实例 ]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[WEB2.0]]></category>
<pubDate>Sat, 18 Aug 2007 03:48:52 +0000</pubDate> 
<guid>http://jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	在网上找了一些MYSQL C API编程的文章，看了后觉得还是写的不够充分，根据自己经验写了这篇《The MySQL C API 编程实例》，希望对需要调用到MYSQL的C的API的朋友有所帮助，附例中的环境为RedHat<br/><br/> &nbsp; &nbsp;在这篇文章里，我们将学会怎么使用MySQL 的C APIs(Application Programming Interfaces 编程接口)。为了很好地了解这篇文章，您需要具备以下前提知识:<br/>C语言变量<br/>C语言函数<br/>C语言指针<br/>简介<br/><br/>C APIs包含在mysqlclient库文件当中与MySQL的源代码一块发行，用于连接到数据库和执行数据库查询。有一些例子在MySQL原代码的clients目录里。<br/><br/> <br/>MySQL C 变量类型<br/><br/>以下变量类型在MySQL的库当中定义。我们需要这些变量是为了使用MySQL的函数。这些变量有详细的解释，但是这些解释对于写代码来说并不重要。<br/>MYSQL<br/><br/> &nbsp; &nbsp;以下代码块是用来连接数据库的通讯过程，要连接MYSQL，必须建立MYSQL实例，通过mysql_init初始化方能开始进行连接，这个在后面会讲到。typedef struct st_mysql {<br/> &nbsp;NET &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; net; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/* Communication parameters */<br/> &nbsp;gptr &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;connector_fd; &nbsp; /* ConnectorFd for SSL */<br/> &nbsp;char &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*host,*user,*passwd,*unix_socket,<br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*server_version,*host_info,*info,*db;<br/> &nbsp;unsigned int &nbsp;port,client_flag,server_capabilities;<br/> &nbsp;unsigned int &nbsp;protocol_version;<br/> &nbsp;unsigned int &nbsp;field_count;<br/> &nbsp;unsigned int &nbsp;server_status;<br/> &nbsp;unsigned long thread_id; &nbsp; &nbsp; &nbsp;/* Id for connection in server */<br/> &nbsp;my_ulonglong affected_rows;<br/> &nbsp;my_ulonglong insert_id; &nbsp; &nbsp; &nbsp; /* id if insert on table with NEXTNR */<br/> &nbsp;my_ulonglong extra_info; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/* Used by mysqlshow */<br/> &nbsp;unsigned long packet_length;<br/> &nbsp;enum mysql_status status;<br/> &nbsp;MYSQL_FIELD &nbsp; *fields;<br/> &nbsp;MEM_ROOT &nbsp; &nbsp; &nbsp;field_alloc;<br/> &nbsp;my_bool &nbsp; &nbsp; &nbsp; free_me; &nbsp; &nbsp; &nbsp; &nbsp;/* If free in mysql_close */<br/> &nbsp;my_bool &nbsp; &nbsp; &nbsp; reconnect; &nbsp; &nbsp; &nbsp;/* set to 1 if automatic reconnect */<br/> &nbsp;struct st_mysql_options options;<br/> &nbsp;char &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;scramble_buff[9];<br/> &nbsp;struct charset_info_st *charset;<br/> &nbsp;unsigned int &nbsp;server_language;<br/>} MYSQL;<br/><br/><br/> <br/>MYSQL_RES<br/><br/> &nbsp; &nbsp;这个结构代表返回行的一个查询的(SELECT, SHOW, DESCRIBE, EXPLAIN)的结果。返回的数据称为“数据集”，用过数据库的朋友应该对数据库中查询后得到的结果集不会陌生，在C的API里对应的就是MYSQL_RES了，从数据库读取数据，最后就是从MYSQL_RES中读取数据。typedef struct st_mysql_res {<br/> &nbsp;my_ulonglong row_count;<br/> &nbsp;unsigned int &nbsp;field_count, current_field;<br/> &nbsp;MYSQL_FIELD &nbsp; *fields;<br/> &nbsp;MYSQL_DATA &nbsp; &nbsp;*data;<br/> &nbsp;MYSQL_ROWS &nbsp; &nbsp;*data_cursor;<br/> &nbsp;MEM_ROOT &nbsp; &nbsp; &nbsp;field_alloc;<br/> &nbsp;MYSQL_ROW &nbsp; &nbsp; row; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/* If unbuffered read */<br/> &nbsp;MYSQL_ROW &nbsp; &nbsp; current_row; &nbsp; &nbsp;/* buffer to current row */<br/> &nbsp;unsigned long *lengths; &nbsp; &nbsp; &nbsp; /* column lengths of current row */<br/> &nbsp;MYSQL &nbsp; &nbsp; &nbsp; &nbsp; *handle; &nbsp; &nbsp; &nbsp; &nbsp;/* for unbuffered reads */<br/> &nbsp;my_bool &nbsp; &nbsp; &nbsp; eof; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/* Used my mysql_fetch_row */<br/>} MYSQL_RES;<br/><br/><br/> <br/>MYSQL_ROW<br/><br/>这是一个行数据的类型安全(type-safe)的表示。当前它实现为一个计数字节的字符串数组。（如果字段值可能包含二进制数据，你不能将这些视为空终止串，因为这样的值可以在内部包含空字节) 行通过调用mysql_fetch_row()获得。typedef char **MYSQL_ROW;<br/><br/>MYSQL_FIELD<br/><br/>这个结构包含字段信息，例如字段名、类型和大小。其成员在下面更详细地描述。你可以通过重复调用mysql_fetch_field()对每一列获得MYSQL_FIELD结构。字段值不是这个结构的部分；他们被包含在一个MYSQL_ROW结构中。<br/><br/> typedef struct st_mysql_field {<br/> &nbsp;char *name; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* Name of column */<br/> &nbsp;char *table; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/* Table of column if column was a field */<br/> &nbsp;char *def; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/* Default value (set by mysql_list_fields) */<br/> &nbsp;enum enum_field_types type; &nbsp; /* Type of field. Se mysql_com.h for types */<br/> &nbsp;unsigned int length; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/* Width of column */<br/> &nbsp;unsigned int max_length; &nbsp; &nbsp; &nbsp;/* Max width of selected set */<br/> &nbsp;unsigned int flags; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* Div flags */<br/> &nbsp;unsigned int decimals; &nbsp; &nbsp; &nbsp; &nbsp;/* Number of decimals in field */<br/>} MYSQL_FIELD;<br/><br/>my_ulonglong<br/>typedef unsigned long my_ulonglong;<br/><br/><br/>该类型用于行编号和mysql_affected_rows()、mysql_num_rows()和mysql_insert_id()。这种类型提供0到1.84e19的一个范围。在一些系统上，试图打印类型my_ulonglong的值将不工作。为了打印出这样的值，将它变换到unsigned long并且使用一个%lu打印格式。例如：<br/>printf (Number of rows: %lu&#92;n&quot;, (unsigned long) mysql_num_rows(result));<br/><br/>连接MySQL，查询数据<br/><br/>现在假设MySQL已安装, 用户和数据表在数据库被创造。以防有什么不明问题的情况, 请参考www.mysql.com 网站。<br/><br/>前面已经说过，MySQL的库文件在mysqlclient。因此在编译MySQL程序的时候有必要加上-lmysqlclient编译选项。MySQL的头文件在/usr/include/mysql目录下(根据Linux的发行版本的不同，这个目录也有所不同)，因此你的程序头部看起来有点这个样子： #include &lt;mysql.h&gt;<br/><br/><br/> <br/><br/>MySQL的变量类型和函数都包含在这个头文件当中<br/><br/>然后，我们需要创建连接数据库的变量，可以简单地这么做：MYSQL mysql;<br/><br/><br/>在连接数据库之前，我们要调用以下函数初始化这个变量：mysql_init(&amp;mysql);<br/><br/><br/>然后，调用mysql_real_connect函数：MYSQL * &nbsp; &nbsp; &nbsp; &nbsp; STDCALL mysql_real_connect(MYSQL *mysql, const char *host,<br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const char *user,<br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const char *passwd,<br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const char *db,<br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; unsigned int port,<br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const char *unix_socket,<br/> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; unsigned int clientflag);<br/><br/> <br/><br/> &nbsp; &nbsp;该函数被调用连接到数据库。host是MySQL服务器的主机名，user是登录的用户名，passwd是登录密码，db是要连接的数据库，port是MySQL服务器的TCP/IP端口，unix_socket是连接类型，clientflag是MySQL运行成ODBC数据库的标记。在这篇文章当中该标记设成0，连接寻建立后，这个函数返回0。<br/><br/>现在可以连接数据库，进行查询了：char *query;<br/><br/><br/> <br/><br/>使用这个字符串我们可以创立任何SQL查询语句进行查询。执行这个查询的函数是：int STDCALL mysql_real_query(MYSQL *mysql, const char *q, unsigned int length);<br/><br/><br/> <br/><br/>mysql是我们前面用过的变量，q是SQL查询语句，length是这个查询语句的长度。如果查询成功，函数返回0。<br/><br/>查询之后，我们要到一个MYSQL_RES变量来使用查询的结果。以下这行创立这个变量：MYSQL_RES *res;<br/><br/><br/> <br/><br/>然后<br/><br/> res = mysql_store_result(&amp;mysql);<br/><br/> <br/><br/> &nbsp; &nbsp;对客户端而言，有两种方法处理结果集合。一种方法是通过调用mysql_store_result()立刻检索全部结果。该函数从服务器获得查询返回的所有行，并将他们存储在客户端。第二种方法是对客户通过调用mysql_use_result()初始化一个一行一行地结果集合的检索。该函数初始化检索，但是实际上不从服务器获得任何行。<br/><br/>在两种情况中，你通过mysql_fetch_row()存取行。用mysql_store_result()、mysql_fetch_row()储存取已经从服务器被取出的行。用mysql_use_result()、mysql_fetch_row()实际上从服务器检索行。调用mysql_fetch_lengths()可获得关于每行中数据值尺寸的信息。<br/><br/><br/> &nbsp; &nbsp;在你用完一个结果集合以后，调用mysql_free_result()释放由它使用的内存。<br/><br/>两种检索机制是互补的。客户程序应该选择最适合他们的要求的途径。在实践中，客户通常更愿意使用mysql_store_result()。<br/><br/>该函数读出查询结果。<br/><br/>尽管可以很容易地查询了，要用这个查询的结果还要用到其它的函数。第一个是：<br/><br/> MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *result);<br/><br/><br/> <br/><br/>该函数把结果转换成“数组”。你可能注意到了，该函数返回的是MYSQL_ROW变量类型。以下语句创立那样的变量：<br/><br/> MYSQL_ROW row = mysql_fetch_row(res)<br/><br/> <br/><br/> &nbsp; &nbsp;如前所解释的，变量row是一个字符串数组。也就是说，row[0]是数组的第一个值，row[1]是数组的第二个值...当我们用mysql_fetch_row的时候，接着变量row会取得结果的下一组的数据。当到了结果的尾部，该函数返回一负值。<br/><br/>使用数据集结束后，记得释放数据集，否则会发生内存泄漏，释放数据集函数如下：void mysql_free_result(MYSQL_RES *result)<br/><br/><br/> <br/><br/>释放由mysql_store_result()、mysql_use_result()、mysql_list_dbs()等为一个结果集合分配的内存。当你用完了一个结果集合时，你必须调用mysql_free_result()来释放它使用的内存。<br/><br/>最后我们要关闭这个连接：mysql_close(&amp;mysql);<br/><br/> <br/>例子程序<br/><br/>执行一个select操作，从数据库中取数据，并执行一个insert操作，往数据库中插入数据，根据这两个操作你可以自由的扩展为任意数据库操作，<br/>准备条件<br/><br/>1、已经安装mysql，上有数据库test，如果没有执行Create Databse test<br/><br/><br/>建立数据库<br/><br/>2、test数据库上有表t1，如果没有，执行CREATE TABLE `t1` (<br/> &nbsp;`id` int(11) default NULL,<br/> &nbsp;`name` varchar(100) default NULL<br/>)<br/><br/><br/>建立表t1<br/>testsql.c：<br/>/* testsql.c<br/> &nbsp;** An example to use MYSQL C API<br/> &nbsp;** Copyright 2004 Coon Xu.<br/> &nbsp;** Author: Coon Xu<br/> &nbsp;** Date: 05 Nov 2004<br/> &nbsp;*/<br/> &nbsp;<br/> &nbsp;#include &lt;mysql.h&gt;<br/> &nbsp;#include &lt;stdio.h&gt;<br/>int main(){<br/> &nbsp; MYSQL mysql; &nbsp; &nbsp; // need a instance to init<br/> &nbsp; MYSQL_RES *res;<br/> &nbsp; MYSQL_ROW row;<br/> &nbsp; char *query;<br/> &nbsp; int t,r;<br/> // connect the database<br/> &nbsp; mysql_init(&amp;mysql);<br/> &nbsp; if (!mysql_real_connect(&amp;mysql,&quot;localhost&quot;, &quot;mmim&quot;, &quot;mmim&quot;, &quot;test&quot;,0,NULL,0))<br/> &nbsp; {<br/> &nbsp; &nbsp; &nbsp; printf( &quot;Error connecting to database: %s&#92;n&quot;,mysql_error(&amp;mysql));<br/> &nbsp; }<br/> &nbsp; else printf(&quot;Connected...&#92;n&quot;);<br/><br/> // get the result from the executing select query<br/> query = &quot;select * from t1&quot;;<br/> &nbsp;<br/> t = mysql_real_query(&amp;mysql,query,(unsigned int) strlen(query));<br/> if (t)<br/> {<br/> &nbsp; &nbsp;printf(&quot;Error making query: %s&#92;n&quot;,<br/> &nbsp; &nbsp; &nbsp;mysql_error(&amp;mysql));<br/> }<br/> else printf(&quot;[%s] made...&#92;n&quot;, query);<br/> res = mysql_store_result(&amp;mysql);<br/> while(row = mysql_fetch_row(res))<br/> {<br/> &nbsp;for(t=0;t&lt;mysql_num_fields(res);t++)<br/> &nbsp;{<br/> &nbsp; printf(&quot;%s &quot;,row[t]);<br/> &nbsp;}<br/> &nbsp;printf(&quot;&#92;n&quot;);<br/> }<br/> <br/> printf(&quot;mysql_free_result...&#92;n&quot;);<br/> mysql_free_result(res); &nbsp; &nbsp; //free result after you get the result<br/> <br/> sleep(1); &nbsp; <br/> <br/> // execute the insert query<br/> query = &quot;insert into t1(id, name) values(3, &#039;kunp&#039;)&quot;;<br/> t = mysql_real_query(&amp;mysql,query,(unsigned int) strlen(query));<br/> if (t)<br/> {<br/> &nbsp; &nbsp;printf(&quot;Error making query: %s&#92;n&quot;,<br/> &nbsp; &nbsp; &nbsp;mysql_error(&amp;mysql));<br/> }<br/> else printf(&quot;[%s] made...&#92;n&quot;, query);<br/> &nbsp;<br/> &nbsp; &nbsp;mysql_close(&amp;mysql);<br/> &nbsp;<br/> &nbsp; return 0;<br/>}<br/><br/>编译<br/><br/>假定mysql的头文件在/usr/include/mysql，库文件在/usr/lib/mysql，执行下列命令进行编译：<br/>gcc testsql.c -I/usr/include/mysql -L/usr/lib/mysql -lmysqlclient<br/>
]]>
</description>
</item><item>
<link>http://jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] [Mysql相关]The MySQL C API 编程实例 ]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>