一、C API数据类型
MYSQL: 该结构代表1个数据库连接的句柄。不应尝试拷贝MYSQL结构。不保证这类拷贝结果会有用。MYSQL_RES: 该结构代表返回行的查询结果(SELECT, SHOW, DESCRIBE, EXPLAIN)。
MYSQL_ROW: 这是1行数据的“类型安全”表示。行是通过调用mysql_fetch_row()获得的。它目前是按照计数字节字符串的数组实施的。 typedef char **MYSQL_ROW。MYSQL_ROW指针是一简单的字符串数组,所有的数据类型被转换成字符串送到客户端。
MYSQL_FIELD: 该结构包含关于字段的信息,如字段名、类型和大小。通过重复调用mysql_fetch_field(),可为每个字段获得MYSQL_FIELD结构。字段值不是该结构的组成部份,它们包含在MYSQL_ROW结构中。
MYSQL_FIELD_OFFSET: 这是MySQL字段列表偏移量的“类型安全”表示(由mysql_field_seek()使用)。偏移量是行内的字段编号,从0开始。
my_ulonglong: 用于行数以及mysql_affected_rows()、mysql_num_rows()和mysql_insert_id()的类型。该类型提供的范围为0~1.84e19。 在某些系统上,不能打印类型my_ulonglong的值。要想打印这类值,请将其转换为无符号长整数类型并使用%lu打印格式,例如:
printf ("Number of rows: %lu\n", (unsigned long) mysql_num_rows(result));
二、C API函数概述
与MySQL交互时,应用程序应使用该一般性原则:
(1)通过调用mysql_library_init(),初始化MySQL库。库可以是mysqlclient C客户端库,或mysqld嵌入式服务器库,具体情况取决于应用程序是否与“-libmysqlclient”或“-libmysqld”标志链接。如果愿意,可省略对mysql_library_init()的调用,这是因为,必要时,mysql_init()会自动调用它。
(2)通过调用mysql_init()初始化连接处理程序,并通过调用mysql_real_connect()连接到服务器。
(3)发出SQL语句并处理其结果。当连接处于活动状态时,客户端或许会使用mysql_query()或mysql_real_query()向服务器发出SQL查询。两者的差别在于,mysql_query()预期的查询为指定的、由Null终结的字符串,而mysql_real_query()预期的是计数字符串。如果字符串包含二进制数据(其中可能包含Null字节),就必须使用mysql_real_query()。
对于每个非SELECT查询(例如INSERT、UPDATE、DELETE),通过调用mysql_affected_rows(),可发现有多少行已被改变(影响)。
对于SELECT查询,能够检索作为结果集的行。注意,某些语句因其返回行,类似与SELECT。包括SHOW、DESCRIBE和EXPLAIN。应按照对待SELECT语句的方式处理它们。
客户端处理结果集的方式有两种:
第一种方式是,通过调用mysql_store_result(),一次性地检索整个结果集。该函数能从服务器获得查询返回的所有行,并将它们保存在客户端。
第二种方式是,针对客户端的,通过调用mysql_use_result(),对“按行”结果集检索进行初始化处理。该函数能初始化检索结果,但不能从服务器获得任何实际行。
在这两种情况下,均能通过调用mysql_fetch_row()访问行。通过mysql_store_result(),mysql_fetch_row()能够访问以前从服务器获得的行。通过mysql_use_result(),mysql_fetch_row()能够实际地检索来自服务器的行。通过调用mysql_fetch_lengths(),能获得关于各行中数据大小的信息。完成结果集操作后,请调用mysql_free_result()释放结果集使用的内存。这两种检索机制是互补的。客户端程序应选择最能满足其要求的方法。
实际上,客户端最常使用的是mysql_store_result()。mysql_store_result()的1个优点在于,由于将行全部提取到了客户端上,你不仅能连续访问行,还能使用mysql_data_seek()或mysql_row_seek()在结果集中向前或向后移动,以更改结果集内当前行的位置。通过调用mysql_num_rows(),还能发现有多少行。另一方面,对于大的结果集,mysql_store_result()所需的内存可能会很大,你很可能遇到内存溢出状况。
通过重复调用mysql_fetch_field(),可以按顺序访问行内的字段信息,或者,通过调用mysql_fetch_field_direct(),能够在行内按字段编号访问字段信息。通过调用mysql_field_seek(),可以改变当前字段的光标位置。对字段光标的设置将影响后续的mysql_fetch_field()调用。此外,你也能通过调用mysql_fetch_fields(),一次性地获得关于字段的所有信息。为了检测和通报错误,MySQL提供了使用mysql_errno()和mysql_error()函数访问错误信息的机制。
(4)通过调用mysql_close(),关闭与MySQL服务器的连接。
(5)通过调用mysql_library_end(),结束MySQL库的使用。
三、C API函数描述
(1)mysql_init()
- MYSQL *MYSQL *mysql_init(MYSQL *mysql) ;
(2)mysql_options()
- int mysql_options(MYSQL *mysql, enum mysql_option option, const char *arg);
(3)mysql_real_connect()
- MYSQL *mysql_real_connect(MYSQL *mysql,
- const char *host,
- const char *user,
- const char *passwd,
- const char *db,
- unsigned int port,
- const char *unix_socket,
- unsigned long client_flag) ;
mysql_real_connect()尝试与运行在主机上的MySQL数据库引擎建立连接。在你能够执行需要有效MySQL连接句柄结构的任何其他API函数之前,mysql_real_connect()必须成功完成。
如果连接成功,返回MYSQL*连接句柄。如果连接失败,返回NULL。对于成功的连接,返回值与第1个参数的值相同。 第1个参数mysql是已有MYSQL结构的地址,调用mysql_real_connect()之前,必须调用mysql_init()来初始化MYSQL结构,通过mysql_options()调用,可更改多种连接选项。 “host”的值必须是主机名或IP地址,如果“host”是NULL或字符串"localhost",连接将被视为与本地主机的连接。“user”参数包含用户的MySQL登录ID。如果“user”是NULL或空字符串"",用户将被视为当前用户。在UNIX环境下,它是当前的登录名。在Windows ODBC下,必须明确指定当前用户名。“passwd”参数包含用户的密码。“db”是数据库名称。如果db为NULL,连接会将默认的数据库设为该值。如果“port”不是0,其值将用作TCP/IP连接的端口号。注意,“host”参数决定了连接的类型。如果unix_socket不是NULL,该字符串描述了应使用的套接字或命名管道。client_flag的值通常为0。
- MYSQL mysql;
- mysql_init(&mysql);
- mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"your_prog_name");
- if (!mysql_real_connect(&mysql,"host","user","passwd","database",0,NULL,0))
- {
- fprintf(stderr, "Failed to connect to database: Error: %s\n",
- mysql_error(&mysql));
- }
- int mysql_query(MYSQL *mysql, const char *query) ;
mysql_query()不能用于包含二进制数据的查询,应使用mysql_real_query()取而代之(二进制数据可能包含字符‘\0’,mysql_query()会将该字符解释为查询字符串结束)。
(5) mysql_real_query()
int mysql_real_query(MYSQL *mysql, const char *query, unsigned long length);
执行由“query”指向的SQL查询,它应是字符串长度字节“long”。正常情况下,字符串必须包含1条SQL语句,而且不应为语句添加终结分号(‘;’)或“\g”。如果允许多语句执行,字符串可包含由分号隔开的多条语句。如果希望知道查询是否应返回结果集,可使用mysql_field_count()进行检查。
(6) mysql_store_result()
- MYSQL_RES *mysql_store_result(MYSQL *mysql) ;
一旦调用了mysql_store_result()并获得了不是Null指针的结果, 可调用mysql_num_rows()来找出结果集中的行数,也可以调用mysql_num_fields()来获取结果集中的列数,或调用mysql_fetch_row()来获取结果集中的行,或调用mysql_row_seek()和mysql_row_tell()来获取或设置结果集中的当前行位置。 一旦完成了对结果集的操作,必须调用mysql_free_result()。
(7)mysql_num_fields()
- unsigned int mysql_num_fields(MYSQL_RES *result);
你可以从指向结果集的指针或指向连接句柄的指针获得行数。如果mysql_store_result()或mysql_use_result()返回NULL,应使用连接句柄(因而没有结果集指针)。在该情况下,可调用mysql_field_count()来判断mysql_store_result()是否生成了非空结果。这样,客户端程序就能采取恰当的行动,而不需要知道查询是否是SELECT语句(或类似SELECT的语句)。
(8)mysql_num_rows()
- my_ulonglong mysql_num_rows(MYSQL_RES *result) ;
(9)mysql_fetch_row()
- MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
- MYSQL_ROW row;
- unsigned int num_fields;
- unsigned int i;
- num_fields = mysql_num_fields(result);
- while ((row = mysql_fetch_row(result)))
- {
- unsigned long *lengths;
- lengths = mysql_fetch_lengths(result);
- for(i = 0; i < num_fields; i++)
- {
- printf("[%.*s] ", (int) lengths[i], row[i] ? row[i] : "NULL");
- }
- printf("\n");
- }
- #include <stdio.h>
- #include <stdlib.h>
- #include <my_global.h>
- #include <mysql.h>
- #include <string.h>
- int main(int argc, char **agrv)
- {
- char *host = "222.24.59.100";
- char *user = "ssss";
- char *password = "ssss";
- char *database = "school";
- unsigned int port = 3306; //无符号整形
- char sqltext[100] = {0};
- MYSQL *con;
- con = mysql_init(NULL);
- if(con == NULL)
- {
- printf("error %u:%s.\n", mysql_errno(con), mysql_error(con));
- exit(1);
- }
- if(mysql_real_connect(con, host, user, password, database, port, NULL, 0) == NULL)
- {
- printf("error %u:%s.\n", mysql_errno(con), mysql_error(con));
- exit(1);
- }
- printf("success to connect to database!\n");
- /*
- sprintf(sqltext,"SET CHARACTER SET GBK"); //设置编码
- if(mysql_real_query(con,sqltext,(unsigned int)strlen(sqltext)));
- {
- printf("编码设置失败!\n");
- exit(1);
- }
- */
- sprintf(sqltext, "CREATE TABLE IF NOT EXISTS student(no varchar(10) unique not null,name varchar(20) not null,class varchar(10) not null,birth_date datetime)");
- if(mysql_query(con, sqltext))//如果查询成功,返回0。如果出现错误,返回非0值。
- {
- printf("error %u:%s.\n", mysql_errno(con), mysql_error(con));
- exit(1);
- }
- /*
- if(mysql_query(con, "INSERT INTO student(no,name,class,birth_date) VALUES('1203210001','Parry','0804','2008-09-01 12:23:12')"))
- {
- printf("error %u:%s.\n", mysql_errno(con), mysql_error(con));
- exit(1);
- }
- if(mysql_query(con, "INSERT INTO student(no,name,class,birth_date) VALUES('1203210002','Jack','0803','2008-10-01 12:24:12')"))
- {
- printf("error %u:%s.\n", mysql_errno(con), mysql_error(con));
- exit(1);
- }
- if(mysql_query(con, "INSERT INTO student(no,name,class,birth_date) VALUES('1203210003','Rose','0801','2008-08-01 10:02:58')"))
- {
- printf("error %u:%s.\n", mysql_errno(con), mysql_error(con));
- exit(1);
- }
- if(mysql_query(con, "select * from student"))
- {
- printf("Error %u: %s\n", mysql_errno(con), mysql_error(con));
- exit(1);
- }
- */
- sprintf(sqltext,"SELECT * FROM student WHERE birth_date='2008-09-01 12:24:12'");
- if(mysql_query(con, sqltext))
- {
- printf("Error %u: %s\n", mysql_errno(con), mysql_error(con));
- exit(1);
- }
- MYSQL_RES *result;//保存结果集
- MYSQL_FIELD *result_field;//保存字段名字信息
- MYSQL_ROW row;
- int num_rows,num_fields;
- int i;
- result = mysql_store_result(con);
- num_rows = mysql_num_rows(result);
- num_fields = mysql_num_fields(result);//获取查询结果中,字段的个数
- printf("num_rows = %d , num_fields = %d\n\n", num_rows , num_fields);
- while((row = mysql_fetch_row(result)))//遍历查询结果中的各行记录,从结果集中取出下一行数据
- {
- for(i = 0 ; i < num_fields ; i++)
- {
- printf("%s", row[i] ? row[i] : "NULL");
- }
- //printf("%s\n", row[3]);//调试行:取出第四个字段,显示时间
- printf("\n");
- }
- result_field = mysql_fetch_fields(result); //获取查询结果中,各个字段的名字;返回所有字段结构的数组,区别mysql_fetch_field:返回下一个字段的类型
- for(i = 0; i < num_fields;i++)
- {
- printf("field %u is %s\n",i,result_field[i].name);//获取的是字段名字(属性),而不是具体数值(字段值)
- }
- mysql_free_result(result);
- mysql_close(con);
- }