1、连接例程:
首先,使用mysql_init来初始化连接剧柄:
#include
初始化之后,你必须使用mysql_real_connect来向一个连接提供参数:
MYSQL *mysql_real_connect(MYSQL *connection,//指向已经被mysql_init初始化过的结构
const char *server_host,//可以是主机名,也可以是IP地址(本地可以是localhost)
const char *sql_user_name,//使用者
const char *sql_password,//使用者密码(密码会再被传输的过程中加密)
const char *db_name,//数据库名字
unsigned int port_number,//NULL,这两个为默认值就行
const char *unix_socket_name,//0
unsigned int flags);//这是改变协议的特性,位模式进行OR操作
如果无法连接,它将返回NULL。mysql_error函数可以提供又帮助的信息。
使用完连接之后,通常在程序退出时,使用mysql_close:
void mysql_close(MYSQL *connection);
这将关闭连接。如果连接时由mysql_init建立的,mysql结构会被释放。指针将会失效并无法再次使用。逗留一个不需
要的连接是对资源的浪费,但是重新打开连接也会带来额外的开销,所以你必须自己权衡何时使用这些选项。
mysql_options例程(仅能在mysql_init和mysql_read_connect之间调用)可以设置一些选项:
int mysql_options(MYSQL *connection,enum option_to_set,const char *argument);
因为mysql_options一次只能设置一个选项,所以每设置一个选项就得调用它一次。你可以根据需要多次使用它,只
要它出现在mysql_init和mysql_real_connect之间即可。并不是所有的选项都是char类型,因此它们必须被转换
成const char *.
enum选项 实际参数类型 说明
MYSQL_OPT_CONNECT_TIMEOUT const unsigned int * 连接超时之前的等待秒数
MYSQL_OPT_COMPRESS None,使用NULL 网络连接中使用压缩机制
MYSQL_INIT_COMMAND const char * 每次连接建立后发送的命令
一次成功的调用将返回0。因为它仅仅是用来设置标志,所以失败总是意味这使用了一个无效的选项。
例子:
如果要设置连接超时时间为7秒,我们使用的代码片段如下所示:
unsigned int timeout=7;
...
connection=mysql_init(NULL);
ret=mysql_options(connection,MYSQL_OPT_CONNECT_TIMEOUT,(const char *)&timeout);
if(ret){
/*Handle error*/
}
connection=mysql_real_connect(connection ...);
下面我们使用一个简洁的程序来测试一下:
首先为用户设置一个新的密码(在下面的代码中,是本机上的rick的用户),然后创建要连接的数据库foo。
$ mysql -u root -p
mysql> grant all on *.* to rick@localhost identified by '123456'
mysql> q
$ mysql -u rick -p
mysql> create database foo;
mysql> q
使用sql文件进行批处理,这个文件为create_children.sql:
create table children (
childno int(11) not null auto_increment primary key,
fname varchar(30),
age int(11)
);
insert into children(childno,fname,age) values(1,'Jenny',21);
insert into children(childno,fname,age) values(2,'Andrew',17);
insert into children(childno,fname,age) values(3,'Gavin',8);
insert into children(childno,fname,age) values(4,'DUncan',5);
insert into children(childno,fname,age) values(5,'Alex',4);
insert into children(childno,fname,age) values(6,'Adrian',9);
重新登录:
$ mysql -u rick -p foo //或者是:mysql -u rick --password=123456 foo
mysql> source create_children.sql //或者是:. create_children.sql
下面的程序connect1.c,它以用户名rick和密码123456来连接本机服务器上名为foo的数据库:
#include <stdlib.h>
#include <stdio.h>
#include "mysql.h"
int main(int argc,char *argv[]){
MYSQL *conn_ptr;
conn_ptr=mysql_init(NULL);//一般都是传递一个NULL
if(!conn_ptr){
fprintf(stderr,"mysql_init failed
");
return EXIT_FAILURE;
}
conn_ptr=mysql_real_connect(conn_ptr,"localhost","rick","123456","foo",0,NULL,0);
if(conn_ptr){
printf("COnnection success
");
}
else
{
printf("Connection failed
");
}
mysql_close(conn_ptr);
return EXIT_SUCCESS;
}
下面是编译:
1、gcc -I/usr/include/mysql connect1.c -L/usr/lib/mysql -L/usr/lib64/mysql -lmysqlclient -o connect1
我的是这种
2、gcc -I/usr/include/mysql connect1.c -L/usr/lib/mysql -lmysqlclient -o connect1
执行:(到这里你就成功了)
$ ./connect1
Connection success
错误处理
unsigned int mysql_errno(MYSQL *connection);
char *mysql_error(MYSQL *connection);
你可以通过调用mysql_error并传递连接结构来获得错误码,它通常都是非0值。
如果未设定错误码,它将返回0.
每次调用库都会跟新错误码,所以你只能得到最后一个执行命令的错误码。
但是上面两个检查是例外,它们不会导致错误码的更新。
mysql_errno的返回值就是实际错误码,它们在头文件errmsg.h或者mysqld_error.h中定义。
这两个文件都可以在MySQL的include目录中找到。
前者报告客户端错误,后者关注服务器错误。
如果你喜欢文本错误信息,也可以调用mysql_error,它提供了有意义的文本信息而不是单调的错误码。
下面的connect2.c它例出了如何使用非动态分配的连接结构,以及如何编写一些基本的错误处理代码:
#include <stdlib.h>
#include <stdio.h>
#include <mysql.h>
int main(int argc,char *argv[])
{
MYSQL my_connection;
mysql_init(&my_connection);
if(mysql_real_connect(&my_connection,"localhost","rick","I do not know","foo",0,NULL,0)){
printf("Connection success
");
mysql_close(&my_connection);
}
else
{
fprintf(stderr,"Connection_failed
");
if(mysql_errno(&my_connection)){
fprintf(stderr,"Connection error %d: %s
",
mysql_errno(&my_connection),mysql_error(&my_connection));
}
}
return EXIT_SUCCESS;
}
下面是编译:
1、gcc -I/usr/include/mysql connect1.c -L/usr/lib/mysql -L/usr/lib64/mysql -lmysqlclient -o connect1
我的是这种
2、gcc -I/usr/include/mysql connect1.c -L/usr/lib/mysql -lmysqlclient -o connect1
执行:
$ ./connect2
Connection_failed
Connection error 1045: Access denied for user 'rick'@'localhost' (using password: YES)
执行SQL语句
int mysql_query(MYSQL *connection,const char *query);
成功,返回0.对于包含二进制数据的查询,你可以使用mysql_real_query。
检查受影响的函数:
my_ulonglong mysql_affected_rows(MYSQL *connection);
例子:
#include <stdlib.h>
#include <stdio.h>
#include <mysql.h>
int main(int argc,char *argv[])
{
MYSQL my_connection;
int res;
mysql_init(&my_connection);
if(mysql_real_connect(&my_connection,"localhost",
"rick","123456","foo",0,NULL,0)){
printf("Connection success
");
//当前是更新,此处可以替换为插入
//mysql_query(&my_connection,"insert into children(fname,age) values('Ann',3)");
res=mysql_query(&my_connection,"update children set age=4 where fname='Ann'");
if(!res){
printf("updated %lu rows
",(unsigned long)mysql_affected_rows(&my_connection));
}
else
{
fprintf(stderr,"update error %d: %s
",mysql_errno(&my_connection),mysql_error(&my_connection));
}
mysql_close(&my_connection);
}
else
{
fprintf(stderr,"Connection failed
");
if(mysql_errno(&my_connection)){
fprintf(stderr,"Connection error %d: %s
",mysql_errno(&my_connection),mysql_error(&my_connection));
}
}
return EXIT_SUCCESS;
}
编译同上。
但是你也可以使用更传统的报告:
if(mysql_real_connect(&my_connection,"localhost","rick","123456","foo",0,NULL,CLIENT_FOUND_ROWS)){
};
发现插入的内容:
atuo_increment类型的列,它由mysql自动分配ID。
LAST_INSERT_ID()会发现每个用户对最后分配的值进行跟踪。
实验:提取由AUTO_INCREMENT生成的ID
MariaDB [foo]> insert into children(fname,age) values('Tom',13);
Query OK, 1 row affected (0.00 sec)
MariaDB [foo]> show tables;
+---------------+
| Tables_in_foo |
+---------------+
| children |
+---------------+
1 row in set (0.00 sec)
MariaDB [foo]> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 2 |
+------------------+
1 row in set (0.00 sec)
每次插入一行,MySQL就分配一个新的id值并且跟踪它,使得你可以用LAST_INSERT_ID()来提取它。
实验:在C程序中使用自动分配的ID
程序名字:insert2.c
#include <stdlib.h>
#include <stdio.h>
#include <mysql.h>
int main(int argc,char *argv[]){
MYSQL my_connection;
MYSQL_RES *res_ptr;
MYSQL_ROW sqlrow;
int res;
mysql_init(&my_connection);
if(mysql_real_connect(&my_connection,"localhost","rick","123456","foo",0,NULL,0)){
printf("Connection success
");
res=mysql_query(&my_connection,"insert into children(fname,age) values('Robert',7)");
if(!res){
printf("Inserted %lu rows
",(unsigned long)mysql_affected_rows(&my_connection));
}
else{
fprintf(stderr,"Insert error %d: %s
",mysql_errno(&my_connection),mysql_error(&my_connection));
}
res=mysql_query(&my_connection,"select last_insert_id()");
if(res){
printf("select error: %s
",mysql_error(&my_connection));
}
else{
/*
对于成功检索数据的每个查询(SELECT、SHOW、DESCRIBE、EXPLAIN),必须调用mysql_store_result()或
mysql_use_result()。mysql_use_result()将初始化结果集检索,但并不像mysql_store_result()那样将结果集实际
读取到客户端。它必须通过对mysql_fetch_row()的调用,对每一行分别进行检索
*/
//MYSQL_RES *mysql_use_result(MYSQL *mysql)
res_ptr=mysql_use_result(&my_connection);
if(res_ptr){
//array mysql_fetch_row(int result)
//获取查询结果集,其区别在于函数的返回值不是一个字符串,而是一个数组
while((sqlrow=mysql_fetch_row(res_ptr))){
printf("We inserted childno %s
",sqlrow[0]);
}
//void mysql_free_result() 函数释放结果内存。
mysql_free_result(res_ptr);
}
}
mysql_close(&my_connection);
}
else{
fprintf(stderr,"Connection failed
");
if(mysql_errno(&my_connection)){
fprintf(stderr,"Connection error %d: %s
",
mysql_errno(&my_connection),mysql_error(&my_connection));
}
}
return EXIT_SUCCESS;
}
下面是编译:
1、gcc -I/usr/include/mysql connect1.c -L/usr/lib/mysql -L/usr/lib64/mysql -lmysqlclient -o connect1
我的是这种
2、gcc -I/usr/include/mysql connect1.c -L/usr/lib/mysql -lmysqlclient -o connect1
返回数据的语句:
你可以使用mysql_query来发送SQL语句,然后,你使用mysql_store_result或者mysql_use_result提取数据。
接着,你将使用一些mysql_fetch_row调用来处理数据。
最后,使用mysql_free_result释放查询占用的内存资源。
mysql_use_result和mysql_store_result的区别主要在于,你想一次返回一行数据,还是一次返回所有的结果。
1、一次提取所有数据的函数
MYSQL_RES *mysql_store_result(MYSQL *connection);
调用mysql_num_rows来得到返回记录的数据,我们希望这是个正数,但是如果没有返回行,这个值将是0:
my_ulonglong mysql_num_rows(MYSQL_RES *result);
a.mysql_fetch_row:这个函数从使用mysql_store_result得到的结构结构中提取一行,并把它放到一个行结构中。当数据用完或者
发生错误时返回NULL
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
b.mysql_data_seek:这个函数用来在结果集中进行跳转,设置将会被下一个mysql_fetch_row操作返回的行。参数offset的值是一个行号,
它必须在0到结果集总行数减1的范围内。传递0将会导致下一个mysql_fetch_row调用返回结果集中的第一行。
void mysql_data_seek(MYSQL_RES *result,my_ulonglong offset);
c.mysql_row_tell:这个函数返回一个偏移量,它用来表示结果集中的当前位置。
MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES *result);
d.但是,你可以这样使用它的返回值:
MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES *result,MYSQL_ROW_OFFSET offset);
e.完成了对数据的所有操作后,你必须明确的调用mysql_free_result来让MYSQL库完成善后处理:
void mysql_free_result(MYSQL_RES *result);
提取数据试验:
#include <stdlib.h>
#include <stdio.h>
#include <mysql.h>
MYSQL my_connection;
MYSQL_RES *res_ptr;
MYSQL_ROW sqlrow;
int main(int argc,char *argv[]){
int res;
mysql_init(&my_connection);
if(mysql_real_connect(&my_connection,"localhost","rick","123456","foo",0,NULL,0)){
printf("Connection success
");
res=mysql_query(&my_connection,"select childno,fname,age from children where age>5");
if(res){
printf("select error: %s
",mysql_error(&my_connection));
}
else{
res_ptr=mysql_store_result(&my_connection);
if(res_ptr){
printf("Retrieved %lu rows
",(unsigned long)mysql_num_rows(res_ptr));
while(sqlrow=mysql_fetch_row(res_ptr)){
printf("Fetched data...
");
}
if(mysql_errno(&my_connection)){
fprintf(stderr,"Retrive error: %s
",mysql_error(&my_connection));
}
mysql_free_result(res_ptr);
}
}
mysql_close(&my_connection);
}
else
{
fprintf(stderr,"Connection failed
");
if(mysql_errno(&my_connection)){
fprintf(stderr,"Connection error %d: %s
",
mysql_errno(&my_connection),mysql_error(&my_connection));
}
}
return EXIT_SUCCESS;
}
编译:
gcc -I/usr/include/mysql insert3.c -L/usr/lib/mysql -L/usr/lib64/mysql -L/usr/lib/mysql -lmysqlclient -o insert3
一次提取一行数据:
MYSQL_RES *mysql_use_result(MYSQL *connection);
处理返回的数据:
mysql_field_count函数提供了一些关于查询结果的基本信息。它接受连接对象,并返回结果集中的字段数目:
unsigned int mysql_field_count(MYSQL *connection);
下面是简单的打印数据的代码:
void display_row(){
unsigned int field_count;
field_count=0;
while(field_count<mysql_field_count(&my_connection)){
printf("%s ",sqlrow(field_count));
field_count++;
}
printf("
");
}
使用mysql_fetch_field()来同时将元数据和数据提取到一个新的结构中:
MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result);
#include <stdlib.h>
#include <stdio.h>
#include <mysql.h>
MYSQL my_connection;
MYSQL_RES *res_ptr;
MYSQL_ROW sqlrow;
void display_header();
void display_row();
int main(int argc, char *argv[]) {
int res;
int first_row = 1; /* Used to ensure we display the row header exactly once when data is successfully retrieved */
mysql_init(&my_connection);
if (mysql_real_connect(&my_connection, "localhost", "rick",
"123456", "foo", 0, NULL, 0)) {
printf("Connection success
");
res = mysql_query(&my_connection, "SELECT childno, fname, age FROM children WHERE age > 5");
if (res) {
fprintf(stderr, "SELECT error: %s
", mysql_error(&my_connection));
} else {
res_ptr = mysql_use_result(&my_connection);
if (res_ptr) {
while ((sqlrow = mysql_fetch_row(res_ptr))) {
if (first_row) {
display_header();
first_row = 0;
}
display_row();
}
if (mysql_errno(&my_connection)) {
fprintf(stderr, "Retrive error: %s
",
mysql_error(&my_connection));
}
mysql_free_result(res_ptr);
}
}
mysql_close(&my_connection);
} else {
fprintf(stderr, "Connection failed
");
if (mysql_errno(&my_connection)) {
fprintf(stderr, "Connection error %d: %s
",
mysql_errno(&my_connection),
mysql_error(&my_connection));
}
}
return EXIT_SUCCESS;
}
void display_header() {
MYSQL_FIELD *field_ptr;
printf("Column details:
");
while ((field_ptr = mysql_fetch_field(res_ptr)) != NULL) {
printf(" Name: %s
", field_ptr->name);
printf(" Type: ");
if (IS_NUM(field_ptr->type)) {
printf("Numeric field
");
} else {
switch(field_ptr->type) {
case FIELD_TYPE_VAR_STRING:
printf("VARCHAR
");
break;
case FIELD_TYPE_LONG:
printf("LONG
");
break;
default:
printf("Type is %d, check in mysql_com.h
", field_ptr->type);
} /* switch */
} /* else */
printf(" Max width %ld
", field_ptr->length); /* Note on versions of MySQL before 4.0 the format should be %d, rather than %ld */
if (field_ptr->flags & AUTO_INCREMENT_FLAG)
printf(" Auto increments
");
printf("
");
} /* while */
}
void display_row() {
unsigned int field_count;
field_count = 0;
while (field_count < mysql_field_count(&my_connection)) {
if (sqlrow[field_count]) printf("%s ", sqlrow[field_count]);
else printf("NULL");
field_count++;
}
printf("
");
}
更多的函数:
char *mysql_get_client_info(void) 返回客户端使用的库的版本信息
char *mysql_get_host_info(MYSQL *connection) 返回服务器连接信息
char *mysql_get_server_info(MYSQL *connection) 返回当前连接的服务器的信息
char *mysql_info(MYSQL *connection); 返回最近执行的查询的信息,但是仅仅只对一些查询类型有效,通常是insert和updata
int mysql_select_db(MYSQL *connection,const char *dbname)如果用户拥有合适的权限,则把默认数据库改成参数指定的数据库,成功返回0
int mysql_shutdown(MYSQL *connection,enum mysql_enum_shutdown_level); 如果用户拥有合适的权限,则关闭连接的数据库服务器。目前关闭级别必须被设置为SHUTDOWN_DEFAULT.成功时返回0