mysql 库的操作
创建库
sql
create database db_name;
修改库的属性
sql
//修改数据库的字符集和校验格式
alter database db_name chatset=utf8 collate=utf8_general_ci
字符集和校验集相关
查看默认的字符集与校验规则
sql
show variables like 'character_set_database';
show variables like
'collation_database';
查看支持的字符集
sql
show charset;
mysql默认是大小写不敏感的,所以可以通过设置校验格式的形式来满足区分大小写的需要
sql
//不区分大小写
create database testDB_1 collate utf8_general_ci;
//区分大小写
create database testDB_2 collate
utf8_bin;
操纵数据库
查看数据库
sql
show databases;
show create database db_name;//查看创建数据库时的语句
修改数据库
修改数据库,主要是指修改数据库的编码格式以及校验规则,mysql现在已经不再支持修改数据库的名称
sql
alter db_name charset=utf8;
alter db_name collate=utf8_bin;
数据库的删除
需要注意的是,删除数据库,会删除数据库的所有表结构,是级连删除,所以慎重删除
sql
drop database db_name;
数据库的备份与恢复
备份使用mysqldump,恢复使用source
sql
//备份整个数据库
#mysqldump -P3306 -u root -p -B db_name1 db_name2 > /path/to/mytest.sql;
//备份数据库的几张表
#mysqldump -P3306 -uroot -p db_name tb1_name tb2_name ... > /path/to/mytest.sql;
//恢复数据库备份
source /path/to/mytest.sql
需要注意的是-B选项并不是必须,如果不加的话,在恢复数据库时需要先创建空的数据库
查看链接情况
sql
show processlist;
mysql表的操作
创建表
sql
create table tb_name(
id int,
name varchar(60)
);
//查看创建的表的结构
desc tb_name;
需要注意的语法点
- 可以一行全写完,但是建议分行写
- 列中内容每一行后加逗号,但是最后一句不要加
修改表
主要有以下几种方法:
- add
- modify
- drop
- rename to(to可以省略)
sql
//在name这一列后创建一个新列grade,类型是tinyint
alter table tb_name add grade tinyint(60) after name;
//将id这一列设置为用bigint存储并加上主键约束
alter table tb_name modify id bigint primary key;
//删除grade列
alter table tb_name drop grade;
//重命名name列
alter table tb_name rename column name to xingming;
mysql数据类型
数值类型
mysql的整形主要有:
| 类型 | 大小 |
|---|---|
| tinyint | 1 bytes |
| smallint | 2 bytes |
| mediumint | 3 bytes |
| int | 4 bytes |
| bigint | 8 bytes |
其中还可以加上unsigned 来表示无符号
sql
create table tb_name(
id tinyint unsigned
);
bit类型
基本语法:
sql
create table tb_name(
gender bit(1)
)
没有指定数字大小的时候,默认是1;bit类型给定大小的范围是1~64;在取出bit类型的时候,按照ASCII的方式读取
小数类型float
基本语法:
sql
create table tb_name(
number float(4, 2)
)
指定的第一个数,是显示的长度,第二个数是小数部分占的长度
float在存放的时候,会自动帮助我们采取四舍五入,比如上面的例子中,如果我们存放99.991,那么mysql会自动帮我们将其改变为99.99,但如果存放99.999,那么会存放失败,因为四舍五入之后超出了长度为4小数部分为2这个限制
除此之外,float还可以设置unsigned,上例默认是-99.99~99.99,而加上unsigned修饰后,则存放0~99.99;
小数类型decimal
decimal和float类型创建使用基本相同,但是值得注意的是decimal的精度更高,float的精度大约只有7位,但是decimal整数部分最大支持65位,小数部分最大支持30位,不指定小数部分默认是0位,整数部分默认是10位
字符类型char
char用来存储字符,最大可以存储255个字符,包括中文和汉字,一个字母和一个汉字都可以用char(1)存储
字符类型varchar
这个类型比较有意思,他有点类似于C++中的string类型,最大长度是65535,但是还要花费1~3个字节来表示存放数据的大小,采取变长的方式,用多少开辟多少,至于能存放多少个字符,这件事和编码方式相关,比如utf8中一个中文字符为3个字节,但是gbk中一个中文字符为2个字节
时间日期类
- date,占用三个字节,表示年月日
- datetime,占用八个字节,表示年月日、时分秒
- timestamp占用四个字节,也表示年月日、时分秒,与前两者不同的是,在数据库中插入时不需要指定时间,而是会自动填入当前时间
enum和set类型
enum是枚举类型,set是几何类型,enum实际上提供的是从1开始的多个数字,最大是65535,set可以存放其中的多个值
sql
enum gender("male", "female");
set hobby("coding", "walking", "running");
//因为set可以存放列出的多个值,所以不能直接用=比较
select name from person where find_in_set("coding", hobby);
除此之外,set在插入时,可以采用类似于linux文件权限的理解方法:即二进制比特位表示是否设置,比如说hobby这个set中,如果我插入3,那么就是插入的coding和walking这两个值(因为3的二进制是11);
表的约束:
空属性、默认值和列描述
sql
create table tb_name(
name varchar(30),
id int not null comment "用户的id"
);
列描述主要是给程序员一些提示作用,可以采用show create table tb_name查看,不想要表格的话可以加上\G
zerofill
用来统一数字长度
sql
create table tb_name(
name varchar(30),
id int(10) zerofill not null
);
例如这张表中就是ID,的长度为10,如果不够就用0来填补到10位显示,但是mysql中存储的依然是原来的数字
primary key主键
主键在一张表中只能有一个,被其约束的内容只能存在一个,重复就会插入失败
sql
create table tb_name(
id int not null primary key
);
创建时没有添加主键,后期也可以添加:
sql
alter table tb_name add primary key(column name);
删除主键
sql
alter table user drop primary key;
联合主键
sql
//name和id中只要有一个不重复即可
create table tb_name(
name varchar(30),
id int,
primary key(name, id)
);
auto_increment 自增长
可以设置自增主键,常与primary key搭配使用,作为逻辑主键
unique唯一键
其实使用上和主键差不多,但不同的是,unique可以有多个.
sql
create table tb_name(
name varchar(30) unique,
id int unique
);
外键
存在主表和从表两个部分,外键约束定义在从表,主表必须有主键约束或者唯一键约束,外键列中的内容必须在主键列存在或者为空。
sql
//先创建主表
create table class_info(
class_id tinyint primary key,
class_name varchar(30)
);
//再创建从表
create table student(
name varchar(30),
class varchar(30),
foreign key (class) references class_info(class_name)
);
mysql的增删查改
即CURD操作(create-插入, update-更新, retrieve-读取, delete-删除)
create
单行数据、全列插入
sql
insert into tb_name values('zhangsan', 1, 'male');
多行数据,指定列插入
sql
insert into tb_name(name, gender) values
('lisi', 'female'),
('wangwu', 'male);
在发生主键或唯一键冲突后更新数据
sql
insert into tb_name values ('zhangsan', 1, 'male') on duplicate key update name = 'zhangsan', id = 10, gender = male;
替换
sql
replace into tb_name('lisi', 2, 'male');
如果存在冲突,那么就将原来的数据删掉再进行插入;如果没有冲突,就直接替换原来的数据
retrieve
基本功能
sql
select name, chinese, math, english, chinese + math + english 总分 from grade_table;
指定列查询,并且指定的名称可以作为表达式计算并指定结果列的名称
sql
select distinct salary from employees;
从员工表中筛选出不重复的工资信息
where条件
首先是几种比较运算符
- = null不安全
- <=> null安全
- like 模糊匹配,用法:
'孙%'可以表示所有第一个字符是'孙'的结果
'孙__' 可以表示所有第一个字符是'孙'并且总长度为三个字符的结果
order by
指定依据那一列来进行排序,并可以指定排的是生序还是降序,如果指定多个列参与排序,则优先级随语句位置先后
sql
select*from tb_name order by chinese desc, math asc, english desc;
表示依据语文降序,数学生序,英语降序的方式进行输出排序。
筛选分页结果
sql
select * from tb_name order by chinese limit 5 offset 5;
表示依照语文成绩排序时,返回从第六行开始的往后行
update
sql
update tb_name set math = math + 30 order by math desc limit 3;
表示将数学成绩最低的三位同学的数学成绩加上30分
delete
sql
delete from tb_name where name = 'zhangsan';
表示从表中删除zhangsan的所有数据
truncate
截断,不会像delete一样经历事务,在内存级的buffer pool中还留有回滚内容,会直接彻底清除掉内容
sql
truncate table tb_name;
聚合函数
| 函数 | 功能 |
|---|---|
| max() | 最大值 |
| min() | 最小值 |
| avg() | 平均值 |
| count() | 返回统计个数 |
| sum() | 返回总和 |
分组查询
sql
select*from employees group by deptno;
表示依据部门编号分组查询
复合查询
多表查询
sql
select class_info.class_id, student_info.student_id from class_info, student_info where student_info.class_id = class_info.class_id;
mysql会对两张表做笛卡尔积,即让一个表的每一行,都与两一张表的每一行拼接,想要搜索出有用的数据,就需要我们指定表名的进行比较
自查询
单行子查询
sql
select*from employees where hire_date = (select hire_date from employees order by hire_date desc limit 1 offset 2) order by hire_date asc;
表示在整张表按照hire_date升序排序的情况下,返回hire_date最大的第三位员工的所有信息
多行子查询
可以使用三个关键字,in、all、any,表示在子查询返回的范围中存在、对于子查询返回的所有结果如何、对于子查询返回的任意结果如何
多列子查询
sql
select name from employees where (emp_no, dept_no) ......
合并查询
union将两个结果集的结果合并,并自动取出相同的行;union也进行合并,但是不去除重复的行
表的内外链接
内链接
本质上就是对笛卡尔积进行筛选,我们前面提过的查询都是内链接。
语法:select 字段 from 表1 inner join 表2 on 连接条件 and 其他条件;
外链接
分为左外链接和右外链接两种
左外链接语法:
select 字段名 from 表名1 left join 表名2 on 连接条件
这样,即使左边的表在右边的表中没有像对应的信息,左边的表的内容也会被完整显示出来
右外链接语法:
select 字段 from 表名1 right join 表名2 on 连接条件;
mysql C语言链接使用:
cpp
#include <iostream>
#include <mysql/mysql.h>
#include <string>
#include <unistd.h>
using namespace std;
const string host = "localhost";
const string user = "connector";
const string passwd = "8992567";
const string db = "rootDB";
unsigned int port = 8080;
int main()
{
//检验是否成功介入mysql库
//cout << "//mysql client version: " << mysql_get_client_info() << endl;
MYSQL* my = mysql_init(nullptr); //初始化mysql对象
//链接数据库
if(mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), 0, nullptr, 0) == nullptr)
{
cout << "connect error" << endl;
return 2;
}
cout << "connect success" << endl;
//进行mysql操作
string sql;
mysql_set_character_set(my, "utf8"); //设置默认的链接编码,默认是latin1
//sql = "update user set name = 'wangwu' where id = 1";
sql = "select*from user";
int n = mysql_query(my, sql.c_str());
if(n == 0)
cout << "sucess" << endl;
else
cout << "fail" << endl;
//转储到mysql结果集
MYSQL_RES* res = mysql_store_result(my);
if(res == nullptr)
{
cout << "store result fail" << endl;
return 4;
}
//获取行和列
int rows = mysql_num_rows(res);
int fields = mysql_num_fields(res);
cout << "rows: " << rows << " fields: " << fields << endl;
//获取属性
MYSQL_FIELD* field_array = mysql_fetch_fields(res);
cout << field_array[0].db << "\t" << field_array[0].table << endl;
for(int i = 0; i < fields; i++)
{
cout << field_array[i].name << "\t";
}
cout << endl;
//获取内容
for(int i = 0; i < rows; i++)
{
MYSQL_ROW row = mysql_fetch_row(res); //其实就是包装的char**
for(int j = 0; j < fields; j++)
{
cout << row[j] << "\t";
}
cout << endl;
}
mysql_free_result(res);//释放结果集,但前提是他已经被mysql_store_result过
mysql_close(my);//关闭mysql对象
return 0;
}