打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Linux下C语言学习笔记—操作MySQL

MySQL是一个真正的多用户、多线程SQL数据库服务器。SQL(结构化查询语言)是世界上最流行的和标准化的数据库语言。MySQL是以一个客户机/服务器结构的实现,它由一个服务器守护程序mysqld和很多不同的客户程序和库组成。

SQL是一种标准化的语言,它使得存储、更新和存取信息更容易。例如,你能用SQL语言为一个网站检索产品信息及存储顾客信息,同时MySQL也足够快和灵活以允许你存储记录文件和图像。

MySQL 主要目标是快速、健壮和易用。最初是因为我们需要这样一个SQL服务器,它能处理与任何可不昂贵硬件平台上提供数据库的厂家在一个数量级上的大型数据库,但速度更快,MySQL就开发出来。自1996年以来,我们一直都在使用MySQL,其环境有超过 40 个数据库,包含 10,000个表,其中500多个表超过7百万行,这大约有100 个吉字节(GB)的关键应用数据。

MySQL建立的基础是业已用在高要求的生产环境多年的一套实用例程。尽管MySQL仍在开发中,但它已经提供一个丰富和极其有用的功能集。

MySQL的官方发音是“My Ess Que Ell”(不是 MY-SEQUEL )。

下表描述MySQL一些重要的特征:

  • 使用核心线程的完全多线程。这意味着它能很容易地利用多CPU(如果有)。
  • C 、C++、 Eiffel 、 Java、 Perl、 PHP、Python、和 TCL  API。见20 MySQL 客户工具和 API
  • 可运行在不同的平台上,见4.2 MySQL支持的操作系统
  • 多种列类型:1、 2、 3、4、和 8 字节长度的有符号/无符号整数、FLOATDOUBLECHARVARCHARTEXTBLOBDATETIMEDATETIME、TIMESTAMPYEARSETENUM类型。 见7.3 列类型
  • 利用一个优化的一遍扫描多重联结(one-sweep multi-join)非常快速地进行联结(join)。
  • 在查询的SELECTWHERE部分支持全部运算符和函数,例如:
    mysql> SELECT CONCAT(first_name, " ", last_name) FROM tbl_name
    WHERE income/dependents > 10000 AND age > 30;
  • 通过一个高度优化的类库实现SQL函数库并且像他们能达到的一样快速,通常在查询初始化后不应该有任何内存分配。
  • 全面支持SQL的GROUP BYORDER BY子句,支持聚合函数( COUNT()COUNT(DISTINCT)AVG()STD()SUM()MAX()MIN() )。
  • 支持ANSI SQL的LEFT OUTER JOIN和ODBC语法
  • 你可以在同一查询中混用来自不同数据库的表。(与版本 3.22一样 )。
  • 一个非常灵活且安全的权限和口令系统,并且它允许基于主机的认证。口令是安全的,因为当与一个服务器连接时,所有的口令传送被加密。
  • ODBC for Windiws 95。所有的 ODBC 2 . 5 函数和其他许多函数。例如,你可以用Access连接你的 MySQL服务器。见16 MySQL  ODBC 支持
  • 具备索引压缩的快速B树磁盘表。
  • 每个表允许有16个索引。每个索引可以由1~16个列或列的一部分组成。最大索引长度是 256 个字节(在编译MySQL时,它可以改变)。一个索引可以使用一个CHARVARCHAR字段的前缀。
  • 定长和变长记录。
  • 用作临时表的内存散列表。
  • 大数据库处理。我们正在对某些包含 50,000,000 个记录的数据库使用MySQL
  • 所有列都有缺省值,你可以用INSERT插入一个表列的子集,那些没用明确给定值的列设置为他们的缺省值。
  • 为了可移植性使用 GNU  Automake , Autoconf 和libtool。
  • 用C和C++编写,并用大量不同的编译器测试。
  • 一个非常快速的基于线程的内存分配系统。
  • 没有内存漏洞。用一个商用内存漏洞监测程序测试过(purify)。
  • 包括myisamchk,一个检查、优化和修复数据库表的快速实用程序,详见13 维护 MySQL安装
  • 全面支持ISO-8859-1  Latin1 字符集。例如,斯堪的纳维亚的字符 @ringaccent{a}, @"a and @"o 在表和列名字被允许。
  • 所有数据以 ISO-8859-1  Latin1 格式保存。所有正常的字符串比较是忽略大小写的。
  • 根据 ISO-8859-1  Latin1 字符集进行排序(目前瑞典语的方式)。通过在源代码中增加排序顺序数组可以改变它。为了理解一个更高级的排序例子,看一看捷克语的排序代码。MySQL支持可在编译时指定的很多不同的字符集。
  • 表和列的别名符合 SQL92 标准。
  • DELETEINSERTREPLACEUPDATE 返回有多少行被改变(受影响)。
  • 函数名不会与表或列名冲突。例如ABS是一个有效的列名字。对函数调用的唯一限制是函数名与随后的“(”不能有空格。详见7.31 MySQL对保留字很挑剔吗?
  • 所有MySQL程序可以用选项--help-?获得联机帮助。
  • 服务器能为客户提供多种语言的出错消息,详见9.1 MySQL支持哪些语言?
  • 客户端使用TCP/IP 连接或Unix套接字(socket)或NT下的命名管道连接MySQL
  • MySQL特有的SHOW命令可用来检索数据库、表和索引的信息,EXPLAIN命令可用来确定优化器如何解决一个查询。


1,使用c语言操作mysql之前,先在mysql里头创建一个数据库,一个表,在表里头添加数据如下:

创建数据库,库名为cusemysql:
mysql>create database cusemysql;
创建表,表名为:
mysql>use cusemysql;
mysql>create table children(childno int not null unique,fname varchar(20),age int);
添加一点数据哦:
mysql>insert into children values(5,"花儿",10);
对拉,为了方便起见,把表的大致样子给大家看看


childno         fname       age
1                小星      9
2                大量      15



2 ,下面进行具体的操作

插入:insert    

好的,我们现编辑一段c代码,取名为insert.c

///////////////////////////////////
/*  insert.c */
#include <stdio.h>
#include <stdlib.h>
#include "/usr/local/mysql/include/mysql/mysql.h" 
/*注意哦,上面必须是mysql.h的绝对地址,一般在mysql下的include目录下,仔细看看你的在哪里?*/

int main(int argc, char *argv[])
{
MYSQL my_connection;

int res;

mysql_init(&my_connection);

/*mysql_real_connect(&mysql,host,user,passwd,dbname,0,NULL,0) == NULL)*/
if (mysql_real_connect(&my_connection, "localhost", "root", "","cusemysql",0,NULL,CLIENT_FOUND_ROWS))
{
    printf("Connection success\n");
    res = mysql_query(&my_connection, "insert into children values(10,'Ann',5)");

    if (!res)
    {
        printf("Inserted %lu rows\n",(unsigned long)mysql_affected_rows(&my_connection));
/*里头的函数返回受表中影响的行数*/
    }
    else
    {
    //分别打印出错误代码及详细信息
        fprintf(stderr, "Insert error %d: %s\n",mysql_errno(&my_connection),mysql_error(&my_connection));
    }
    mysql_close(&my_connection);
}

else
{
    fprintf(stderr, "Connection failed\n");

    if (mysql_errno(&my_connection))
    {
        fprintf(stderr, "Connection error %d: %s\n",mysql_errno(&my_connection),mysql_error(&my_connection));
        }
}
    return EXIT_SUCCESS;
}
/////////////////////////////////////////////
代码写完了,要编译哦
#gcc -o insert insert.c -L /usr/local/mysql/lib/mysql/*.a -lz
ok,现在我们执行看看
#./insert
Connection Success
Inserted 1 rows

year,果然可以,呵呵
不信到mysql下看看表children中是否多了刚才插入的那一行数据

注:也许你会问上面gcc的命令参数是什么意思阿,其实,我也不太清楚,呵呵
大概是要把mysql下的某个特定库包含进来,可是我不知道具体是个什么库,所以用*.a全部包含进来拉
其实只要包含mysqlclient.a就可以,你试试看


更新:update

我们只要把上面的代码中的

res = mysql_query(&my_connection, "insert into children values(10,'Ann',5)");

换成

res = mysql_query(&my_connection, "update children set age=20 where childno<5 ");

即可
上面语句实现的功能是,把编号小于5的所有孩子的年龄全部改成20岁



检索:select

看代码之前,最好是先看蓝色字体的部分[介绍了代码中用到的一些函数的作用]
//////////////////////////////////////////////////
/*  select.c */

#include <stdio.h>
#include <stdlib.h>
#include "/usr/local/mysql/include/mysql/mysql.h"

int main(int argc, char *argv[])
{
MYSQL my_connection;
MYSQL_RES *res_ptr;
MYSQL_ROW sqlrow;

int res;

mysql_init(&my_connection);

/*mysql_real_connect(&mysql,host,user,passwd,dbname,0,NULL,0) == NULL)*/
if (mysql_real_connect(&my_connection, "localhost", "root", "","cusemysql",0,NULL,CLIENT_FOUND_ROWS))
{
    printf("Connection success\n");
    res = mysql_query(&my_connection, "select childno,fname,age from  children where age<20");

    if (res)
    {
        printf("SELECT error:%s\n",mysql_error(&my_connection));
    }
    else
    {
       res_ptr=mysql_store_result(&my_connection);
       if(res_ptr)
       {
              printf("Retrieved %lu Rows\n",(unsigned long)mysql_num_rows(res_ptr));
              while((sqlrow=mysql_fetch_row(res_ptr)))
              {
                     printf("Fetched data...\n");
              }
              if (mysql_errno(&my_connection))
              {
                     fprintf(stderr,"Retrive error:%s\n",mysql_error(&my_connection));
              }
       }
       mysql_free_result(res_ptr);
       }
    mysql_close(&my_connection);
}

else
{
    fprintf(stderr, "Connection failed\n");

    if (mysql_errno(&my_connection))
    {
        fprintf(stderr, "Connection error %d: %s\n",
        mysql_errno(&my_connection),
        mysql_error(&my_connection));
        }
}
    return EXIT_SUCCESS;
}
//////////////////////////////////////////////////
面语句实现的功能是:检索出年龄小于20岁的小孩的信息,不过没有对信息进行任何处理哦
下次我们对数据进行一定的处理

这里介绍上面用到的几个函数:

可以从SELECT语句(或其他返回数据的语句)中检索完所有数据,在单一调用中,使用mysql_store_result:

MYSQL_RES *mysql_store_result(MYSQL *connection);

必须在mysql_query检索数据后才能调用这个函数,以在结果集中存储该数据。这个函数从服务器中检索所有数据并立即将它存储在客户机中。它返回一个指向以前我们从未遇到过的结构(结果集结构)的指针。如果语句失败,则返回NULL。

使用等价的PostgreSQL时,应该知道返回NULL意味着已经发生了错误,并且这与未检索到数据的情况不同。即使,返回值不是NULL,也不意味着当前有数据要处理。

如果未返回NULL,则可以调用mysql_num_rows并且检索实际返回的行数,它当然可能是0。

my_ulonglong mysql_num_rows(MYSQL_RES *result);

它从mysql_store_result取得返回的结果结构,并且在该结果集中返回行数,行数可能为0。如果mysql_store_result成功,则mysql_num_rows也总是成功的。

这种mysql_store_result和mysql_num_rows的组合是检索数据的一种简便并且直接的方法。一旦 mysql_store_result成功返回,则所有查询数据都已经存储在客户机上并且我们知道可以从结果结构中检索它,而不用担心会发生数据库或网络错误,因为对于程序所有数据都是本地的。还可以立即发现返回的行数,它可以使编码更简便。如前所述,它将所有结果立即地发送回客户机。对于大结果集,它可能耗费大量的服务器、网络和客户机资源。由于这些原因,使用更大的数据集时,最好仅检索需要的数据。不久,我们将讨论如何使用 mysql_use_result函数来完成该操作。

一旦检索了数据,则可以使用mysql_fetch_row来检索它,并且使用mysql_data_seek、mysql_row_seek、mysql_row_tell操作结果集。在开始检索数据阶段之前,让我们先讨论一下这些函数。

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);

