数据库之MySQL的介绍与使用20180703

/*******************************************************************************************/

一、mysql的安装

0.下载

MySQL数据库版本相对比较繁杂。常见的有:Community社区版、Enterprise企业版。

Community版是开源免费的,这也是我们通常用的MySQL的版本。可以满足绝大多数用户需求。

Enterprise版,官方指出提供30天免费试用期。可进一步划分为MySQL标准版、MySQL企业版、MySQL集群版。官方提供付费服务。

其中Community Server 可以直接从mysql 的官网下载。但Enterprice Edition只能从Oracle edelivery上下载,而Edelivery有时会屏蔽中国IP。

MySQL各版本区别参见:

http://www.admin10000.com/Document/62.html

下载mysql时注意区分版本细节及所应用的系统平台:linux(32/64) 、win(32/64)

举例:MySQL Community Server 5.6.20 win版本

GA 是指软件的通用版本,一般指正式发布的版本 (Generally Available (GA) Release)

mysql-essential-5.1.60-win32.msi          是精简版,如果只需要mysql服务,就选择此版本。

mysql-5.1.60-win32.msi                            是完整版,包含安装程序和配置向导,有MySQL文档。

mysql-noinstall-5.1.60-win32.zip 是非安装的zip压缩包,没有自动安装程序和配置向导,无安装向导

mysql-5.1.60.zip 是用于windows的Mysql源码压缩包

linux版本

在http://www.mysql.com/downloads/网站上下载不了

在 www.oracle.com/downloads 找mysql 注册用户, 选择操作系统平台和mysql版本 进行下载

官方文档上有关MySQL安装,介绍了3种类型及其对应安装方式来安装MySQL数据库:

  Linux supports anumber of different solutions for installing MySQL. The recommended method isto use one of the distributions from Oracle. If you choose this method, thereare three options available:

(1)  Installingfrom a generic binary package in .tar.gz format. See Section 2.2,“Installing MySQL from Generic Binaries on Unix/Linux” for moreinformation.

(2)    Extractingand compiling MySQL from a source distribution. For detailed instructions,see Section 2.9, “InstallingMySQL from Source”.

(3)    Installingusing a pre-compiled RPM package. For more information on using the RPMsolution, see Section 2.5.1,“Installing MySQL from RPM Packages on Linux”

我们选用较简单的RPM 包来安装

1.查询

查询服务器上已经安装的mysql

在终端提示符输入:rpm -aq | grep MySQL 命令

2.卸载

rpm -e 软件包名--nodeps --allmatches (不理会依赖关系,删除所有上一步查出来的相同的mysql)

3.安装

解压.zip安装包

unzip V46610-01-MySQL Database 5.6.20 RPM for Oracle Linux  RHEL 6 x86 (64bit).zip

安装如下软件包:

MySQL-client-advanced-5.6.20-1.el6.x86_64.rpm

MySQL-devel-advanced-5.6.20-1.el6.x86_64.rpm

MySQL-server-advanced-5.6.20-1.el6.x86_64.rpm

--#表示需要在root下执行

#rpm -ivh MySQL-server-advanced-5.6.****-1.el6.x86_64.rpm

mysql安装的时候自动初始化一个root用户(mysql数据库用户,不是操作系统用户)

用户名密码在在root目录下,通过cat目录下的 .mysql_secret文件可查看当前的密码

[[email protected] oracle]# cat /root/.mysql_secret

#rpm -ivh MySQL-client-advanced-5.6.****-1.el6.x86_64.rpm

说明:不安装mysql-client是不能使用mysql工具登陆到mysql数据库

其他软件包选择性安装,这个是开发需要安装的,如果没有安装则没有库文件以及头文件,无法进行编程:

#rpm -ivh MySQL-devel-advanced-5.6.20-1.el6.x86_64.rpm

4.修改密码

一般自己安装之后要修改密码.

--登陆

mysql -uroot -p123456

改密码,在登录后的情况下

set password=password(‘123‘);

具体安装可以参考《Redhat下安装mysql 5.6.20.docx》

5.ubuntu下安装mysql.txt

1). sudo apt-get install mysql-server

2). sudo apt-get isntall mysql-client

3). sudo apt-get install libmysqlclient-dev

提示:安装过程中会提示设置密码什么的,注意设置了不要忘了,安装完成之后可以使用如下命令来检查是否安装成功:

6.远程连接模式说明

vmvare 网卡

桥接模式 : 物理机 和虚拟机 同一网段

NAT模式 : VMNET8 与 虚拟机 同一网段

主机模式: VMNET1 与 虚拟机 同一网段。仅限于自己能连,别人连不了

/*******************************************************************************************/

二、mysql的简介

mysql 是瑞典 mysqlAB公司 ,后来被sun收购,之后被oracle 收购.

社区版和企业版

开源的 ,免费的

mysql体系结构,

mysql首先是用户,然后接下来是数据库,最后才是表。

所以学习从库开始,

先库的增删改查,然后表的增删改查,最后是数据的增删改查,

由于mysql比较小,不像oracle那么大 有个dba来操作数据库,所以mysql需要都得会

具体见图《mysql体系结构与oracle体系结构的不同.png》:

/*******************************************************************************************/

三、mysql库的操作

1.mysql启动不了的时候使用:

1).先杀掉进程 mysqld,没有这个进程,则无法登录

2).重启mysql服务

[[email protected] oracle]# service mysql restart

2.库的增删改查

1).查看当前有的数据库

mysql> show databases;

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

| Database           |

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

| information_schema |

| mysql              |

| performance_schema |

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

这三个是mysql自带的,这三个不能删,删了会有问题

2).创建一个yekai的数据库

create database yekai;

3).查看yekai数据库是怎么创建的,查看数据库(创建的相关)信息

mysql> show create database yekai;

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

| Database | Create Database |

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

| yekai | CREATE DATABASE `yekai` /*!40100 DEFAULT CHARACTERSET latin1 */ |

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

1 row in set (0.00 sec)

4).创建了utf8字符集的数据库,这样可以支持中文

create database mydb1 character set utf8;

5).将数据库的字符集修改为utf8

alter database yekai character set utf8;

6).删除yekai这个数据库

drop database yekai;

7).创建一个utf8的数据库并对输入数据进行校对 ,创建数据库 对数据库存入的数据按照utf8格式进行一个检查

create database mydb3 character set utf8 collate utf8_general_ci;

后续操作这个数据库的时候就会检查是否是utf8格式的。

/*******************************************************************************************/

四、mysql表的管理

表的管理:增删改查

1.表的增加

我们要创建表先要选择数据库

--先选取库

use mydb1 //这个指令不需要敲分号,其他的都要敲

--再创建表,由于mysql的数据类型与oracle的不一样,所以列名后面的数据类型要用mysql自己的,相对于oracle要做修改

create table t1(id int,name varchar(30));

//具体数据类型的说明,以及数据类型表示的说明,

timeStamp: 时间戳,自动赋值为当前日期时间

注意,mysql中的数据类型:

具体见图1:

2.表的修改

--修改表的属性,可以加column关键字,oracle不能加

--增加email列

alter table t1 add email varchar(30);

--增加sal列

alter table t1 add column sal float;

--修改列属性,可以加column关键字,oracle不能加

alter table t1 modify email varchar(40);

--change可以修改列名和列的属性,如下是把列名email改为 address,并修改数据类型为varchar(20)

alter table t1 change column email address varchar(20);

desc t1;//查看表结构。

--删除列

alter table t1 drop column address;

--重命名表需要有table关键字,oracle则不需要

rename table t1 to t2;

