使用C语言访问MySQL数据库基础
一、MySQL管理
包含在MySQL发行版中的一些有用的工具程序使管理工作变得相当容易。
除mysqlshow命令以外,所有的MySQL命令都接受所示的3个标准参数
命令选项 |
参数 |
说明 |
-u |
用户名 |
在默认情况下,mysql工具会尝试把当前linux的用户名作为MySQL的用户名,可以使用-u参数来指定一个不同的用户名 |
-p |
[密码] |
如果给出了-p参数但是未提供密码,系统会提示输入密码。 如果没有给出-p参数,MySQL命令将假设不需要密码 |
-h |
主机名 |
用于连接位于不同主机上的服务器(这个参数对于本地服务器总是可以省略) |
1、mysql命令
#mysql –u rick –p database-name
#mysql –u rick --password=secretpassworddatabase-name <sqlcommands.sql
当mysql客户端连接到服务器后,除了标准SQL92命令集外,还有以下特定命令也会被mysql支持
命令 |
可选的简短形式 |
说明 |
help 或? |
\h或\? |
显示命令列表 |
edit |
\e |
编辑命令。使用的编辑器由环境变量$EDITOR决定 |
exit或quit |
\q |
退出MySQL客户端 |
Go |
\g |
执行命令 |
source <filename> |
\. |
从指定文件执行SQL |
Status |
\s |
显示服务器状态信息 |
System <command> |
\! |
执行一个系统命令 |
tee <filename> |
\T |
把所有文件的副本添加到指定文件中 |
Use <database> |
\u |
使用给定的数据库 |
每个数据库都是一个独立的表格集,这使得我们可以外对不同的目的建立不同的数据库,并为每个数据库指定不同的用户,而只需要使用同一个数据库服务器就可以有效管理它们了。
2、mysqladmin 快速进行MySQL数据库管理的主要工具
mysqladmin支持的命令
命令 |
说明 |
create <database_name> |
创建一个数据库 |
drop <database_name> |
删除一个数据库 |
Password <new_password> |
修改密码 |
Ping |
检查服务器是否正在运行 |
reload |
重载控制权限grant表 |
Status |
提供服务器的状态 |
Shutdown |
停止服务器 |
Variables |
显示控制MySQL操作的变量及其当前值 |
Version |
提供服务器的版本号以及它持续运行的时间 |
3、mysqldump
作用:以SQL命令集的形式将部分或整个数据库导出到一个单独文件中,该文件能被重新导入MySQL或其它的SQL RDBMS。它接受数据库名和表名作为参数
命令 |
说明 |
--add-drop-table |
添加sql命令到输出文件,以在创建表的命令之前丢弃(删除)任何表 |
-e |
使用扩展的insert语法,这不是sql标准,但是如果在正转储大量数据,那么当你试图重新加载这些数据到MySQL时,这将加速转储数据的加载速度 |
-t |
只转储(备份)表中数据,而不是用来创建表的信息 |
-d |
只转储(备份)表结构,而不是实际数据 |
例:#mysqldump –u rick –p db-name >db-name.dump
4、mysqlimport
作用:用于将批量数据导入到一个表中
通过使用mysqlimport,可以从一个输入文件中读取大量的文本数据。这个命令唯一的参数需求是一个文件名和一个数据库名。默认情况下,数据应以tab分隔符分开。
5、mysqlshow
作用:快速了解MySQL安装及其组成数据库的信息
l 不提供参数,它列出所有可用的数据库
l 以一个数据库为参数,它列出该数据库中的表
l 以数据训和表名为参数,它列出表中的列
l 以数据库、表和列为参数,它列出指定列的详细信息
二、连接例程
用C语言连接MySQL数据库包含两个步骤
l 初始化一个连接句柄结构
l 实际进行连接
1、 使用mysql_init来初始化连接句柄
#include “mysql.h”
MYSQL *mysql_init(MYSQL *);
返回值:通常传递NULL给这个例程,它会返回一个指向新分配的连接句柄结构的指针
若传递一个已有的结构,它将被重新初始化。
出错时返回NULL
2、 进行实际连接
#include “mysql.h”
MYSQL *mysql_real_connect(MYSQL *connection,
const char*server_host,//localhost
const char*sql_user_name,
const char*sql_password,
const char *db_name,
unsigned intport_number,//端口号,一般为0
const char*unix_socket_name,//套接字,一般为null
unsigned int flags);
参数:connection 必须指向已经被mysql_init初始化过的结构
Sql_user_name和sql_password如果登录名为NULL,则假设登录名为当前Linux用户的登录ID,
如果密码为NULL,将只能访问服务器上无需密码就可访问的数据,密码会在
通过网络传输前进行加密
Port_number和unix_socket_name应该分别为0和NULL
flags用来对一些定义的位模式进行OR操作
返回值:若无法连接,它将返回NULL,mysql_error函数可以提供有帮助的信息
3、 关闭连接
#include “mysql.h”
Void mysql_close(MYSQL *connection);
如果连接是由mysql_init建立的,MYSQL结构会被释放。指针将会失效并无法再次使用
4、 mysql_options例程
可以在mysql_init和mysql_real_connect之间调用设置一些选项
#include “mysql.h”
Int mysql_options(MYSQL *connection, enum option_to_set, const char*argument);
说明:mysql_options例程一次只能设置一个选项,所以每设置一个选项就得调用它一次,同时,该例程必须出现在mysql_init和mysql_real_connect之间即可。
选 项
enum选项 |
实际参数类型 |
说明 |
MySQL_OPT_CONNECT_TIMEOUT |
Const unsigned int * |
连接超时之前的等待秒数 |
MySQL_OPT_COMPRESS |
None, 使用NULL |
网络连接中使用压缩机制 |
MySQL_INIT_COMMAND |
Const char * |
每次连接建立后发送的命令 |
返回值:一次成功的调用将返回0。因为它仅仅是用来设置标志,所以失败总是意味着使用了一个无效的选项。
例:如果要设置连接超时时间为7秒,其代码片断如下:
Unsigned inttimeout = 7;
…
connection=mysql_init(NULL);
ret=mysql_option(connection,MYSQL_OPT_CONNECTION_TIMEOUT, (constchar *)&timeout);
if (ret){
/Handle error */
…
}
connection=mysql_real_connect(connection…
5、 连接数据库实例---connect1.c
5.1 数据库部分
在211.71.149.59MySQL数据库服务器中以”ex+学号”为数据库名,以学号为用户名,创建数据库
1) 进入MySQL数据库
%mysql –u root –p
Password: 1qaz2wsx
2) 生成数据库
create database ex110301;
Query OK, 1 row affected (0.01sec)
3) 授权:
用户的授权信息保存于mysql数据库中的user表中
例:mysql>user mysql;
mysql>select user, host, passwordfrom user;
授权语法:
grant allon 数据库名.表名 to 用户名@客户登录计算机名(地址)identified by ‘密码’;
例:mysql>grant all on *.* to test@localhost identified by ‘password’;
mysql>use mysql; 打开MySQL数据库
mysql>update user 更新user表
>setpassword=OLD_PASSWORD('password')
>where user='test';
mysql>flush privileges;
或
mysql>grant all on ex110301.* to w12@localhost identified by ‘password’;//只能在本地访问这个数据库
mysql>grantall on ex110301.* to w12@% identified by ‘password’; (%是Any的意思,任何地方都可以访问)
mysql>use mysql; 打开MySQL数据库
mysql>update user 更新user表
>setpassword=OLD_PASSWORD('password')
>where user='w12';
mysql>flush privileges;
或
mysql>grant all on ex110301.* tow12@'%' identified by 'password';
mysql>use mysql; 打开MySQL数据库
mysql>update user 更新user表
>setpassword=OLD_PASSWORD('password')
>where user='w12';
mysql>flush privileges;
mysql>exit
4) 改用你授权的用户名/密码登录
%mysql –u 授权的用户名 -p
Password:输入授权密码
5) 查看该用户有权限访问的数据库
mysql>show databases;
5.2 程序部分
1 #include <stdlib.h>
2 #include <stdio.h>
4 #include "mysql.h"
5
6 int main(int argc, char *argv[]) {
7 MYSQL *conn_ptr;
8
9 conn_ptr = mysql_init(NULL);
10 if (!conn_ptr) {
11 fprintf(stderr, "mysql_init failed\n");
12 return EXIT_FAILURE;
13 }
14
15 conn_ptr= mysql_real_connect(conn_ptr, "localhost", "用户名", "密码",
"数据库名称", 0, NULL, 0);
18 if (conn_ptr) {
19 printf("Connection success\n");
20 } else {
21 printf("Connection failed\n");
22 }
23
24 mysql_close(conn_ptr);
25
26 return EXIT_SUCCESS;
27 }
编译:# gcc -I/usr/include/mysql connect1.c -L/usr/lib/mysql -lmysqlclient -o connect1
其中:-I(大写的i) 指定include路径
-L(大写的L) 指定库文件路径
-l(小写的l) 指定链接的库函数
执行:# ./connect1
结果:Connection success
三、错误处理
MySQL使用由连接句柄结构报告的返回码,两个必备的例程是:
Unsigned int mysql_errno(MYSQL *connection); 返回错误码
和
char *mysql_error(MYSQL *connection); 返回错误码对应的文本信息
可以通过调用mysql_errno并传递连接结构来获得错误码(错误码在头文件errmsg.h(报告客户端错误)或mysqld_error.h(报告服务器端错误)中定义),错误码通常都是非0值。如果未设定错误码,它将返回0.
每次调用库都会更新错误码,所以只能得到最后一个执行命令的错误码。
例:connect2.c
1 #include<stdlib.h>
2 #include <stdio.h>
4 #include "mysql.h"
5
6 int main(int argc, char *argv[]) {
7 MYSQL my_connection;
8
9 mysql_init(&my_connection);
10 if (mysql_real_connect(&my_connection, "localhost", "用户名", "错误密码", "db-name", 0, NULL, 0)) {
11 printf("Connection success\n");
12 mysql_close(&my_connection);
13 } else {
14 fprintf(stderr, "Connection failed\n");
15 if (mysql_errno(&my_connection)) {
16 fprintf(stderr, "Connectionerror %d: %s\n", mysql_errno(&
my_connection),mysql_error(&my_connection));
17 }
18 }
19
20 return EXIT_SUCCESS;
21 }
编译:# gcc -I/usr/include/mysql connect2.c -L/usr/lib/mysql-lmysqlclient -o connect2
执行:# ./connect2
结果:Connection failed
Connection error 1045: Accessdenied for user 'n1417'@'localhost' (using password: YES)_
四、执行SQL语句
(一)、执行SQL语句的主要API函数
Intmysql_query(MYSQL *connection, const char *query);
说明:此例程接受连接结构指针和文本字符串形式的有效SQL语句
返回值:如果成功,返回0
(二)、不返回数据的SQL语句
不返回数据SQL语句是指update, delete和insert
1、检查受影响的行数
My_ulonglongmysql_affected_rows(MYSQL *connection);
说明:返回值的数据类型是my_ulonglong(无符号长整型),使用printf时,应使用的转换符为%lu
作用:函数返回受update, insert或delete查询影响的行数
返回值:0 没有受影响的行数
正数 受语句影响的行数
1.1 操作数据库
# mysql -u 用户名 -p db-name
Enter password:
mysql> showtables;
+---------------+
| Tables_in_foo |
+---------------+
| children |
+---------------+
1 row in set (0.00sec)
mysql> droptable children; 删除表children
Query OK, 0 rowsaffected (0.25 sec)
mysql> createtable children( 新生成children表
-> childno int(11) auto_increment notnull primary key,
-> fname varchar(30),
-> age int
-> );
Query OK, 0 rowsaffected (0.01 sec)
插入数据
mysql> insertinto children(fname,age) values("jenny",21);
mysql> insertinto children(fname,age) values("Andrew",17);
mysql> insertinto children(fname,age) values("Gavin",9);
mysql> insertinto children(fname,age) values("Duncan",6);
mysql> insertinto children(fname,age) values("Emma",4);
mysql> insertinto children(fname,age) values("Alex",15);
mysql> insertinto children(fname,age) values("Ann",15);
1.2检查插入的数据
mysql> select *from children;
+---------+--------+------+
| childno | fname | age |
+---------+--------+------+
| 1 | jenny | 21 |
| 2 | Andrew | 17 |
| 3 | Gavin | 9 |
| 4 | Duncan | 6 |
| 5 | Emma | 4 |
| 6 | Alex | 15 |
| 7 | Ann | 15 |
+---------+--------+------+
7 rows in set (0.00 sec)
2、程序: 更新数据---update1.c
1 #include <stdlib.h>
2 #include <stdio.h>
3
4 #include "mysql.h"
5
6 int main(int argc, char *argv[]) {
7 MYSQL my_connection;
8 int res; int age_value=4;
9
10 mysql_init(&my_connection);
11 if (mysql_real_connect(&my_connection, "localhost",
12 "username","secret", "foo", 0, NULL, 0)) {
13 printf("Connection success\n");
15 res = mysql_query(&my_connection, "UPDATE children SET AGE = %d
WHERE fname = 'Ann'",age_value); //说明:因为C语言不能区分一个单词是变量还是字符串,可以直接写死
//所以采用类似于printf的占位符%d,%ld,%u,%s等形式
//来明示此处引入的值是以变量形式表示。
16 if (!res) {
17 printf("Updated %lu rows\n", (unsignedlong)mysql_affected_rows(&my_connection));
18 } else {
19 fprintf(stderr, "Update error %d: %s\n",mysql_errno(&my_co
nnection), mysql_error(&my_connection));
21 }
22
23 mysql_close(&my_connection);
24 } else {
25 fprintf(stderr, "Connection failed\n");
26 if(mysql_errno(&my_connection)) {
27 fprintf(stderr, "Connection error%d: %s\n", mysql_errno(&my_connection),mysql_error(&my_connection));
29 }
30 }
31
32 return EXIT_SUCCESS;
33 }
编译:# gcc -I/usr/include/mysql update1.c -L/usr/lib/mysql -lmysqlclient-o update1
执行: # ./update1
结果:未修改代码时报错
Connectionsuccess
Updated1 rows
五、返回数据的语句
在C应用程序中提取数据一般需要以下4个步骤
l 执行查询:使用mysql_query来发送SQL语句
l 提取数据:使用mysql_store_result或mysql_use_result来提取数据
l 处理数据:使用mysql_fetch_row处理数据
l 必要的清理工作:使用mysql_free_result释放查询占用的资源
(一)、相关数据类型
l MYSQL_RES:此数据结构表示一次查询返回行的结果(select, show, describe, explain)。
从一查询中返回的信息被称为结果集
· MYSQL_ROW:这是一行数据的一种type-safe表示方式。它目前被作为计数字节字符串的阵列
它是由mysql_fetch_row()函数获取的行。即将一行记录中的不同类型的字段,转换为同一数据类型的数组形式,其每个属性字段的数据表达为:MYSQL_ROW[0]; MYSQL_ROW[1]; ...;MYSQL_ROW[N],避免用户定义结构体。
(二)、一次提取所有数据的函数
1、mysql_store_result()
作用:在一次调用中从select(或其它返回数据的语句)中提取所有数据,这个函数将立刻保存在客户端中返回的所有数据
#include “mysql.h”
MYSQL_RES *mysql_store_result(MYSQL *connection);
说明:需要在成功调用mysql_query之后使用此函数
返回值:返回一个指向结果集结构的指针
失败则返回NULL
2、my_ulonglong mysql_num_rows(MYSQL_RES*result);
作用:在调用mysql_store_result调用成功后,需要调用mysql_num_rows来得到返回记录的数目(返回结果集中的行数)
返回值:成功 正数
如果没有返回行,这个值将是0
3、mysql_fetch_row
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
作用:这个函数从使用mysql_strore_result得到的结果结构中提取一行,并把它放到一个行结构中。
当数据用完或发生错误时返回NULL。
4、mysql_date_seek
作用:用来在结果集中跳转,设置将会被下一个msyql_fetch_row操作返回的行
Voidmysql_data_seek(MYSQL_RES *result, my_ulonglong offset);
参数:offset的值是一个行号,它必须在0到结果集总行数减1的范围内。
传递0将会导致下一个mysql_fetch_row调用返回结果集中的第一行
2、mysql_row_tell
作用:返回一个偏移值,它用来表示结果集中的当前位置。它不是行号,不能把它用于mysq_data_seek
MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES *result);
3、mysql_free_result
作用:调用此函数来让MySQL库清理它分配的对象
Voidmysql_free_result(MYSQL_RES *result);
程序select1.c
1 #include <stdlib.h>
2 #include <stdio.h>
3
4 #include "mysql.h"
5
6 MYSQL my_connection;
7 MYSQL_RES *res_ptr;
8 MYSQL_ROW sqlrow;
9
10 int main(int argc, char *argv[]) {
11 int res;
12
13 mysql_init(&my_connection);
14 if (mysql_real_connect(&my_connection, "localhost","rick","secret", "foo", 0, NULL, 0)) {
16 printf("Connection success\n");
17
18 res = mysql_query(&my_connection, "SELECT childno, fname, ageFRO
M children WHERE age > 5");
19
20 if (res) {
21 printf("SELECT error: %s\n", mysql_error(&my_connection));
22 } else {
23 res_ptr = mysql_store_result(&my_connection);
24 if (res_ptr) {
25 printf("Retrieved %lu rows\n", (unsignedlong)mysql_num_rows(res_ptr));
26 while ((sqlrow = mysql_fetch_row(res_ptr))) {
27 printf("Fetched data...\n");
28 }
29 if (mysql_errno(&my_connection)) {
30 fprintf(stderr, "Retrive error: %s\n",mysql_error(&my_connection));
31 }
32 mysql_free_result(res_ptr);
33 }
35 }
36 mysql_close(&my_connection);
37
38 } else {
39 fprintf(stderr, "Connection failed\n");
40 if (mysql_errno(&my_connection)) {
41 fprintf(stderr, "Connection error %d: %s\n",
42 mysql_errno(&my_connection), mysql_error(&my_connection));
43 }
44 }
45
46 return EXIT_SUCCESS;
47 }
编译:cc -o select1 select1.c -I/usr/include/mysql-L/usr/lib/mysql -lmysqlclient
执行:# ./select1
结果:Connection success
Retrieved 5 rows
Fetched data...
Fetched data...
Fetched data...
Fetched data...
Fetched data...
(三)、一次提取一行
1、逐行提取数据
MYSQL_RES*mysql_use_result(MYSQL *connection);
返回值:指向结果集对明的指针,为了真正得到数据,你必须反复调用mysql_fetch_row直到提取了所有数据。如果没有从mysql_use_result中得到所有数据,那么程序中后续的提取数据操作可能会返回遭到破坏的信息。
错误,返回NULL
2、调用mysql_use_result和mysql_store_result的区别
Mysql_use_result具备资源管理方面的实质好处,但是它不能与mysql_data_seek、mysql_row_seek或mysql_row_tell一起使用,并且由于直到所有数据都被提取后才能实际生效,mysql_num_rows的使用也受到限制。
但是它可以更好地平衡网络负载,以减少可能非常大的数据集带来的存储开销
程序:select2.c
1 #include <stdlib.h>
2 #include <stdio.h>
3
4 #include "mysql.h"
5
6 MYSQL my_connection;
7 MYSQL_RES *res_ptr;
8 MYSQL_ROW sqlrow;
9
10 int main(int argc, char *argv[]) {
11 int res;
12
13 mysql_init(&my_connection);
14 if (mysql_real_connect(&my_connection, "localhost","rick",
15 "secret", "foo", 0, NULL, 0)) {
16 printf("Connection success\n");
17
18 res = mysql_query(&my_connection, "SELECT childno, fname, ageFRO
M children WHERE age > 5");
19
20 if (res) {
21 printf("SELECT error: %s\n", mysql_error(&my_connection));
22 } else {
23 res_ptr = mysql_use_result(&my_connection);
24 if (res_ptr) {
25 while ((sqlrow = mysql_fetch_row(res_ptr))) {
26 printf("Fetcheddata...\n");
27 }
28 if (mysql_errno(&my_connection)) {
29 printf("Retrive error:%s\n", mysql_error(&my_connection));
30 }
31 mysql_free_result(res_ptr);
32 }
33 }
34 mysql_close(&my_connection);
35
36 } else {
37 fprintf(stderr, "Connection failed\n");
38 if (mysql_errno(&my_connection)) {
39 fprintf(stderr, "Connection error %d: %s\n",
40 mysql_errno(&my_connection), mysql_error(&my_connection));
41 }
42 }
43
44 return EXIT_SUCCESS;
45 }
编译:# cc -o select2 select2.c -I/usr/include/mysql -L/usr/lib/mysql -lmysqlclient
执行:./select2
Connection success
Fetched data...
Fetched data...
Fetched data...
Fetched data...
Fetched data...
//不会从服务器读到客户端,所以没有提示5行
六、处理返回数据
上述函数从数据库中提取行,但是如何处理返回的实际数据呢?
同大多数SQL数据库一样,MySQL返回两种类型的数据
n 从表中提取的信息,也就是列数据
n 元数据(metadata)(describe <表名>中提取的数据)
1、mysql_field_count
作用:返回结果集中的字段(列)数目
Unsigned intmysql_field_count(MYSQL *connection);
程序select3.c
1 #include <stdlib.h>
2 #include <stdio.h>
3
4 #include "mysql.h"
5
6 MYSQL my_connection;
7 MYSQL_RES *res_ptr;
8 MYSQL_ROW sqlrow;
9
10 void display_row();
11
12 int main(int argc, char *argv[]) {
13 int res;
14
15 mysql_init(&my_connection);
16 if (mysql_real_connect(&my_connection, "localhost","rick","secret", "foo", 0, NULL, 0)) {
18 printf("Connection success\n");
19
20 res = mysql_query(&my_connection, "SELECT childno, fname, ageFROM children WHERE age > 5");
21
22 if (res) {
23 printf("SELECT error: %s\n", mysql_error(&my_connection));
24 } else {
25 res_ptr = mysql_use_result(&my_connection);
26 if (res_ptr) {
27 while ((sqlrow = mysql_fetch_row(res_ptr))) {
28 printf("Fetcheddata...\n");
29 display_row();
30 }
31 if (mysql_errno(&my_connection)) {
32 printf("Retrive error:%s\n", mysql_error(&my_connection));
33 }
34 mysql_free_result(res_ptr);
35 }
36 }
37 mysql_close(&my_connection);
38
39 } else {
40 fprintf(stderr, "Connection failed\n");
41 if (mysql_errno(&my_connection)) {
42 fprintf(stderr, "Connection error %d: %s\n",
43 mysql_errno(&my_connection), mysql_error(&my_connection));
44 }
45 }
46
47 return EXIT_SUCCESS;
48 }
49
50 void display_row() {
51 unsigned int field_count;
52
53 field_count = 0;
54 while (field_count < mysql_field_count(&my_connection)) {
55 printf("%s ", sqlrow[field_count]);
56 field_count++;
57 }
58 printf("\n");
59 }
编译:# cc -o select3 select3.c -I/usr/include/mysql -L/usr/lib/mysql -lmysqlclient
执行:# ./select3
试写出程序运行的结果:
Connection success
Fetched data...
1 jenny 21
Fetched data...
2 Andrew 17
Fetched data...
3 Gavin 9
Fetched data...
4 Duncan 6
Fetched data...
6 Alex 15
3、同时将元数据和数据提取到一个新的结构中
#include “mysql.h”
MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result)
重复调用此函数,直到返回表示数据结束的NULL值为止,然后,使用指向字段结构数据的指针来得到关于列的信息。
结构MySQL_FIELD定义在mysql.h中
MySQL_FIELD结构中的成员 |
说 明 |
char *name; |
列名,为字符串 |
char *table; |
列所属的有名。当一个查询要使用到多个表时,非常有用 注意:对于结果中可计算的值如MAX,它所对应的表名将为空字符串 |
enum enum_field_types type; |
列类型 |
unsigned int length; |
列宽,在定义表时指定 |
unsigned int max_length; |
如果使用sql_store_result,它将包含以字节为单位的提取的最长列值的长度。如果使用mysql_use_result,它将不会被设置 |
unsigned int flags; |
关于列定义的标志,与得到的数据无关。常见标志的含义都很明显,它们是NOT_NULL_FLAG, PRI_KEY_FLAG, UNSIGNED_FLAG, AUTO_INCREMENT_FLAG和BINARY_FLAG |
unsigned int decimals |
小数点后的数字个数,仅对数字字段有效 |
一个特别有用的预定义的宏为IS_NUM,当字段类型为数字时,它返回true,如
If (IS_NUM(mysql_field_ptr->type)) printf(“Numerictype filed\n”);
4、mysql_field_seek
#include “mysql.h”
MYSQL_FIELD_OFFSETmysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET offset);
作用:可以用此函数来覆盖当前的字段编号,该编号随每次mysql_fetch_field调用而自动增加
如果给参数offset传递值0,将跳回第一列
5、转义SQL语句中的特殊字符
mysql_escape_string(char *to, const char *from, unsigned long length);
Mysql_real_escape_string(MYSQL *mysql, char*to, const char *from, unsigned long length)
作用:转义SQL语句中的特殊字符,用于产生一个有效的SQL字符串
参数:from : 对一个转义SQL字符串进行译码(encoded)
to 将译码的结果放入to指针所指向的位置,并附加null字节
length长度
ASCII码字符转义表
例:char query[1000],*end;
end = strcpy(query,"INSERTINTO test_table values(");
*end++ = '\'';
end +=mysql_real_escape_string(&mysql, end,"What's this",11);
*end++ = '\'';
*end++ = ',';
*end++ = '\'';
end +=mysql_real_escape_string(&mysql, end,"binary data: \0\r\n",16);
*end++ = '\'';
*end++ = ')'; 此时end=INSERT INTO test_table values(“what’s this” ,”binary data: “);
if(mysql_real_query(&mysql,query,(unsigned int) (end - query)))
{
fprintf(stderr,"Failed to insert row, Error: %s\n",
mysql_error(&mysql));
}
程序select4.c
1 #include <stdlib.h>
2 #include <stdio.h>
3
4 #include "mysql.h"
5
6 MYSQL my_connection;
7 MYSQL_RES *res_ptr;
8 MYSQL_ROW sqlrow;
9
10 void display_header();
11 void display_row();
12
13
14 int main(int argc, char*argv[]) {
15 int res;
16 int first_row = 1;
/* Used toensure we display the row header exactly once when data is successfullyretrieved */
17
18
19 mysql_init(&my_connection);
20 if(mysql_real_connect(&my_connection, "localhost","rick","secret", "foo", 0,NULL, 0)) {
22 printf("Connectionsuccess\n");
23
24 res = mysql_query(&my_connection,"SELECT childno, fname, ageFROM children WHERE age > 5");
25
26 if (res) {
27 fprintf(stderr,"SELECT error: %s\n", mysql_error(&my_connection));
28 } else {
29 res_ptr =mysql_use_result(&my_connection);
30 if (res_ptr) {
31 while ((sqlrow = mysql_fetch_row(res_ptr))) {
32 if (first_row){
33 display_header();
34 first_row =0;
35 }
36 display_row();
37 }
38 if(mysql_errno(&my_connection)) {
39 fprintf(stderr,"Retrive error: %s\n",
40 mysql_error(&my_connection));
41 }
42 mysql_free_result(res_ptr);
43 }
44 }
45 mysql_close(&my_connection);
46 } else {
47 fprintf(stderr,"Connection failed\n");
48 if(mysql_errno(&my_connection)) {
49 fprintf(stderr,"Connection error %d: %s\n",
50 mysql_errno(&my_connection),
51 mysql_error(&my_connection));
52 }
53 }
54
55 return EXIT_SUCCESS;
56 }
57
58
59 void display_header() {
60 MYSQL_FIELD *field_ptr;
61
62 printf("Columndetails:\n");
63
64 while ((field_ptr =mysql_fetch_field(res_ptr)) != NULL) {
65 printf("\t Name:%s\n", field_ptr->name);
66 printf("\t Type:");
67 if(IS_NUM(field_ptr->type)) {
68 printf("Numericfield\n");
69 } else {
70 switch(field_ptr->type) {
71 caseFIELD_TYPE_VAR_STRING:
72 printf("VARCHAR\n");
73 break;
74 caseFIELD_TYPE_LONG:
75 printf("LONG\n");
76 break;
77 default:
78 printf("Type is %d, check in mysql_com.h\n",field_ptr->type);
79 } /* switch */
80 } /* else */
81
82 printf("\t Max width %ld\n",field_ptr->length);
/* Note on versions of MySQL before 4.0 the formatshould be %d, rather than %ld */
83 if (field_ptr->flags& AUTO_INCREMENT_FLAG)
84 printf("\t Autoincrements\n");
85 printf("\n");
86 } /* while */
87 }
88
89
90 void display_row() {
91 unsigned int field_count;
92
93 field_count = 0;
94 while (field_count <mysql_field_count(&my_connection)) {
95 if (sqlrow[field_count])printf("%s ", sqlrow[field_count]);
96 elseprintf("NULL");
97 field_count++;
98 }
99 printf("\n");
100 }
编译:# cc -o select4 select4.c -I/usr/include/mysql-L/usr/lib/mysql -lmysqlclient
执行:# ./select4
试写出程序运行的结果:
Connectionsuccess
Column details:
Name: childno
Type: Numeric field
Max width 11
Auto increments
Name: fname
Type: VARCHAR
Max width 30
Name: age
Type: Numeric field
Max width 11
1 jenny 21
2 Andrew 17
3 Gavin 9
4 Duncan 6
6 Alex 15