这个函数采用从存储结果中获取的结果结构,并且从中检索单一行,在行结构中返回分配给您的数据。当没有更多数据或者发生错误时,返回NULL。稍后,我们将回来处理这一行中的数据。

void mysql_data_seek(MYSQL_RES *result, my_ulonglong offset);

这个函数允许您进入结果集,设置将由下一个获取操作返回的行。offset是行号,它必须在从0到结果集中的行数减 1 的范围内。传递0将导致在下一次调用mysql_fetch_row时返回第一行。

MYSQL_ROW_OFFEST mysql_row_tell(MYSQL_RES *result);

这个函数返回一个偏移值,它表示结果集中的当前位置。它不是行号,不能将它用于mysql_data_seek。但是,可将它用于:

MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET offset);

它移动结果集中的当前位置,并返回以前的位置。

有时,这一对函数对于在结果集中的已知点之间跳转很有用。请注意,不要将row tell和row seek使用的偏移值与data_seek使用的行号混淆。这些是不可交换的,结果将是您所希望看到的。

void mysql_free_result(MYSQL_RES *result);

完成结果集时, 必须总是调用这个函数,以允许MySQL库整理分配给它的对象。



检索并处理[比较全面哦,呵呵]:select    

下面是详细的代码:
//////////////////
/*  select1.c */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "/usr/local/mysql/include/mysql/mysql.h"
 