create table t1 as select * from t2;

3.表的查看

--查看当前库下有哪些表,代替了oracle中的select * from tab;

show tables;

--查看表的创建方式:

show create table t1;

具体见图2:

其中,ENGINE(引擎)=InnoDB,

这个引擎是 InnoDB

InnoDB :引擎的一种方式,这种方式支持事务,默认情况下事务不开启(自动提交,这点和oracle不一样).

默认的这种引擎速度比较快。

另外其中列名还有表名加了单引号,表示这个名称是区分大小写的,

mysql> use Mydb1

ERROR 1049 (42000): Unknown database ‘Mydb1‘

库名区分大小写

字段不区分大小写

4.表的删除

--删除表 不支持purge关键字 ,也就是mysql不支持回收站(因为mysql是小数据库)

drop table t1;

清空表:truncate先删除表,再创建个空表

/*******************************************************************************************/

五、mysql数据处理

mysql对数据的增删改查和oracle大致是一样的。

表数据的处理,也就是增删改查

create table employee(id int,

name varchar(20),

sex int,

birthday date,

salary double,

entry_date date,

resume text

);//这里面是空格,不要有tab健,tab键会导致数据错误,缺少行

insert into employee values(1,‘叶开‘,1,‘1983-04-27‘,15000,‘2012-06-24‘,‘一个大牛‘);

insert into employee(id,name,sex,birthday,salary,entry_date,resume) values(2,‘傅红雪‘,1,‘1984-02-22‘,10000,‘2012-07-24‘,‘一个中牛‘);

insert into employee(id,name,sex,birthday,salary,entry_date,resume) values(3,‘陆小佳‘,0,‘1985-08-28‘,7000,‘2012-08-24‘,‘一个小虾‘);

update emploee set resume=‘123‘ where id =3;

delete from emploee where id =3;

事务的处理上不一样,mysql是自动提交的。

/*******************************************************************************************/

六、mysql的函数

1.日期时间函数

MySQL里面时间分为三类:时间、日期、时间戳(含有时分秒的sysdate),具体见图3:

sysdate伪列 mysql不存在,使用now()

即:select now() from dual;

--昨天,今天,明天

select now()-1,now(),now()+1 from dual;//这样类似oracle的做法不对,它把日期变为数字然后加减1了

正确的做法,使用date_add或者date_sub:

mysql> select date_add(now(),interval -1 day),now(),date_add(now(),interval 1 day) from dual;

//interval是关键字,-1 数据是多少,day是数据类型

--明年的今天

mysql> select date_add(now(),interval 1 year) from dual;

--addtime函数增加秒数,注意这个秒数要小于60

mysql> select addtime(now(),10),now() from dual;

--注意这个秒数要小于60,如果要加一分钟,则:

mysql> select addtime(now(),‘0:1:0‘),now() from dual;

2.字符串相关函数

字符串相关函数,具体可见图4:

--concat函数支持多个参数,oracle不支持这么多个,|| 语法mysql保留即不报错,但是mysql中功能不存在

mysql> select concat(‘hello‘,‘world‘,‘111‘),‘hello‘||‘world‘ from dual;

--查看字符集(编码)

mysql> select charset(‘hllo‘),charset(‘叶开‘) from dual;

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

| charset(‘hllo‘) | charset(‘叶开‘)   |

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

| utf8            | utf8              |

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

-- 查看字符串长度,一个汉字三个字节(这时因为格式是utf8),oracle是gbk格式,所以oracle是两个字节

mysql> select length(‘hello中国‘) from dual;

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

| length(‘hello中国‘)   |

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

|                    11 |

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

3.日期转换函数

在MySQL中没有to_date函数,进行日期转换需使用date_format()来代替

1).日期转字符串:

转换函数  yyyy-mm-dd 语法支持,功能没有

mysql> select date_format(‘2013-5-11‘, ‘yyyy-mm-dd‘) from dual;

mysql> select date_format(now(), ‘%Y-%m-%d‘) from dual;

y(没有20只有17)和Y(2017)不一样。

mysql> select date_format(now(), ‘%Y-%c-%d %h:%i:%s‘) from dual;

c(02变成2,会去掉0)和m(02)、M(用英语书写的月份)不一样

2).字符串转日期:

mysql> select str_to_date(‘2013-6-04 05:14:15‘ , ‘%Y-%c-%d %h:%i:%s‘) from dual;

//最好字符串要和格式串一致,即对应起来,当然不一致也能转换

mysql> select str_to_date(‘2013-06-04 05:14:15‘ , ‘%Y-%m-%d %h:%i:%s‘) from dual;

3).格式很像Linux下的date命令,date命令后可以加格式串来得到想要的日期格式:

[[email protected] ~]$ date +‘%y-%m-%d‘

17-02-16

[[email protected] ~]$ date +‘%Y-%m-%d‘

2017-02-16

4.数学相关函数

具体可见图5:

5.group by语法

-- 求各个班英语的平均分

select avg(english),class_id,id from student group by class_id;

//这样在oracle中是不允许的(select后面出现的非主函数的列在group by后面必须出现),但是在mysql中是可以,

这个id是每个分组第一条记录对应的id,但是这样没有意义.

mysql group by语法检查不严格,我们仍然用oracle的要求.

/*******************************************************************************************/

七、多表数据

create database if not exists mydb1 character set utf8;

//if not exists 如果不存在才去执行,这样反复执行这个命令就不会报错

sql文件里面的这些sql语句除了复制粘贴来直接外,可以直接使用

source scott_data.sql

这样来执行。

Oracle中连接方法:

等值连接

不等值连接

外连接

自连接

MySQL 使用SQL99标准的连接查询(JOIN..ON..)

1.内连接

对应于oracle的等值连接

(在mysql中使用edit来书写,其实是用vi打开了,而在oracle中ed就可以了。

edit中书写完毕后,用wq保存,然后再输入;号执行。)

1).求员工号,姓名,月薪,部门名称

--oracle写法

select e.empno,e.ename,e.sal,d.dname

from emp e,dept d

where e.deptno=d.deptno;

--sql99(mysql)写法

select e.empno,e.ename,e.sal,d.dname

from emp e inner join dept d

on e.deptno=d.deptno;

口诀: 1. , --> inner join 2. where ---> on

两种写法在mysql中都能使用

2.外连接

1).求员工总人数,显示部门编号,名称,人数

--oracle写法

select d.deptno,d.dname,count(e.empno)

from emp e , dept d

where e.deptno=d.deptno;

查询结果有问题,这是由于条件不是完全相等,需要用到左外 右外才行,(也有可能是没有group by的原因)

>>>>>>oracle的外连接在mysql中不能使用,如下是oracle的外连接在mysql中不能使用

select d.deptno,d.dname,count(e.empno)

from emp e , dept d

where e.deptno(+)=d.deptno;

--sql99的写法

select d.deptno,d.dname,count(e.empno)

from emp e right outer join dept d

on e.deptno=d.deptno

group by d.deptno,d.dname;

右外连接口诀: 1  , --- > right outer join(即保留join右边的部分,也就是dept d) 2 where --> on

select d.deptno,d.dname,count(e.empno)

from dept d left outer join emp e

on e.deptno=d.deptno

group by d.deptno,d.dname;

左外连接口诀: 1  , --- > left outer join 2 where --> on

左外或者右外的取决条件是 表在(逗号(outer join))的位置,与等号无关

3.自连接(特殊的外连接)

数据都在同一张表,不在同一行

//把emp表分别当成老板表和员工表

员工表的老板是老板表的员工(连接(筛选记录的)条件,(筛选(找出)两张表组合起来的集合中满足(连接)条件的记录)).

