Mysql C API编程指南

原创 2012年03月28日 09:46:02

MYSQL C API 入门教程

(一)关于本教程

这是一本关于MYQL的C语言编程的入门教程,它讲述了MYSQL的C API编程的基本知识。

(二)关于MYSQL数据库

MYSQL是一个领先的开源数据管理系统,是一个多用户、多线程的数据库系统。MYSQL在web应用中特别流行,是非常流行的LAMP(L-linux, A-apache, M-mysql, P-php)平台中的一部分。MYSQL最早是由瑞典的MYSQL AB公司所开发, 这家公司以及Trolltech 是非常有名的开放源代码公司。MYSQL兼容大多数操作系统平台,包括BSD Unix、Linux、Windows以及MAC。维基百科和YouTube使用MYSQL,这些网站每天处理上百万的查询请求。MYSQL包括两个版本:MYSQL服务端版本和MYSQL嵌入式版本。

(三)第一个示例

第一个示例简单的测试MYSQL的API函数,代码如下:

#include <my_global.h>
#include <mysql.h>
int main(int argc, char **argv)
{
     printf("MySQL client version: %s\n", mysql_get_client_info());
     return 0;
}


API mysql_get_client_info获取mysql客户端的版本号,编译:

gcc version.c -o version  `mysql_config --cflags --libs

执行程序verion,得出如下输出结果:

 $ ./version

 MySQL client version: 5.0.38

代码详解:

 #include <my_global.h>

 #include <mysql.h>

首先,我们包含必要的头文件myql.h和my_global.h,mysql.h是MYSQL函数调用中要包含的最重要的头文件。my_global.h包含了一些全局函数的声明以及标准输入输出的头文件。

printf("MySQL client version: %s\n", mysql_get_client_info());

这些代码打印了Mysql客户端的版本号,通过使用mysql_get_client_info API调用。

(四)创建数据库

以下代码演示如何创建数据库:

#include <my_global.h>
#include <mysql.h>
int main(int argc, char **argv)
{
  MYSQL *conn;
  conn = mysql_init(NULL);
  if (conn == NULL) {
      printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn));
      exit(1);
  }
  if (mysql_real_connect(conn, "localhost", "zetcode", 
          "passwd", NULL, 0, NULL, 0) == NULL) {
      printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn));
      exit(1);
  }
  if (mysql_query(conn, "create database testdb")) {
      printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn));
      exit(1);
  }
  mysql_close(conn);
}


以上示例代码先连接到mysql数据库,然后创建一个testdb数据库。现在登录到数据库中验证一下:

mysql> show databases;

+--------------------+

| Database           |

+--------------------+

| information_schema |

| mysql              |

| testdb             |

+--------------------+

3 rows in set (0.00 sec)

经验证,数据库testdb确实已经创建好了。

在这个示例代码中,我们进行了错误检查,进行错误检查是非常重要的,因为数据库编程中有许多地方会出现错误。为了简明起见,后面的示例将忽略错误检查。

本示例代码可以划分为以下几个部分:

1.初始化一个链接结构。

2.创建一个链接。

3.执行查询。

4.关闭链接。

MYSQL* conn;

首先,声明一个conn指针指向一个MYSQL结构体,这个结构体就是一个数据库连接句柄。

conn = mysql_init(NULL);

函数mysql_init将返回一个链接句柄。

 if (conn == NULL) {

     printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn));

     exit(1);

 }

我们检查函数返回值,如果mysql_init函数执行失败,我们打印错误信息并且结束程序。

if (mysql_real_connect(conn, "localhost", "zetcode", 

         "passwd", NULL, 0, NULL, 0) == NULL) {

     printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn));

     exit(1);

 }

函数mysql_real_connect建立一个到mysql数据库的链接。调用这个函数要提供 链接句柄、主机名、用户、密码等参数,最后四个参数依次是数据库名、端口、unix套接字和客户端标志。

if (mysql_query(conn, "create database testdb")) {

     printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn));

     exit(1);

 }

mysql_close(conn);

函数mysql_query执行sql语句,在本示例中,将建立一个新的数据库。最后,我们关闭数据库链接。

(五)创建表并且插入数据

本示例将创建一个表并且插入一些数据,示例代码如下:

#include <my_global.h>
#include <mysql.h>
int main(int argc, char **argv)
{
  MYSQL *conn;
  conn = mysql_init(NULL);
  mysql_real_connect(conn, "localhost", "zetcode", "passwd", "testdb", 0, NULL, 0);
  mysql_query(conn, "CREATE TABLE writers(name VARCHAR(25))");
  mysql_query(conn, "INSERT INTO writers VALUES('Leo Tolstoy')");
  mysql_query(conn, "INSERT INTO writers VALUES('Jack London')");
  mysql_query(conn, "INSERT INTO writers VALUES('Honore de Balzac')");
  mysql_query(conn, "INSERT INTO writers VALUES('Lion Feuchtwanger')");
  mysql_query(conn, "INSERT INTO writers VALUES('Emile Zola')");
  mysql_close(conn);
}


在本示例代码中,我们没有使用任何新的mysql API,创建表和插入数据都是使用mysql_query函数。

1.建立链接

mysql_real_connect(conn, "localhost", "zetcode", "passwd", "testdb", 0, NULL, 0);

2.建立writers表,该表只有一列,类型为VARCHAR。

mysql_query(conn, "CREATE TABLE writers(name VARCHAR(25))");

3.插入数据

mysql_query(conn, "INSERT INTO writers VALUES('Leo Tolstoy')");

mysql_query(conn, "INSERT INTO writers VALUES('Jack London')");

mysql_query(conn, "INSERT INTO writers VALUES('Honore de Balzac')");

mysql_query(conn, "INSERT INTO writers VALUES('Lion Feuchtwanger')");

mysql_query(conn, "INSERT INTO writers VALUES('Emile Zola')");

4.验证数据

mysql> select * from writers;

+-------------------+

| name              |

+-------------------+

| Leo Tolstoy       |

| Jack London       |

| Honore de Balzac  |

| Lion Feuchtwanger |

| Emile Zola        |

+-------------------+

5 rows in set (0.00 sec)

5.关闭链接

mysql_close(conn);

(六)从数据库中查询数据

这一节,我们从表中查询数据,分为以下几步:

1.建立一个链接

2.执行查询

3.获取结果集

4.获取所有行

5.释放结果集

6.释放链接

本节示例代码如下:

#include <my_global.h>
#include <mysql.h>
int main(int argc, char **argv)
{
  MYSQL *conn;
  MYSQL_RES *result;
  MYSQL_ROW row;
  int num_fields;
  int i;
  conn = mysql_init(NULL);
  mysql_real_connect(conn, "localhost", "zetcode", "passwd", "testdb", 0, NULL, 0);
  mysql_query(conn, "SELECT * FROM writers");
  result = mysql_store_result(conn);
  num_fields = mysql_num_fields(result);
  while ((row = mysql_fetch_row(result)))
  {
      for(i = 0; i < num_fields; i++)
      {
          printf("%s ", row[i] ? row[i] : "NULL");
      }
      printf("\n");
  }
  mysql_free_result(result);
  mysql_close(conn);
}


1.执行查询,并取回writers表中的所有数据:

mysql_query(conn, "SELECT * FROM writers");

2.获取结果集

result = mysql_store_result(conn);

3.获取writers表中的所有字段

num_fields = mysql_num_fields(result);

4.获取每行数据,并且输出到屏幕上

 while ((row = mysql_fetch_row(result)))

  {

      for(i = 0; i < num_fields; i++)

      {

          printf("%s ", row[i] ? row[i] : "NULL");

      }

      printf("\n");

  }

5.释放结果集

 mysql_free_result(result);

6.关闭链接

 mysql_close(conn);

(七)列头

在本节中,将演示查询数据并获取表中每一列的名字。

 首先,我们建立一个新的表,并插入些数据:

 mysql> create table friends (id int not null primary key auto_increment,

                               name varchar(20), age int);

 mysql> insert into friends(name, age) values('Tom', 25);

 mysql> insert into friends(name, age) values('Elisabeth', 32);

 mysql> insert into friends(name, age) values('Jane', 22);

 mysql> insert into friends(name, age) values('Luke', 28);

本节示例代码如下:

#include <my_global.h>
#include <mysql.h>
int main(int argc, char **argv)
{
  MYSQL *conn;
  MYSQL_RES *result;
  MYSQL_ROW row;
  MYSQL_FIELD *field;
  int num_fields;
  int i;
  conn = mysql_init(NULL);
  mysql_real_connect(conn, "localhost", "zetcode", "passwd", "testdb", 0, NULL, 0);
  mysql_query(conn, "SELECT * FROM friends");
  result = mysql_store_result(conn);
  num_fields = mysql_num_fields(result);
  while ((row = mysql_fetch_row(result)))
  {
      for(i = 0; i < num_fields; i++)
      {
          if (i == 0) {
             while(field = mysql_fetch_field(result)) {
                printf("%s ", field->name);
             }
          printf("\n");
          }
          printf("%s  ", row[i] ? row[i] : "NULL");
      }
  }
  printf("\n");
  mysql_free_result(result);
  mysql_close(conn);
}


本节示例代码和上一节类似,只是增加了获取表中列名称的代码:

 while(field = mysql_fetch_field(result)) {

     printf("%s ", field->name);

 }

函数mysql_fetch_field返回一个MYSQL_FIELD结构,从结构中可以获取列的名称。编译后,程序输出如下:

$ ./headers

id name age

1  Tom  25

2  Elisabeth  32

3  Jane  22

4  Luke  28

(八)插入图片到Mysql数据库

有人喜欢使用mysql来存储图片,而有的人喜欢把图片存储在文件系统中。而当我们要处理成千上万的图片时,会引起技术问题。图片时二进制数据,mysql有种特殊的数据类型,用来存储二进制数据,叫做BLOB(Binary Large Ojbect)。

mysql> describe images;

+-------+------------+------+-----+---------+-------+

| Field | Type       | Null | Key | Default | Extra |

+-------+------------+------+-----+---------+-------+

| id    | int(11)    | NO   | PRI |         |       |

| data  | mediumblob | YES  |     | NULL    |       |

+-------+------------+------+-----+---------+-------+

2 rows in set (0.00 sec)

这个是本节中我们要使用的表,创建语句如下:

create table images(id int not null primary key, data mediumblob);

以下是本例中所有程序代码:

#include <my_global.h>

#include <mysql.h>

int main(int argc, char **argv)

{

  MYSQL *conn;

  int len, size;

  char data[1000*1024];

  char chunk[2*1000*1024+1];

  char query[1024*5000];

  FILE *fp;

  conn = mysql_init(NULL);

  mysql_real_connect(conn, "localhost", "zetcode", "passwd", "testdb", 0, NULL, 0);

  fp = fopen("image.png", "rb");

  size = fread(data, 1, 1024*1000, fp);

  mysql_real_escape_string(conn, chunk, data, size);

  char *stat = "INSERT INTO images(id, data) VALUES('1', '%s')";

  len = snprintf(query, sizeof(stat)+sizeof(chunk) , stat, chunk);

  mysql_real_query(conn, query, len);

  fclose(fp);

  mysql_close(conn);

}

在本例中,我们把一张图片存储到images表中。图片大小最大不超过1M。

首先我们,打开一个图片文件,并读取图片数据:

 fp = fopen("image.png", "rb");

 size = fread(data, 1, 1024*1000, fp);

二进制数据可以包含一些特殊的字符,这些在sql语句中可能会引起一些问题。所以必须进行转义,理论上来说,每个字符可能是特殊字符。所以chunk数组大小是data数组大小的两倍,该函数会在chunk数组加上结尾符。

 mysql_real_escape_string(conn, chunk, data, size);

一下两行代码拼接insert所用的sql语句:

 char *stat = "INSERT INTO images(id, data) VALUES('1', '%s')";

 len = snprintf(query, sizeof(stat)+sizeof(chunk) , stat, chunk);

最后,执行sql语句:

mysql_real_query(conn, query, len);

(九)从Mysql数据库取回图片

在上一节中,我们把图片保存到数据库中,本节我们把图片从数据库中取回并且还原为图片,本节示例代码如下:

#include <my_global.h>
#include <mysql.h>
int main(int argc, char **argv)
{
  MYSQL *conn;
  MYSQL_RES *result;
  MYSQL_ROW row;
  unsigned long *lengths;
  FILE *fp;
  conn = mysql_init(NULL);
  mysql_real_connect(conn, "localhost", "zetcode", "passwd", "testdb", 0, NULL, 0);
  fp = fopen("image.png", "wb");
  mysql_query(conn, "SELECT data FROM images WHERE id=1");
  result = mysql_store_result(conn);
  row = mysql_fetch_row(result);
  lengths = mysql_fetch_lengths(result);
  fwrite(row[0], lengths[0], 1, fp);
  mysql_free_result(result);
  fclose(fp);
  mysql_close(conn);
}


首先,我们创建一个文件用来保存图片:

fp = fopen("image.png", "wb");

然后,我们把之前的图片查询出来:

 mysql_query(conn, "SELECT data FROM images WHERE id=1");

之后,得到图片数据和数据长度:

row = mysql_fetch_row(result);

lengths = mysql_fetch_lengths(result);

最后,使用fwrite把图片保存到文件中:

fwrite(row[0], lengths[0], 1, fp);


最后,推荐一个编程分类网站 www.code250.com


相关文章推荐

高质量C++/C编程指南 -- 第1章 文件结构

第 1 章 文件结构 每个 C++/C 程序通常分为两个文件。一个文件用于保存程序的声明( declaration ),称为头文件。另一个文件用于保存程序的实现( implementation ),...

objective-C运行时编程指南之运行时交互

运行时交互 Objective-C程序和运行时系统在三个不同层次上就行交互:通过Objective-C源代码;通过定义在Foundation框架中的NSObject类里的方法;通过直接调用运行时方法...

推荐-高质量C++/C编程指南(林锐)

推荐-高质量C++/C编程指南(林锐) 版本/状态 作者 参与者 起止日期 备注 V 0.9 草稿文件 ...

《高质量C++/C编程指南》读书笔记之一

《高质量C++/C编程指南》------作者林锐博士 作者在前言中所讲的关于编程老手与编程高手以及结合自己的经历,给我们讲述了关于编程质量的重要性以及必须对于其质量的重视。 1.知错就改。 2....

Objective-C 运行时编程指南 之 Declared Properties

可以使用方法访问属性元数据,支持通过类或协议中的名字查找属性,获得以 @encode 字符串表示的属性类型,以及拷贝属性的标志列表作为C字符串数组。已声明的属性的列表对于每个类和协议都是可用的。...

高质量C++/C编程指南

格式来引用标准库的头文件(编译器将从标准库目录开始搜索)。 l 【规则1-2-3】用 #include “filename.h” 格式来引用非标准库的头文件(编译器将从用户的工...

《高质量C++/C编程指南》笔记——内存管理1-2

7.1 内存分配方式 内存分配方式有三种: (1)从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。 (2)在栈上创建。在...

《林锐-高质量C/C++编程指南》笔记

1.if语句规则 1.1 不可将布尔变量直接与TRUE、 FALSE 或者1、 0 进行比较。 根据布尔类型的语义,零值为“假”(记为FALSE),任何非零值都是“真”(记为TRUE)。TRUE 的值...

高质量C/C++编程指南(一)

不知道大家之前的评分怎样,无论如何好的写作规范方便了自己,也会方便以后看代码的人。以下的写作规范源自 林锐的《高质量C++/C编程指南。...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Mysql C API编程指南
举报原因:
原因补充:

(最多只允许输入30个字)