int main(int argc, char *argv[])
{
MYSQL my_connection;
MYSQL_RES *res_ptr;   /*指向检索的结果存放地址的指针*/
MYSQL_ROW sqlrow;     /*返回的记录信息*/
MYSQL_FIELD *fd;      /*字段结构指针*/
char aszflds[25][25]; /*用来存放各字段名*/
int res;             /*执行查询操作后的返回标志*/
int i,j,k;

mysql_init(&my_connection);

/*mysql_real_connect(&mysql,host,user,passwd,dbname,0,NULL,0) == NULL)*/
if (mysql_real_connect(&my_connection, "localhost", "root", "","cusemysql",0,NULL,CLIENT_FOUND_ROWS))
{
    printf("Connection success\n");
    res = mysql_query(&my_connection, "select childno,fname,age from children where age<20");

    if (res)
    {
        printf("SELECT error:%s\n",mysql_error(&my_connection));
    }
    else
    {
       res_ptr=mysql_store_result(&my_connection);
       if(res_ptr)
       {
              printf("Retrieved %lu Rows\n",(unsigned long)mysql_num_rows(res_ptr));
              /*取得各字段名*/
              for(i=0;fd=mysql_fetch_field(res_ptr);i++)
                     strcpy(aszflds[i],fd->name);
              /*输出各条记录*/
              printf("下面是检索出的各条记录信息:\n");
              j=mysql_num_fields(res_ptr);
              for(i=0;i<j;i++)
              printf("%s\t",aszflds[i]);
              printf("\n");
              while((sqlrow=mysql_fetch_row(res_ptr)))
              {
                     for(i=0;i<j;i++)
                     printf("%s\t",sqlrow[i]);
                     printf("\n");
              }
              if (mysql_errno(&my_connection))
              {
                     fprintf(stderr,"Retrive error:s\n",mysql_error(&my_connection));
              }
       }
       mysql_free_result(res_ptr);
       }
    mysql_close(&my_connection);
}

else
{
    fprintf(stderr, "Connection failed\n");

    if (mysql_errno(&my_connection))
    {
        fprintf(stderr, "Connection error %d: %s\n",
        mysql_errno(&my_connection),
        mysql_error(&my_connection));
        }
}
    return EXIT_SUCCESS;
}
//////////////////////////////////////
主要要注意的几个地方是:
1,mysql.h的路径,必须确定它的绝对路径哦(这句话是错误的,只要在编译是把对应库编译进去即可,具体操作方法请查询本博客)
2,注意你的数据库的用户名和密码是否正确
3,在编译的时候必须包含这个库文件mysqlclient.a[记不太清楚,不过你可以直接包含它所在的目录下的所有库,肯定就没有问题,

各方意见:
一.
编译方法有点不规范。

正确的应该是这样:

1.在程序开头包含头文件应这样写:
#include <mysql.h>

2.编译应这样写:

$ gcc -o mysql mysql.c `mysql_config --cflags --libs`

有很多朋友虽然安装好了mysql但却不知如何使用它。在这篇文章中我们就从连接MYSQL、修改密码、增加用户等方面来学习一些MYSQL的常用命令。  
一、连接MYSQL。  
格式: mysql -h主机地址 -u用户名 -p用户密码  
1、例1:连接到本机上的MYSQL。  
首先在打开DOS窗口,然后进入目录 mysqlbin,再键入命令mysql -uroot -p,回车后提示你输密码,如果刚安装好MYSQL,超级用户root是没有密码的,故直接回车即可进入到MYSQL中了,MYSQL的提示符是:mysql>  
2、例2:连接到远程主机上的MYSQL。假设远程主机的IP为:110.110.110.110,用户名为root,密码为abcd123。则键入以下命令:  
mysql -h110.110.110.110 -uroot -pabcd123  
(注:u与root可以不用加空格,其它也一样)  
3、退出MYSQL命令: exit (回车)  
二、修改密码。  
格式:mysqladmin -u用户名 -p旧密码 password 新密码  
1、例1:给root加个密码ab12。首先在DOS下进入目录mysqlbin,然后键入以下命令  
mysqladmin -uroot -password ab12  
注:因为开始时root没有密码,所以-p旧密码一项就可以省略了。  
2、例2:再将root的密码改为djg345。  
mysqladmin -uroot -pab12 password djg345  
三、增加新用户。(注意:和上面不同,下面的因为是MYSQL环境中的命令,所以后面都带一个分号作为命令结束符)  
格式:grant select on 数据库.* to 用户名@登录主机 identified by "密码"  
例1、增加一个用户test1密码为abc,让他可以在任何主机上登录,并对所有数据库有查询、插入、修改、删除的权限。首先用以root用户连入MYSQL,然后键入以下命令:  
grant select,insert,update,delete on *.* to test1@"%" Identified by "abc";  
但例1增加的用户是十分危险的,你想如某个人知道test1的密码,那么他就可以在internet上的任何一台电脑上登录你的mysql数据库并对你的数据可以为所欲为了,解决办法见例2。  
例2、增加一个用户test2密码为abc,让他只可以在localhost上登录,并可以对数据库mydb进行查询、插入、修改、删除的操作(localhost指本地主机,即MYSQL数据库所在的那台主机),这样用户即使用知道test2的密码,他也无法从internet上直接访问数据库,只能通过MYSQL主机上的web页来访问了。  
grant select,insert,update,delete on mydb.* to test2@localhost identified by "abc";  
如果你不想test2有密码,可以再打一个命令将密码消掉。  
grant select,insert,update,delete on mydb.* to test2@localhost identified by "";  


(下篇)  
在上篇我们讲了登录、增加用户、密码更改等问题。下篇我们来看看MYSQL中有关数据库方面的操作。注意:你必须首先登录到MYSQL中,以下操作都是在MYSQL的提示符下进行的,而且每个命令以分号结束。  

一、操作技巧  
1、如果你打命令时,回车后发现忘记加分号,你无须重打一遍命令,只要打个分号回车就可以了。也就是说你可以把一个完整的命令分成几行来打,完后用分号作结束标志就OK。  
2、你可以使用光标上下键调出以前的命令。但以前我用过的一个MYSQL旧版本不支持。我现在用的是mysql-3.23.27-beta-win。  

二、显示命令  
1、显示数据库列表。  
show databases;  
刚开始时才两个数据库:mysql和test。mysql库很重要它里面有MYSQL的系统信息,我们改密码和新增用户,实际上就是用这个库进行操作。  
2、显示库中的数据表:  
use mysql; //打开库,学过FOXBASE的一定不会陌生吧  
show tables;  
3、显示数据表的结构:  
describe 表名;  
4、建库:  
create database 库名;  
5、建表:  
use 库名;  
create table 表名 (字段设定列表);  
6、删库和删表:  
drop database 库名;  
drop table 表名;  
7、将表中记录清空:  
delete from 表名;  
8、显示表中的记录:  
select * from 表名;  

三、一个建库和建表以及插入数据的实例  
drop database if exists school; //如果存在SCHOOL则删除  
create database school; //建立库SCHOOL  
use school; //打开库SCHOOL  
create table teacher //建立表TEACHER  
(  
id int(3) auto_increment not null primary key,  
name char(10) not null,  
address varchar(50) default '深圳',  
year date  
); //建表结束  
//以下为插入字段  
insert into teacher values('','glchengang','深圳一中','1976-10-10');  
insert into teacher values('','jack','深圳一中','1975-12-23');  

注:在建表中(1)将ID设为长度为3的数字字段:int(3)并让它每个记录自动加一:auto_increment并不能为空:not null而且让他成为主字段primary key(2)将NAME设为长度为10的字符字段(3)将ADDRESS设为长度50的字符字段,而且缺省值为深圳。 varchar和char有什么区别呢,只有等以后的文章再说了。 (4)将YEAR设为日期字段。  
如果你在mysql提示符键入上面的命令也可以,但不方便调试。你可以将以上命令原样写入一个文本文件中假设为school.sql,然后复制到c:下,并在DOS状态进入目录mysqlbin,然后键入以下命令:  
mysql -uroot -p密码 < c:school.sql 
如果成功,空出一行无任何显示;如有错误,会有提示。(以上命令已经调试,你只要将//的注释去掉即可使用)。 

四、将文本数据转到数据库中 
1、文本数据应符合的格式:字段数据之间用tab键隔开,null值用n来代替. 
例: 
3 rose 深圳二中 1976-10-10 
4 mike 深圳一中 1975-12-23 
2、数据传入命令 load data local infile "文件名" into table 表名; 
注意:你最好将文件复制到mysqlbin目录下,并且要先用use命令打表所在的库 。 

五、备份数据库:(命令在DOS的mysqlbin目录下执行) 
mysqldump --opt school>school.bbb  
注释:将数据库school备份到school.bbb文件,school.bbb是一个文本文件,文件名任取,打开看看你会有新发现。  

后记:其实MYSQL的对数据库的操作与其它的SQL类数据库大同小异,您最好找本将SQL的书看看。我在这里只介绍一些基本的,其实我也就只懂这些了,呵呵。最好的MYSQL教程还是“晏子“译的“MYSQL中文参考手册“不仅免费每个相关网站都有下载,而且它是最权威的。可惜不是象"PHP4中文手册" 那样是chm的格式,在查找函数命令的时候不太方便。 


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
windows c语言连接mysql数据库的实现方法
串口编程中使用MScommd的注意事项
使用C语言访问MySQL数据 —— 执行SQL语句(2)
C语言链接数据库
PHP 数据库
《PHP+MySQL动态网站开发实例教程》第8章 PHP操作MySQL数据库
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服