--oracle写法(不带外连接)

select concat(e.ename,‘‘‘s boss is ‘,b.ename)

from emp e,emp b

where e.mgr = b.empno;

--sql99的写法

select concat(e.ename,‘‘‘s boss is ‘,b.ename)

from emp e left outer join  emp b

on e.mgr = b.empno;

返回的结果中有一个记录是null,这时因为有一个 b.ename是null,这样字符串连接后也是null

滤空函数:

--nvl(滤空)函数mysql不支持

select concat(e.ename,‘‘‘s boss is ‘,nvl(b.ename,‘himself‘))

from emp e left outer join  emp b

on e.mgr = b.empno;

--nvl(滤空)函数用ifnull替换

select concat(e.ename,‘‘‘s boss is ‘,ifnull(b.ename,‘himself‘))

from emp e left outer join  emp b

on e.mgr = b.empno;

4.满外联接

任一边有值就会显示。

select e.*, d.*

from emp e full outer join dept d

on e.deptno=d.deptno

也可以省略outer关键字

5.交叉连接:

叉集,即笛卡尔集

select e.*, d.*

from emp e cross join dept d

无连接条件

6.inner 和 outer 可以省.

7.

后续实际项目中用的是redhat系统上装数据库

select ‘create synonym‘||TNAME||‘for scott.‘||TNAME from tab where tabtype=‘TABLE‘;//这样可以拿到建所有同义词的语句

序列的作用给表的主键使用,为了避免主键冲突.

nextval  默认加载到内存中 20个.如果没用完就掉电了,由于在内存中记不下来,所以重新上电后是从下一段即40开始

/*******************************************************************************************/

八、mysql的约束

1.约束的定义

*定义主键约束 primary key:       不允许为空,不允许重复

*定义主键自动增长 auto_increment

*定义唯一约束 unique

*定义非空约束 not null

*定义外键约束 constraint ordersid_FK foreign key(ordersid) references orders(id)

*删除主键:alter table tablename drop primary key ;

可以通过SELECT * FROM information_schema.`TABLE_CONSTRAINTS`;查看表的约束

2.与Oracle的区别

mysql的约束与oracle的区别在于没有检查了,即语法支持但是功能没有了

mysql主键不需要序列,只需要自动增长关键字即可

mysql定义外键语法与oracle略有不同。

定义外键约束 constraint ordersid_FK foreign key(ordersid) references orders(id)

//ordersid_FK 别名 ,ordersid  本表里用外键的字段,orders(id) 引用rders表的id字段

3.示例:

mysql> drop table myclass;

mysql> create table myclass(

class_id int primary key auto_increment,

class_name varchar(20) not null,

create_date timestamp);

mysql> insert into myclass(class_id,class_name) values(5,‘5班‘); //即使是auto_increment,只要满足主键的约束也能这样手动增加

mysql> insert into myclass(class_name) values(‘什么班‘); //自动增长的机制是取前面的最大值,然后加1,一开始啥都没有则第一个是1

mysql> create table mystudent(

student_id int primary key auto_increment,

student_name varchar(20) not null,

hiredate timestamp,

class_id int,

constraint stu_classid_FK foreign key(class_id) references myclass(class_id));

//stu_classid_FK 外键约束名,class_id 是外键,依赖于myclass表的class_id(上一个表的主键是这个表的外键(的依赖))

--非空约束

mysql> insert into mystudent(student_name,class_id) values(null,1);

ERROR 1048 (23000): Column ‘student_name‘ cannot be null

--违反外键约束//当前class_id依赖于其他表的主键,即当前的class_id的值 要是其他表的主键中已经存在的

mysql> insert into mystudent(student_name,class_id) values(‘fuhongxue2‘,8);//上一个表的class_id中没有值为8的

--有外键时删除表

-违反外键约束,需要先删除学生,再删除班级

mysql> delete from myclass where class_id=5;

mysql> delete from mystudent where class_id=5;

Query OK, 1 row affected (0.00 sec)

mysql> delete from myclass where class_id=5;

Query OK, 1 row affected (0.01 sec)

/*******************************************************************************************/

九、mysql中文乱码问题

中文乱码问题:要重视

三层因素:

因素1: MySQL自身的设计

【实验步骤1】:

mysql> show variables like ‘character%‘;        查看所有应用的字符集

结果有好几种字符集,具体哪种字符集是属于哪一端的见图《字符集归类.png》:

【实验步骤2】:    指定字符集登录数据库

$ mysql -uroot -p123456 --default_character_set=gbk 指定字符集登录数据库

mysql> show variables like ‘character%‘;

影响了与客户端相关联的 3处 (最外层)

在这种状态下执行use mydb2;

mysql> select * from employee;

查看输出,会出现乱码。

原来的三条数据,是以utf8的形式存储到数据库中,当使用gbk连接以后,数据库仍按照utf8的形式将数据返回,出错。

【实验步骤3】:

在该环境下插入带有中文的一行数据。

mysql> insert into employee(id,name,sex,birthday,salary,entry_date,resume) values(10,‘张三疯‘,1,‘1983-09-21‘,15000,‘2012-06-24‘,‘一个老牛‘);

ERROR 1366 (HY000): Incorrect string value: ‘\x80\xE4\xB8\xAA\xE8\x80...‘ for column ‘resume‘ at row 1

因素2:操作系统的语言集

linux操作系统 是一个 多用户的操作

[[email protected] ~]# cat /etc/sysconfig/i18n //查看当前语言设置

LANG="zh_CN.UTF-8"     //数据存储按照UTF8格式,数据展示按照简体中文.

操作系统的菜单按照zh_CN显示,  文件存储按照utf8

linux操作系统语言环境 和 用户的配置的语言环境LANG 相互影响(两者(要)一样)

[[email protected] ~]$ echo $LANG

zh_CN.UTF-8

改了任意一个,就会乱码:

【实验步骤4】:

修改用户下的.bash_profile 中的LANG,屏蔽操作系统的LANG设置。再查数据库

mysql> select * from employee;

结论: 用户的LANG设置,影响了应用程序的语言环境,导致myql的语言环境发生了改变:

mysql> show variables like ‘character%‘;

在此环境下,检索中文会出现乱码。

【实验步骤5】:在上述环境之下,向数据库中插入中文。

insert into employee(id,name,sex,birthday,salary,entry_date,resume) values(5,‘张三疯‘,1,‘1987-05-21‘,15000,‘2014-06-24‘,‘一个老牛‘);

数据能插入到数据库中,没 有 报 任 何 错 误!但显示不正确。

因素3:文件存储格式

命令输入字符的格式,

比如

远程连接工具里配置输入命令的字符编码 不一致时也会有问题

所以操作前要查询一下数据,并且操作后再查一下,确定一个是否有乱码。

/*******************************************************************************************/

十、mysql分页问题处理

前面说的那两个mysql本来就有,且不能删除的表,里面都是一些mysql库相关的信息,比如表的约束啥的

可以切换到那两个数据库,然后查询看看里面的内容。

--显示数据

select * from emp \G; 这种方式显出出来的结果是一行一行的展示数据,就和没有\G的效果完全不同了

--top-N问题解决(mysql解决top-N问题的方法与oracle不同,主要就是使用了limit)

-- limit 取前3名,

select * from emp order by sal desc limit 3;

-- limit取5-8名,limit 后的两个数字,代表跳过的记录数,和然后取的记录数.

select * from emp order by sal desc limit 4,4;

/*******************************************************************************************/

十一、mysql api编程

mysql API详细见《MySQL 中文完全参考手册5.1.chm》,主要研究的是c库,也就是mysql提高给c的api

(下面摘出的是文档中需要特别注意的地方,并作了相应的注释)

1.依赖

C API代码是与MySQL一起提供的。它包含在mysqlclient库中,并允许C程序访问数据库。

//也就是c操作mysql时需要这个库文件以及相关的头文件

//依赖的头文件和库文件

/usr/include/mysql/mysql.h

/usr/lib64/mysql/libmysqlclient.a

[[email protected] ~]$ locate mysql.h  //或者使用locate命令找到头文件和库文件 这时由于linux平台对文件信息做了记录,数据也不是实时更新的所以速度快,使用locate可查询到

//比如新增了一个文件,用locate不一定找的出来,但是用find可以找出来 //同样对于libmysqlclient.a文件,也可以用这个命令找到路径

2.使用流程

与MySQL交互时,应用程序应使用该一般性原则(流程):

1).通过调用mysql_library_init(),初始化MySQL库。库可以是mysqlclient C客户端库,或mysqld嵌入式服务器库,具体情况取决于应用程序是否与“-libmysqlclient”或“-libmysqld”标志链接。

2).通过调用mysql_init()初始化连接处理程序,并通过调用mysql_real_connect()连接到服务器。

3).发出SQL语句并处理其结果。(在下面的讨论中,详细介绍了使用它的方法)。

4).通过调用mysql_close(),关闭与MySQL服务器的连接。

5).通过调用mysql_library_end(),结束MySQL库的使用。

//其中第一步和第五步可以省略

//mysql编程的流程:

mysql_init 初始化

mysql_real_connect 连接

//做操作

mysql_close  关闭

3.示例

熟悉mysql api编程的方式:编写一个mysql客户端:

1).成功连接到mysql

2).做一下查询和新增数据的操作

3).编写客户端

1).成功连接到mysql(配置环境)

(1).初始化函数

MYSQL *mysql_init(MYSQL *mysql)  初始化函数

MYSQL 代表mysql连接句柄 ,传入参数可以为NULL

返回成功 是 连接句柄,失败 NULL

(2).连接mysql的函数

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 连接句柄 ,要用初始后的返回值

host    主机 本地ip地址

user  用户 mysql的用户

passwd 密码 mysql的用户的密码

db     库名

port  端口 一般不用,填0

unix_socket  一般不用,填NULL

client_flag  标志位 通常为0,具体见手册,里面有说明

返回值: 返回 连接句柄,失败返回 NULL

(3).关闭连接

void mysql_close(MYSQL *mysql)

mysql 连接句柄 mysql_real_connect

代码见《hello.c》:

 1 //gcc 01_hello.c -o 01_hello -I/usr/include/mysql/ -L/usr/lib64/mysql/ -lmysqlclient -lstdc++ -ldl -lpthread -lrt
 2 #include "mysql.h"
 3 #include <stdio.h>
 4 #include <stdlib.h>
 5
 6 #define _HOST_  "127.0.0.1"   //主机
 7 #define _USER_  "root"   //用户 mysql的用户
 8 #define _PASSWD_ "123"   //密码 mysql
 9 #define _DB_     "scott"  //库
10
11
12
13 int main()
14 {
15     MYSQL *mysql = NULL;
16     //1. mysql_init
17     mysql = mysql_init(NULL);
18     if(mysql == NULL){
19         printf("mysql init err\n");
20         exit(1);
21     }
22     //2. mysql_real_connect
23     //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)
24     mysql = mysql_real_connect(mysql,_HOST_,_USER_,_PASSWD_,_DB_,0,NULL,0);
25     if(mysql == NULL ){
26         printf("mysql connect err!\n");
27         exit(1);
28     }
29     printf("welcome to mysql!\n");
30     //3. mysql_close
31     mysql_close(mysql);
32     return 0;
33 }

hello.c

注意编译:

//gcc 01_hello.c -o 01_hello -I/usr/include/mysql/ -L/usr/lib64/mysql/ -lmysqlclient

这样首先会报gxx的错误,这是缺少g++的库,解决方法:

//gcc 01_hello.c -o 01_hello -I/usr/include/mysql/ -L/usr/lib64/mysql/ -lmysqlclient -lstdc++

这样首先会报dlxx的错误,man 相关缺少定义的函数,然后加上需要的,解决方法:

gcc 01_hello.c -o 01_hello -I/usr/include/mysql/ -L/usr/lib64/mysql/ -lmysqlclient -lstdc++ -ldl -lpthread -lrt

(4).makefile编写

make -n //假装走一遍,并不是真的执行,相当于测试指令。

具体内容见《makefile》:

 1 #gcc 01_hello.c -o 01_hello -I/usr/include/mysql/ -L/usr/lib64/mysql/ -lmysqlclient -lstdc++ -ldl -lpthread -lrt
 2
 3 GCC=gcc
 4 IncPath=/usr/include/mysql/
 5 LibPath=/usr/lib64/mysql/
 6 PubLib=-lmysqlclient -lstdc++ -ldl -lpthread -lrt
 7
 8 SrcFiles=$(wildcard *.c)
 9 TargetFiles=$(patsubst %.c,%,$(SrcFiles))
10
11 all:$(TargetFiles)
12
13
14 %:%.c
15     $(GCC) $? -o [email protected] -I$(IncPath) -L$(LibPath) $(PubLib)
16
17
18 clean:
19     rm -f $(TargetFiles)

makefile

2).mysql api新增数据

实现insert功能:

-- mysql sql执行函数 执行完了就完了,不会返回结果

int mysql_query(MYSQL *mysql, const char *query)

mysql 连接句柄

query   执行的sql

成功返回0 ,失败返回非0

代码见《insert.c》:

 1 //insert
 2 #include "mysql.h"
 3 #include <stdio.h>
 4 #include <stdlib.h>
 5
 6 #define _HOST_  "127.0.0.1"   //主机
 7 #define _USER_  "root"   //用户 mysql的用户
 8 #define _PASSWD_ "123"   //密码 mysql
 9 #define _DB_     "scott"  //库
10
11
12
13 int main()
14 {
15     MYSQL *mysql = NULL;
16     //1. mysql_init
17     mysql = mysql_init(NULL);
18     if(mysql == NULL){
19         printf("mysql init err\n");
20         exit(1);
21     }
22     //2. mysql_real_connect
23     //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)
24     mysql = mysql_real_connect(mysql,_HOST_,_USER_,_PASSWD_,_DB_,0,NULL,0);
25     if(mysql == NULL ){
26         printf("mysql connect err!\n");
27         exit(1);
28     }
29     printf("welcome to mysql!\n");
30
31     // 在此处添加业务代码
32     char *rSql = "insert into dept(deptno,dname,loc) values(50,‘caiwu‘,‘beijing‘)";
33     //执行
34     if(mysql_query(mysql,rSql) ){
35         printf("mysql query err:%s\n",rSql);
36         mysql_close(mysql);
37         exit(1);
38     }
39     printf("insert ok!\n");
40     //3. mysql_close
41     mysql_close(mysql);
42     return 0;
43 }

insert.c

3).实现mysql查询

除了用执行函数外,还需要知道返回的结果,也就是查询结果集,

这时需要使用的函数:

MYSQL_RES *mysql_store_result(MYSQL *mysql)

描述

对于成功检索了数据的每个查询(SELECT、SHOW、DESCRIBE、EXPLAIN、CHECK TABLE等),必须调用mysql_store_result()或mysql_use_result() 。

对于其他查询,不需要调用mysql_store_result()或mysql_use_result(),但是如果在任何情况下均调用了mysql_store_result(),它也不会导致任何伤害或性能降低。通过检查mysql_store_result()是否返回0,可检测查询是否没有结果集(以后会更多)。

MYSQL_RES关于该结构体的描述可以去mysql.h里面查找

mysql 连接句柄

返回 结果集 MYSQL_RES ,失败 返回 NULL

--取结果集的下一行,循环调用这个函数则可以得到结果集的所有行

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result) //可以调用mysql_fetch_row()来获取结果集中的行

result 取回的结果集

MYSQL_ROW 返回下一行的结构 //MYSQL_ROW 是char**,是一个二维数组,表示一行的内容

char ** 可以展示.

即二维数组中的每一个元素是每一列的内容,比如row[0]是该行第一列的内容,row[1]是该行第二列的内容

--释放结果集//一旦完成了对结果集的操作,必须调用mysql_free_result()。

void mysql_free_result(MYSQL_RES *result)

获取列的个数的函数:

unsigned int mysql_num_fields(MYSQL_RES *result) //返回结果集中的行数。

获取列名使用的函数:

MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result) //返回所有MYSQL_FIELD结构的数组,数组的元素就是每一列的列名

代码见《select.c》:

 1 //select 查询功能
 2 #include "mysql.h"
 3 #include <stdio.h>
 4 #include <stdlib.h>
 5
 6 #define _HOST_  "127.0.0.1"   //主机
 7 #define _USER_  "root"   //用户 mysql的用户
 8 #define _PASSWD_ "123"   //密码 mysql
 9 #define _DB_     "scott"  //库
10
11
12
13 int main()
14 {
15     MYSQL *mysql = NULL;
16     //1. mysql_init
17     mysql = mysql_init(NULL);
18     if(mysql == NULL){
19         printf("mysql init err\n");
20         exit(1);
21     }
22     //2. mysql_real_connect
23     //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)
24     mysql = mysql_real_connect(mysql,_HOST_,_USER_,_PASSWD_,_DB_,0,NULL,0);
25     if(mysql == NULL ){
26         printf("mysql connect err!\n");
27         exit(1);
28     }
29     printf("welcome to mysql!\n");
30
31     //在此处添加业务代码
32
33     //执行查询
34     if(mysql_query(mysql,"select * from emp") ){
35         printf("mysql query err\n");
36         mysql_close(mysql);
37         exit(1);
38     }
39     //处理查询结果集
40     MYSQL_RES *result = mysql_store_result(mysql);
41     MYSQL_ROW row;
42     int i =0;
43     if(result != NULL)//代表有结果集
44     {
45         //    MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)
46         while( (row=mysql_fetch_row(result) )) {
47             for(i = 0; i < 8 ; i ++)//针对 列的循环,一共是8列
48             {
49                 printf("%s\t",row[i]);
50             }
51             printf("\n");//上面处理是一行,此处换行
52         }
53         mysql_free_result(result);
54     }
55
56
57
58     //3. mysql_close
59     mysql_close(mysql);
60     return 0;
61 }

select.c

4).客户端工具编写

类似输入mysql -uroot -p123进行登录,并输入sql语句后会返回结果的程序工具

编写客户端:

连接到mysql数据库 mysql_init mysql_real_connect

打印管理台信息 MYSQL>

等待输入sql

执行输入的sql,主要是两类,有结果集(查询),没有结果集的

有结果集的打印结果集

关闭 mysql_close

注意,获取控制台的输入数据一般也可以使用fgets,该函数是阻塞的。

my_ulonglong mysql_affected_rows(MYSQL *mysql) //返回的是,多少个数在集合中

描述

返回上次UPDATE更改的行数,上次DELETE删除的行数,或上次INSERT语句插入的行数。

//连接之后设置一下字符集,来保证不同地方登录到服务器写入的数据的编码格式都是一样的。

int mysql_set_character_set(MYSQL *mysql, char *csname)

描述

该函数用于为当前连接设置默认的字符集。

mysql_set_character_set(mysql,"utf8"); //设置字符集

代码见《client.c》:

 1 //select2 查询功能 完善
 2 #include "mysql.h"
 3 #include <stdio.h>
 4 #include <stdlib.h>
 5 #include <string.h>
 6
 7 #define _HOST_  "127.0.0.1"   //主机
 8 #define _USER_  "root"   //用户 mysql的用户
 9 #define _PASSWD_ "123"   //密码 mysql
10 #define _DB_     "scott"  //库
11
12 //显示结果集的函数
13 void showresult(MYSQL_RES *result,MYSQL *mysql)
14 {
15     unsigned int num_fields;
16     unsigned int i;
17     MYSQL_FIELD *fields;
18
19     num_fields = mysql_num_fields(result);//获得字段数
20     fields = mysql_fetch_fields(result);//获取字段数组
21     for(i = 0; i < num_fields; i++)
22     {
23        printf("%s\t", fields[i].name);//打印字段,也就是表头
24     }
25     printf("\n");
26
27     printf("----------------------------------------------------------------\n");
28
29     MYSQL_ROW row;
30     if(result != NULL)//代表有结果集
31     {
32         //    MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)
33         while( (row=mysql_fetch_row(result) )) {
34             for(i = 0; i < num_fields ; i ++)//num_fields 列数
35             {
36                 printf("%s\t",row[i]);
37             }
38             printf("\n");//上面处理是一行,此处换行
39         }
40
41     }
42     printf("----------------------------------------------------------------\n");
43     printf("%ld rows in set\n",(long) mysql_affected_rows(mysql));
44
45 }
46
47 int main()
48 {
49     MYSQL *mysql = NULL;
50     //1. mysql_init
51     mysql = mysql_init(NULL);
52     if(mysql == NULL){
53         printf("mysql init err\n");
54         exit(1);
55     }
56     //2. mysql_real_connect
57     //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)
58     mysql = mysql_real_connect(mysql,_HOST_,_USER_,_PASSWD_,_DB_,0,NULL,0);
59     if(mysql == NULL ){
60         printf("mysql connect err!\n");
61         exit(1);
62     }
63     printf("welcome to mysql!\n");
64
65     mysql_set_character_set(mysql,"utf8"); //设置字符集
66
67
68     //在此处添加业务代码
69     char rSql[512];
70
71
72     while(1){
73         printf("yekaiSQL>");
74         memset(rSql,0x00,sizeof(rSql));
75         fgets(rSql, sizeof(rSql), stdin);
76         printf("rSql:%s\n",rSql);
77         if(strncmp(rSql,"quit",4) == 0 || strncmp(rSql,"QUIT",4) == 0)
78         {
79             printf("bye bye\n");
80             break;
81         }
82         //执行sql
83         if(mysql_query(mysql,rSql) ){
84             printf("mysql query err\n");
85             //mysql_close(mysql);
86             //exit(1);
87         }
88         //处理查询结果集
89         MYSQL_RES *result = mysql_store_result(mysql);
90         if(result != NULL){
91             showresult(result,mysql);//打印结果集
92             mysql_free_result(result);
93         }
94     }
95
96     //3. mysql_close
97     mysql_close(mysql);
98     return 0;
99 }

client.c

/*******************************************************************************************/

十二、mysql预处理

1.预处理函数主要作用就是为了提高速度,适合sql语句多次反复执行

2.MySQL客户端/服务器协议提供了预处理语句。该功能采用了由mysql_stmt_init()初始化函数返回的MYSQL_STMT语句处理程序数据结构。

3.对于多次执行的语句,预处理执行是一种有效的方式。

首先对语句进行解析,$$$为执行作好准备$$$。

接下来,在以后使用初始化函数返回的语句句柄执行一次或多次。

对于多次执行的语句,预处理执行比直接执行快,主要原因在于,

仅对查询执行$$$一次解析操作$$$。在直接执行的情况下,每次执行语句时,均将进行查询。

此外,由于每次执行预处理语句时仅需$$$发送参数$$$的数据,从而减少了网络通信量。

4.预处理语句的另一个优点是,它采用了二进制协议,从而使得客户端和服务器之间的数据传输更有效率。

5.下述语句可用作预处理语句:

CREATE TABLE、DELETE、DO、INSERT、REPLACE、SELECT、SET、UPDATE、

以及大多数SHOW语句。在MySQL 5.1中,不支持其他语句。

6.缺点:用的比较难一点,也就是编程的时候难一点。

7.预处理流程见图《预处理的流程.png》:

8.mysql预处理详解(代码说明)

#define INSERT_SAMPLE "INSERT INTO test_table(col1,col2,col3) VALUES(?,?,?)"

//其中那三个问号代表占位,其实就是代表要传入的参数

MYSQL_BIND    bind[3];//绑定变量 ,前面有三个问号,即有三个参数,所以这里是三个

bind[0].buffer= (char *)&int_data;//内存地址的映射

//注意,这个是指针的赋值导致的结果是双向的,即bind[0].buffer指向的内容改变了,则int_data

里面的内容也跟着变化了,同时,int_data里面的内容改变了,即bind[0].buffer所指向的内容也变化了

bind[0].is_null= 0;//由于是取地址赋值的,所以改为等于NULL更合适,

bind[0].length= 0;//由于是取地址赋值的,所以改为等于NULL更合适,

//如果绑定变量内的成员不等于NULL,那么由于内存映射的关系,修改了赋值的变量,则就是修改了绑定变量指向的

内存,同时也会传递到sql语句(类似传递了实参),因为绑定变量已经和sql语句建立了联系

示例:

int_data= 10;             /* integer */

strncpy(str_data, "MySQL", STRING_SIZE); /* string  */

str_length= strlen(str_data);

/* INSERT SMALLINT data as NULL */

is_null= 1;//指示插入的第三个字段是否为null,如果等于1表示要插入的是空,则无论指向的内存是什么情况,插入的数据都是null

/* Execute the INSERT statement - 1*/

if (mysql_stmt_execute(stmt)) //预处理的执行,第一次执行

补充:

//int mysql_stmt_fetch(MYSQL_STMT *stmt)   涉及到查询,具体看手册

param_count= mysql_stmt_param_count(stmt);//获得参数个数 ,这个函数不是预处理必须的流程,

代码见《prepare_insert.c》:

  1 #include <stdio.h>
  2 #include "mysql.h"
  3 #include <stdlib.h>
  4 #include <string.h>
  5
  6 #define _HOST_ "localhost"  //主机
  7 #define _USER_ "root"       //mysql用户,非主机
  8 #define _PASSWD_ "123"   //密码
  9 #define _DBNAME_ "scott"    //库名
 10
 11 #define STRING_SIZE 50
 12
 13 #define DROP_SAMPLE_TABLE "DROP TABLE IF EXISTS test_table"
 14 #define CREATE_SAMPLE_TABLE "CREATE TABLE test_table(col1 INT, 15                                                  col2 VARCHAR(40), 16                                                  col3 SMALLINT, 17                                                  col4 TIMESTAMP)"
 18 #define INSERT_SAMPLE "INSERT INTO test_table(col1,col2,col3) VALUES(?,?,?)"
 19 void prepare_insert(MYSQL *mysql);
 20
 21 int main()
 22 {
 23     //1.初始化
 24     MYSQL * mysql = NULL;
 25     mysql = mysql_init(NULL) ;
 26     if(mysql == NULL )
 27     {
 28         printf("mysql init err\n");
 29         exit(1);
 30     }
 31     //2.连接
 32     mysql = mysql_real_connect(mysql, _HOST_,_USER_, _PASSWD_,_DBNAME_, 0, NULL,0);
 33     if(mysql == NULL)
 34     {
 35         printf("mysql_real_connect connect err\n");
 36         exit(1);
 37     }
 38     printf("welcome to mysql \n");
 39     prepare_insert(mysql);
 40     //3.关闭
 41     mysql_close(mysql);
 42     return 0;
 43 }
 44
 45
 46
 47
 48 void prepare_insert(MYSQL *mysql)
 49 {
 50     MYSQL_STMT    *stmt;//预处理的句柄
 51     MYSQL_BIND    bind[3];//绑定变量
 52     my_ulonglong  affected_rows;
 53     int           param_count;
 54     short         small_data;
 55     int           int_data;
 56     char          str_data[STRING_SIZE];
 57     unsigned long str_length;
 58     my_bool       is_null;
 59
 60     if (mysql_query(mysql, DROP_SAMPLE_TABLE))//删除表
 61     {
 62       fprintf(stderr, " DROP TABLE failed\n");
 63       fprintf(stderr, " %s\n", mysql_error(mysql));
 64       exit(0);
 65     }
 66
 67     if (mysql_query(mysql, CREATE_SAMPLE_TABLE))//创建表
 68     {
 69       fprintf(stderr, " CREATE TABLE failed\n");
 70       fprintf(stderr, " %s\n", mysql_error(mysql));
 71       exit(0);
 72     }
 73
 74     /* Prepare an INSERT query with 3 parameters */
 75     /* (the TIMESTAMP column is not named; the server */
 76     /*  sets it to the current date and time) */
 77     stmt = mysql_stmt_init(mysql); //预处理的初始化
 78     if (!stmt)
 79     {
 80       fprintf(stderr, " mysql_stmt_init(), out of memory\n");
 81       exit(0);
 82     }
 83     if (mysql_stmt_prepare(stmt, INSERT_SAMPLE, strlen(INSERT_SAMPLE))) //insert 语句 的预处理
 84     {
 85       fprintf(stderr, " mysql_stmt_prepare(), INSERT failed\n");
 86       fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
 87       exit(0);
 88     }
 89     fprintf(stdout, " prepare, INSERT successful\n");
 90
 91     /* Get the parameter count from the statement */
 92     param_count= mysql_stmt_param_count(stmt);//获得参数个数
 93     fprintf(stdout, " total parameters in INSERT: %d\n", param_count);
 94
 95     if (param_count != 3) /* validate parameter count */
 96     {
 97       fprintf(stderr, " invalid parameter count returned by MySQL\n");
 98       exit(0);
 99     }
100
101     /* Bind the data for all 3 parameters */
102
103     memset(bind, 0, sizeof(bind));
104
105     /* INTEGER PARAM */
106     /* This is a number type, so there is no need to specify buffer_length */
107     bind[0].buffer_type= MYSQL_TYPE_LONG;
108     bind[0].buffer= (char *)&int_data;//内存地址的映射
109     bind[0].is_null= 0;
110     bind[0].length= 0;
111
112     /* STRING PARAM */
113     bind[1].buffer_type= MYSQL_TYPE_STRING;
114     bind[1].buffer= (char *)str_data;//char 100
115     bind[1].buffer_length= STRING_SIZE;
116     bind[1].is_null= 0;
117     bind[1].length= &str_length;
118
119     /* SMALLINT PARAM */
120     bind[2].buffer_type= MYSQL_TYPE_SHORT;
121     bind[2].buffer= (char *)&small_data;
122     bind[2].is_null= &is_null;//是否为null的指示器
123     bind[2].length= 0;
124
125     /* Bind the buffers */
126     if (mysql_stmt_bind_param(stmt, bind)) //绑定变量 参数绑定
127     {
128       fprintf(stderr, " mysql_stmt_bind_param() failed\n");
129       fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
130       exit(0);
131     }
132
133     //第一波赋值
134     int_data= 10;             /* integer */
135     strncpy(str_data, "MySQL", STRING_SIZE); /* string  */
136     str_length= strlen(str_data);
137
138     /* INSERT SMALLINT data as NULL */
139     is_null= 1;//指示插入的第三个字段是否为null
140
141     /* Execute the INSERT statement - 1*/
142     if (mysql_stmt_execute(stmt)) //预处理的执行,第一次执行
143     {
144       fprintf(stderr, " mysql_stmt_execute(), 1 failed\n");
145       fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
146       exit(0);
147     }
148
149     /* Get the total number of affected rows */
150     affected_rows= mysql_stmt_affected_rows(stmt);//预处理的影响条数
151     fprintf(stdout, " total affected rows(insert 1): %lu\n",
152                     (unsigned long) affected_rows);
153
154     if (affected_rows != 1) /* validate affected rows */
155     {
156       fprintf(stderr, " invalid affected rows by MySQL\n");
157       exit(0);
158     }
159
160     //第二波赋值
161     int_data= 1000;
162     strncpy(str_data, "The most popular Open Source database", STRING_SIZE);
163     str_length= strlen(str_data);
164     small_data= 1000;         /* smallint */
165     is_null= 0;               /* reset */
166
167     /* Execute the INSERT statement - 2*/
168     if (mysql_stmt_execute(stmt))//第二次执行
169     {
170       fprintf(stderr, " mysql_stmt_execute, 2 failed\n");
171       fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
172       exit(0);
173     }
174
175     /* Get the total rows affected */
176     affected_rows= mysql_stmt_affected_rows(stmt);
177     fprintf(stdout, " total affected rows(insert 2): %lu\n",
178                     (unsigned long) affected_rows);
179
180     if (affected_rows != 1) /* validate affected rows */
181     {
182       fprintf(stderr, " invalid affected rows by MySQL\n");
183       exit(0);
184     }
185
186     /* Close the statement */
187     if (mysql_stmt_close(stmt))
188     {
189       fprintf(stderr, " failed while closing the statement\n");
190       fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
191       exit(0);
192     }
193
194 }

prepare_insert.c

/*******************************************************************************************/

十三、mysql事务处理

mysql默认事务不开启,但是事务是支持的,是可以开启的。

#define SET_TRAN   "SET AUTOCOMMIT=0"  //代表自动提交是被关闭了的,也就是事务开启了。———手动commit

#define UNSET_TRAN      "SET AUTOCOMMIT=1"  //自动commit,执行完sql语句,立刻就提交,也就是恢复了默认

//无论设置事务为手动提交还是自动提交,都要先开启事务,即执行"start transaction"

具体见代码《tran.c》:

  1 //mysql中的事务
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 #include <string.h>
  5 #include "mysql.h"
  6
  7 #define SET_TRAN    "SET AUTOCOMMIT=0"          //手动commit    ————手动commit
  8 #define UNSET_TRAN    "SET AUTOCOMMIT=1"            //自动commit
  9
 10 #define _HOST_ "127.0.0.1"
 11 #define _USER_ "root"
 12 #define _PASSWD_ "123"
 13 #define _DBNAME_ "scott"
 14
 15 //设置事务为手动提交
 16 int mysql_OperationTran(MYSQL *mysql)
 17 {
 18     //--开启事务
 19     int ret = mysql_query(mysql, "start transaction");
 20     if (ret != 0) {
 21         printf("mysql_OperationTran query start err: %s\n", mysql_error(mysql));
 22         return ret;
 23     }
 24
 25     //--设置事务为手动提交
 26     ret = mysql_query(mysql, SET_TRAN);            //set autocommmit = 0
 27     if (ret != 0) {
 28         printf("mysql_OperationTran query set err: %s\n", mysql_error(mysql));
 29         return ret;
 30     }
 31
 32     return ret;
 33 }
 34
 35 //设置事务为自动提交
 36 int mysql_AutoTran(MYSQL *mysql)
 37 {
 38     //--开启事务
 39     int ret = mysql_query(mysql, "start transaction");
 40     if (ret != 0) {
 41         printf("mysql_AutoTran query start err: %s\n", mysql_error(mysql));
 42         return ret;
 43     }
 44
 45     //--设置事务为自动提交
 46     ret = mysql_query(mysql, UNSET_TRAN);  //"set autocommit = 1"
 47     if (ret != 0) {
 48         printf("mysql_AutoTran query set err: %s\n", mysql_error(mysql));
 49         return ret;
 50     }
 51
 52     return ret;
 53 }
 54
 55 //执行commit,手动提交事务
 56 int mysql_Commit(MYSQL *mysql)
 57 {
 58     int ret = mysql_query(mysql, "COMMIT"); //提交
 59     if (ret != 0) {
 60         printf("commit err: %s\n", mysql_error(mysql));
 61         return ret;
 62     }
 63     return ret;
 64 }
 65
 66 //执行rollback,回滚事务
 67 int mysql_Rollback(MYSQL *mysql)
 68 {
 69     int ret = mysql_query(mysql, "ROLLBACK");
 70     if (ret != 0) {
 71         printf("rollback err: %s\n", mysql_error(mysql));
 72         return ret;
 73     }
 74     return ret;
 75
 76 }
 77
 78 #define DROP_SAMPLE_TABLE "DROP TABLE IF EXISTS test_table"
 79 #define CREATE_SAMPLE_TABLE "CREATE TABLE test_table(col1 INT, 80                                                  col2 VARCHAR(10), 81                                                  col3 VARCHAR(10))"
 82
 83 #define sql01 "INSERT INTO test_table(col1,col2,col3) VALUES(10, ‘AAA‘, ‘A1‘)"
 84 #define sql02 "INSERT INTO test_table(col1,col2,col3) VALUES(20, ‘BBB‘, ‘B2‘)"
 85 #define sql03 "INSERT INTO test_table(col1,col2,col3) VALUES(30, ‘CCC‘, ‘C3‘)"
 86 #define sql04 "INSERT INTO test_table(col1,col2,col3) VALUES(40, ‘DDD‘, ‘D4‘)"
 87
 88 int main(void)
 89 {
 90     int ret = 0;
 91
 92     MYSQL *mysql = mysql_init(NULL);
 93
 94     mysql = mysql_real_connect(mysql, _HOST_, _USER_, _PASSWD_, _DBNAME_, 0, NULL, 0);
 95     if (mysql == NULL) {
 96         ret = mysql_errno(mysql);
 97         printf("func mysql_real_connect() err:%d\n", ret);
 98         return ret;
 99     }
100     printf(" --- connect ok......\n");
101     //执行删除表
102     if (mysql_query(mysql, DROP_SAMPLE_TABLE)) {
103       fprintf(stderr, " DROP TABLE failed\n");
104       fprintf(stderr, " %s\n", mysql_error(mysql));
105       exit(0);
106     }
107     //执行创建表
108     if (mysql_query(mysql, CREATE_SAMPLE_TABLE)) {
109       fprintf(stderr, " CREATE TABLE failed\n");
110       fprintf(stderr, " %s\n", mysql_error(mysql));
111       exit(0);
112     }
113
114     ret = mysql_OperationTran(mysql);     //开启事务,并修改事务属性为手动commit
115     if (ret != 0) {
116         printf("mysql_OperationTran() err:%d\n", ret);
117         return ret;
118     }
119
120     ret = mysql_query(mysql, sql01);    //向表中插入第一行数据 ‘AAA’
121     if (ret != 0) {
122         printf("mysql_query() err:%d\n", ret);
123         return ret;
124     }
125
126     ret = mysql_query(mysql, sql02);    //向表中插入第二行数据 ‘BBB’
127     if (ret != 0) {
128         printf("mysql_query() err:%d\n", ret);
129         return ret;
130     }
131
132     ret = mysql_Commit(mysql);             //手动提交事务
133     if (ret != 0) {
134         printf("mysql_Commit() err:%d\n", ret);
135         return ret;
136     }
137     //////////AAA BBB  进去了。
138
139 #if 1
140     ret = mysql_AutoTran(mysql);         // =再次= 修改事务属性为【自动】commit
141     if (ret != 0) {
142         printf("mysql_OperationTran() err:%d\n", ret);
143         return ret;
144     }
145 #else
146     ret = mysql_OperationTran(mysql);     // =再次= 修改事务属性为【手动】commit
147     if (ret != 0) {
148         printf("mysql_OperationTran() err:%d\n", ret);
149         return ret;
150     }
151 #endif
152
153     ret = mysql_query(mysql, sql03);    //向表中插入第三行数据 ‘CCC’
154     if (ret != 0) {
155         printf("mysql_query() err:%d\n", ret);
156         return ret;
157     }
158
159     ret = mysql_query(mysql, sql04);    //向表中插入第四行数据 ‘DDD’
160     if (ret != 0) {
161         printf("mysql_query() err:%d\n", ret);
162         return ret;
163     }
164
165     ret = mysql_Rollback(mysql);        //直接rollback操作
166     if (ret != 0) {
167         printf("mysql_Rollback() err:%d\n", ret);
168         return ret;
169     }
170
171     //rollback操作是否能回退掉CCC、DDD的值,取决于事务属性。
172
173     mysql_close(mysql);
174
175     return 0;
176 }

tran.c

原文地址:https://www.cnblogs.com/yuweifeng/p/9264423.html

时间: 2024-10-08 17:03:12

数据库之MySQL的介绍与使用20180703的相关文章

数据库 之 Mysql日志介绍

1  概述 本文将介绍如下Mysql的六种日志的相关概念 查询日志:general_log 慢查询日志:log_slow_queries 错误日志:log_error, log_warnings 二进制日志:binlog 中继日志:relay_log 事务日志:innodb_log 2  查询日志 默认没有开启,考虑到数据库服务器本身占用存储IO,所以一般不会使用查询日志的功能,防止给mysql造成性能降低 记录查询语句,日志存储位置: 文件:file 表:table (mysql.genera

mysql的介绍;安装及基本配置;mysql数据库运行必备技能

一.MySQL的介绍 1. 数据库:数据库集中存放位置 1) 常见的数据库类型:关系型(mysql.oracle.SQLserver2008,DB2),树型(windows注册表).非关系型(NoSQL). 2) 关系型数据库对象:数据记录-存->表à存à数据库:表分为数据库,关系表 2. MySQL是开源的关系型数据软件,目前由oracle公司维护,特点是:多线程.多用户.基于C/S架构(客户端/服务器),简单易用.查询速度快,安全可靠. 二.安装及基本配置: 1. 安装 1) 安装依赖ncu

数据库 之 Mysql存储引擎介绍

1  存储引擎概念介绍 存储引擎其实就是如何实现存储数据,如何为存储的数据建立索引以及如何更新,查询数据等技术实现的方法.数据库中的存储引擎其实是对使用了该引擎的表进行某种设置,数据库中的表设定了什么存储引擎,那么该表在数据存储方式.数据更新方式.数据查询性能以及是否支持索引等方面就会有不同的"效果". 通过选择不同的存储引擎,获得额外的速度或者功能,从而改善服务器的应用的整体功能.例如,如果你在研究大量的临时数据,你也许需要使用内存MySQL存储引擎.内存存储引擎能够在内存中存储所有

MySQL数据库(二)MySQL基本介绍

MySQL基本介绍 MySQL是一个关系型数据库管理系统. 1.MySQL是一种开源免费的数据库产品. 2.MySQL对PHP的支持最好(wamp或者lamp) MySQL中用到的操作指令就是SQL指令. 启动和停止MySQL服务 MySQL是一种C/S结构:客户端和服务端 服务端对应的软件:mysqld.exe,在mysql的安装目录下的bin目录中可以找到. 命令行方式   通过Windows下打开cmd,然后使用命令进行管理 net start 服务(mysql):开启服务 错误情况:发生

MySQL主从复制介绍

1.1 MySQL主从复制原理介绍 MySQL的主从复制是一个异步的复制过程(虽然一般情况下感觉是实时的),数据将从一个MySQL数据库(我们称之为Master)复制到另一个MySQL数据库(我们称之为Slave),在Master与Slave之间实现整个主从复制的过程是由三个线程参与完成的,其中有两个线程(SQL线程和IO线程)在Slave端,另外一个线程(I/O线程)在Master端. 要实现MySQL的主从复制,首先必须打开Master端的binlog记录功能,否则就无法实现.因为整个复制过

17.1 MySQL主从介绍;17.2 准备工作;17.3 配置主;17.4 配置从;17.5 测试主从同步

17.1 MySQL主从介绍 1. MySQL主从又叫做Replication.AB复制.简单讲就是A和B两台机器做主从后,在A上写数据,另外一台B也会跟着写数据,两者数据实时同步的 2. MySQL主从是基于binlog的,主上须开启binlog才能进行主从. 3. 主从过程大致有3个步骤 1)主将更改操作记录到binlog里 2)从将主的binlog事件(sql语句)同步到从本机上并记录在relaylog里 3)从根据relaylog里面的sql语句按顺序执行 4. 主上有一个log dum

【数据库】MySQL 从安装到命令

一, MySQL 的安装于配置 我是通过百度云盘的方式下载的.建议登录百度云终端,然后点击下面的链接,选择要安装的版本,解压安装. http://www.h2ero.cn/pan/share/17cde6_aWlxjeu.html (1)安装前准备 解压过后把mysql文件夹放到指定的文件目录下.我因为在虚拟机中只配置了一个盘符,所以直接放置在了C盘下.建议放置到其他盘符. 另外如果选择的是免安装版本的话,压缩过后文件夹的名称就叫做mysql.如果不是免安装版本那么后面会带有不同的版本号以及服务

MySQL性能调优与架构设计——第1章 MySQL 基本介绍

MySQL性能调优与架构设计——第1章 MySQL 基本介绍 前言:作为最为流行的开源数据库软件之一, MySQL 数据库软件已经是广为人知了. 但是为了照顾对MySQL还不熟悉的读者,这章我们将对 MySQL 做一个简单的介绍.主要内容包括MySQL 各功能模块组成,各模块协同工作原理, Query 处理的流程等. 1.1 MySQLServer 简介 1.1.1 什么是 MySQLMySQL 是由MySQL AB公司(目前已经被SUN公司收归麾下,SUN已经被Oracle收购)自主研发的,目

mysql information_schema介绍

mysql information_schema介绍 一.information_schema是什么 information_schema是MySQL自带的一个信息数据库,其保存着关于MySQL服务器所维护的所有其他数据库的信息,如数据库名,数据库的表,表栏的数据类型与访问权限等. 也就是说当你建立一个新的数据库,或者在已有的数据库中增删改表的话,都会记录在information_schema库中. 你可以通过information_schema库来查看各个数据库的信息:有时候是很有用的哦,例如