一.数据库的概念
数据:事物的特征
数据库的本质是:通过套接字进行通信,来读存数据的一种软件,由于每次开发人员写程序都得写数据的套接字,所以诞生了数据库这个软件,减少重复劳动。(sql语句通用)
数据库就相当于文件夹,表就相当于文件(对于关系型数据来讲,非关系型数据库的是用key-value来进行存取的,没有表。#以下都默认是mysql数据库)
二.数据库忘记密码的办法
mariadb有效
vim /etc/my.cnf #主配置文件 [mysqld] skip-grant-table systemctl restart mariadb mysql MariaDB [(none)]> update mysql.user set password=password("123") where user="root" and host="localhost"; MariaDB [(none)]> flush privileges; MariaDB [(none)]>bye #打开/etc/my.cnf去掉skip-grant-table,然后重启 systemctl restart mariadb mysql -u root -p123 #以新密码登录
rm -rf /var/lib/mysql/mysql #所有授权信息全部丢失!!! systemctl restart mariadb mysql ###删除授权库,初始化
三.数据库的基本管理
1.统一字符编码
mysqladmin -uroot -p(原始密码,没有可以跳过) password "123" MariaDB [(none)]> select user(); # 查看当前的登陆的用户 +----------------+ | user() | +----------------+ | root@localhost | +----------------+ MariaDB [(none)]> \s #查看数据库的信息 [mysqld] #代表服务端 [mysql] #代表客户端(mysql自己的客户端)(局部) [server] #代表全局的服务端 [client] #代表全局的客户端 统一字符编码 #1. 修改配置文件 [mysqld] default-character-set=utf8 [client] default-character-set=utf8 [mysql] default-character-set=utf8 #mysql5.5以上:修改方式有所改动 [mysqld] character-set-server=utf8 collation-server=utf8_general_ci [client] default-character-set=utf8 [mysql] default-character-set=utf8 #2. 重启服务 #3. 查看修改结果: \s show variables like '%char%' show variables like 'char_'
二.库的操作
在硬盘上对应文件夹。
操作文件夹(库) 增加 create database db1 charset utf8; (charset 设置字符编码 ) 查看 show databases; show create database db1; #查看详细的信息你创建的db1。 修改 alter database db1 charset gbk; 删除 drop database db1;
三.表的操作
在硬盘上对应文件。
操作文件(表): #语法: create table 表名( 字段名1 类型[(宽度) 约束条件], 字段名2 类型[(宽度) 约束条件], 字段名3 类型[(宽度) 约束条件] ); #注意: 1. 在同一张表中,字段名是不能相同 2. 宽度和约束条件可选 3. 字段名和类型是必须的 查看当前所在的文件夹: select database(): 切换文件夹: use db1 增加 create table t1(id int,name char); #id只能传入整形,name只能传入字符类型。 查看 show tables; show create table t1; 查看表的详细信息 desc t1; #查看表结构 改 alter table t1 add sex char;#改的是表的结构 alter table t1 drop sex; alter table t1 modify name char(16) first; alter table t1 change name Name char(13) ; 删除 drop table t1;
#表的复制
复制表的操作: 复制表结构+记录 (key不会复制: 主键、外键和索引) select user,host from mysql.user; #你所要复制的内容。 create table t5 select user,host from mysql.user; #复制表 (表的结构,记录都复制过去) 如果想要只复制表的结构,不要记录的话,可以用以下两种方法。 create table t6 select user,host from mysql.user where 1=2;(因为查到的是空,所以无记录) create table t7 like mysql.user;
四.记录的操作
对应文件里的内容
操作文件的内容(记录) 增加 insert into db1.t1 (id,sex) values #可以调换顺序,但是必须要一一对应 (1,'z'), (2,'y'); 查 select id,sex from db1.t1; select * from db1.t1; #查找全部的信息,效率不高,不建议这么写。测试可以 改 update db1.t1 set sex='x' where id =2; 删 delete from t1 where id=2;
五.存储引擎
存储引擎:
存储引擎介绍:
存储引擎即表类型,mysql根据不同的表类型会有不同的处理机制。
就如同文件有各种的类型一样。
show engines; 查找mysql支持的引擎
show engines\G 后面加上大写G,显示出来会在一行当中,去掉表格。
\c 可以取消执行
InnoDB 引擎 在创建表的时候需要指定主建,不指定则会系统生成隐藏的字段。
六.数据类型
数据类型:(常用的) 整型: 默认是有符号的,如果超出范围,即按照最大的范围去存。 整型的宽度: 代表的是显示的宽度(其他类型指的都是存储的宽度),默认是 int(10) unsigned zerofill zerofill 的意思是不够10位的话,用0填充。 浮点型: x (m,d) m为总共多少位,d其中的小数位数。 float(255,30) double(255,30) decimal(65,30) 日期类型: MariaDB [db1]> create table t11 ( -> id int, -> name char(19), -> born_year year, -> birth_data date, -> class_time time, -> reg_time datetime -> ); insert into db1.t11 values(1,'zym',now(),now(),now(),now()); #插入日期,now会返回当前的时间,然后mysql会提取当前的时间。 +------+------+-----------+------------+------------+---------------------+ | id | name | born_year | birth_data | class_time | reg_time | +------+------+-----------+------------+------------+---------------------+ | 1 | zym | 2018 | 2018-01-26 | 09:37:50 | 2018-01-26 09:37:50 | +------+------+-----------+------------+------------+---------------------+ 也可以自己插入,但是得按照上方的格式: insert into db1.t11 values(1,'zym','2018','2018-01-26','09:37:50','2018-01-26 09:37:50'); 字符串类型: char:定长,一般使用 varchar:变长 create table t16(name char(5)); #(5)代表的是字符的个数 create table t17(name varchar(5)); insert into t16 values('xx ') insert into t17 values('xx ') char 固定长度,不够用空格在后面补齐,但是取出的时候会去掉尾部的空格,即使用时会去掉尾部的空格。 zym |zz |xxxx | select char_length(name) from t16; set sql_mode = 'PAD_CHAR_TO_FULL_LENGTH' 设置这个可以取出空格 使用时直接用等值使用就可以,例如 : where xx=xx 但是like(模糊匹配不同) like name 'xx' 这样使用的时候不会去掉尾部的空格,所以是取不出来的,用该用like varchar(5) 1bytes+zym|1bytes+zzz|1bytes+yyy 用一个bytes来描述数据,告诉你数据的大小。如果一个1bytes的头不够,则需要2个bytes的头。 char 和 vchar的比较 char 简单粗暴,存取都快,但是浪费空间。 vchar 存取都慢。 char 字段尽量在前面,跟mysql查询性能有关 不建议char和vchar一块使用(在一张表中)
7.枚举类型与集合类型
create table employee( id int, name char(10), sex enum('male','female','other'), hobbies set('play','eat','music','read') ); insert into employee values (1,'zym','male','music,read'); insert into employee values (2,'zzz','xxx','music,read') #如果xxx不在sex里面查询结果就是什么也没有。
8.约束性条件
约束性条件: #not null default create table t12 (name char(19) not null default 'aaaa'); insert into t12 values(); #传入空值,查询是aaaa ######key ###1.primary key 索引里面 primery 大于等于 not null unique 如果没有制定的话,InnoDB 会将第一个不为空,且唯一的字段当做主键。 ###2.unique 唯一 create talbe t13 (id int unique name char(19)); desc t13; +-------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+----------+------+-----+---------+-------+ | id | int(11) | YES | UNI | NULL | | | name | char(16) | YES | | NULL | | +-------+----------+------+-----+---------+-------+ insert into t13 values (1,'zym'), (1,'zzz'); 这样插入会报错,因为unique是唯一,不能有两个一样的id号"1". 也可以这样形式的插入 create table t15 (id int ,name char(19),unique(id)); ###联合唯一: 联合主键 联合唯一 create table t17 ( id int primary key auto_increment,host char(19),port int,unique(host,port)); 会报错: insert into t17 (host,port) values('1.1.1.1',3306),('1.1.1.1',3306); ERROR 1062 (23000): Duplicate entry '1.1.1.1-3306' for key 'host' ###3.foreign key ###4.index ###5.auto_increment (自增长) create table t16 (id int unique auto_increment); id 会随着你的插入自行增长。 指定步长: set global auto_increment_increment=2 #步长为2 show create table student; ter table student auto_increment=xxx;(只能设置成大于当前id的值) #设置步长 sqlserver:自增步长 基于表级别 create table t1( id int。。。 )engine=innodb,auto_increment=2 步长=2 default charset=utf8 mysql自增的步长: show session variables like 'auto_inc%'; #基于会话级别 set session auto_increment_increment=2 #修改会话级别的步长 #基于全局级别的 set global auto_increment_increment=2 #修改全局级别的步长(所有会话都生效) #!!!注意了注意了注意了!!! If the value of auto_increment_offset is greater than that of auto_increment_increment, the value of auto_increment_offset is ignored. 翻译:如果auto_increment_offset的值大于auto_increment_increment的值,则auto_increment_offset的值会被忽略 比如:设置auto_increment_offset=3,auto_increment_increment=2 mysql> set global auto_increment_increment=5; Query OK, 0 rows affected (0.00 sec) mysql> set global auto_increment_offset=3; Query OK, 0 rows affected (0.00 sec) mysql> show variables like 'auto_incre%'; #需要退出重新登录 拆表的思想: #foreign key的使用 用一个字段关联其他表。例如:员工,部门。 emp表: [fk] (约束条件) id name dep_id 1 zym 1 2 zzz 2 3 yyy 1 dep表 id name 1 技术 2 公关 3 技术 多对一的关系,emp表多对一dep表,要找就找多对一。 先建被关联的表: create table dep(id int primary key auto_increment,name char(19)); #在建emp表 create table emp(id int primary key auto_increment,name char(19),dep_id int, foreign key(dep_id) references dep(id) on delete cascade on update cascade); on delete cascade on update cascade #加上上方这两条,如果被关联的表(dep)有变动的话,emp表也随之变化 #先插dep表 insert into dep (name) values('it'),('hr'),('sale'); #再插emp表 insert into emp(name,dep_id) values('zym',1),('zzz',3),('yyy',1); 双向的多对一: 先建两个表,然后利用第三个表实现关联的关系。 create table book(id int primary key auto_increment,name char(19)); create table author(id int primary key auto_increment,name char(19)); create table book2author(id primary key auto_increment,book_id int ,author_int, foreign key(book_id) references book(id), on delete cascade on update cascade, foreign key(author_id) references author(id)) on delete cascade on update cascade ); 一对一的关系: 就是在多对一的情况下,加上unique限制唯一。
9.单表查询
单表查询: 语法: select distinct 字段1,字段2...from 表 #distinct是记录去重 where 约束条件 group by 分组字段 having 过滤条件 order by 排序字段 limit 显示条数; ####!!!!!重点 sql语句按这个顺序执行。 重点中的重点:关键字的执行优先级 from where group by having select distinct order by limit select sidtinct 字段一,字段二,...from 左表 left join 右表 #先连接表之后再select. on 连接条件 where 约束条件 group by 字段 having select distinct order by limit 四则运算; select name,salary*12 from emp; #支持四则运算 select name as 姓名 ,salary*12 as 年薪 from employee; #起别名(改标题) +------------+-------------+ | 姓名 | 年薪 | +------------+-------------+ | egon | 87603.96 | | alex | 12000003.72 | 定义格式显示: select concat('姓名:',name,' ' ,'年薪 ',salary*12) from employee; 使用 concat 函数 来进行格式的定义,进行拼接。 +---------------------------------------------------+ | concat('姓名:',name,' ' ,'年薪 ',salary*12) | +---------------------------------------------------+ | 姓名:egon 年薪 87603.96 | | 姓名:alex 年薪 12000003.72 | | 姓名:wupeiqi 年薪 99600.00 select concat_ws(':',name,salary*12) from employee;#制定第一个分隔符 +-------------------------------+ | concat_ws(':',name,salary*12) | +-------------------------------+ | egon:87603.96 | | alex:12000003.72 约束条件: where 1. 比较运算符:> < >= <= <> != 2. between 80 and 100 值在80到100之间(包括80和100) 3. in(10,20,30) 值是10或20或30 4. like 'egon%' pattern可以是%或_, %表示任意多字符 _表示一个字符 5. 逻辑运算符:在多个条件直接可以使用逻辑运算符 and or not 利用以上的方法进行组合查询 mysql中空是 null 并不是'', 所以要查询空的要求时,需要。 select * from emp where post_comment is null; #查询空 select * from emp where name regexp '^程.*$'; #regexp 可以使用正则了 group by 分组:一旦分组处理数据的话就得按组来处理了。如果纠结单个元素就不用分组了。 select * from employee group by post; set global sql_mode='only_full_group_by'; #更改为严格模式,之后就取不出单个的记录了。 聚合函数: !!聚合函数只能在分组之后使用 !!但是 select count(id) from employee;可以使用的原因是默认的约束条件都为真。 但是where不能用聚合函数,因为where在分组之前。 select post,max(salary) from employee group by post;#取出组中最高的工资数 select post,min(salary) from employee group by post 最低 select post,avg(salary) from employee group by post 平均 select post,sum(salary) from employee group by post 工资总和 select post,count(id) from employee group by post 公司的员工数 select post,group_concat(name) from employee group by post; #查出每个岗位的人名 +-----------------------------------------+---------------------------------------------------------+ | post | group_concat(name) | +-----------------------------------------+---------------------------------------------------------+ | operation | 程咬铁,程咬铜,程咬银,程咬金,张野 | | sale | 格格,星星,丁丁,丫丫,歪歪 | | teacher | 成龙,jinxin,jingliyang,liwenzhou,yuanhao,wupeiqi,alex | | 老男孩驻沙河办事处外交大使 | egon | +-----------------------------------------+---------------------------------------------------------+ having过滤: 查平均工资超过10000的部门。 MariaDB [db1]> select post,avg(salary) as avg_num from employee group by post having avg(salary) > 10000;; +-----------+---------------+ | post | avg_num | +-----------+---------------+ | operation | 16800.026000 | | teacher | 151842.901429 | +-----------+---------------+ having 只能在group by 后面使用 order by 排序字段 MariaDB [db1]> select post,avg(salary) as avg_num from employee group by post having avg(salary) > 10000 order by avg(salary) ; 以avg(salary)进行排序,默认是从小到大排序。 从大到小 order by avg(salary)后面加 desc 可以连续排序,如果一项分不出大小的话 order by age,salary desc; limit 3,3; 从第三条开始向后走3条。进行分页,但是数据过多的话效率过低。
10.多表查询
多表查询; 表独立比较好,但是dingo用的是外键,forign key 准备表:emp +----+------------+--------+------+--------+ | id | name | sex | age | dep_id | +----+------------+--------+------+--------+ | 13 | egon | male | 18 | 200 | | 15 | alex | female | 48 | 201 | | 17 | wupeiqi | male | 38 | 201 | | 19 | yuanhao | male | 28 | 202 | | 21 | liwenzhou | male | 18 | 200 | | 23 | jingliyang | female | 18 | 203 | +----+------------+--------+------+--------+ dep +-----+--------------+ | id | name | +-----+--------------+ | 200 | 技术 | | 201 | 人力资源 | | 202 | 销售 | | 203 | 运营 | | 204 | 运营2 | +-----+--------------+ ##笛卡尔集; select * from dep,emp; 两张表相互对应(但是会产生无效的用具) 1 ------aaaa 2 ------aaaa 3 ------aaaa 1 ------bbbb 2 ------bbbb 3 ------bbbb select * from dep,emp where dep.id = emp.ep_id; 筛选有用的值 ##内连接:inner join select * from dep inner join emp on dep.id = emp.dep_id; #筛选有用的值 +-----+--------------+----+------------+--------+------+--------+ | id | name | id | name | sex | age | dep_id | +-----+--------------+----+------------+--------+------+--------+ | 200 | 技术 | 13 | egon | male | 18 | 200 | | 201 | 人力资源 | 15 | alex | female | 48 | 201 | | 201 | 人力资源 | 17 | wupeiqi | male | 38 | 201 | | 202 | 销售 | 19 | yuanhao | male | 28 | 202 | | 200 | 技术 | 21 | liwenzhou | male | 18 | 200 | | 203 | 运营 | 23 | jingliyang | female | 18 | 203 | +-----+--------------+----+------------+--------+------+--------+ 实现步骤:先找到左边这张表,做笛卡尔积,然后过滤执行on条件,inner join只取两张表的共同的部分。 ##左链接: left join select * from dep left join emp on dep.id = emp.dep_id; +-----+--------------+------+------------+--------+------+--------+ | id | name | id | name | sex | age | dep_id | +-----+--------------+------+------------+--------+------+--------+ | 200 | 技术 | 13 | egon | male | 18 | 200 | | 200 | 技术 | 21 | liwenzhou | male | 18 | 200 | | 201 | 人力资源 | 15 | alex | female | 48 | 201 | | 201 | 人力资源 | 17 | wupeiqi | male | 38 | 201 | | 202 | 销售 | 19 | yuanhao | male | 28 | 202 | | 203 | 运营 | 23 | jingliyang | female | 18 | 203 | | 204 | 运营2 | NULL | NULL | NULL | NULL | NULL | +-----+--------------+------+------------+--------+------+--------+ 会显示左边表没有对应的一项 即(204 对应为空的) ##右连接 select * from dep left join emp on dep.id = emp.dep_id; 会显示右边表没有对应的一项 ##全连接: full join 但是mysql中没有所以需要找到左连接和右连接相同的部分,即去重 #(union去重) select * from dep left join emp on dep.id = emp.dep_id union select * from dep left join emp on dep.id = emp.dep_id; ##子查询 查询平均年龄在25岁以上的部门名字 select name from dep where id in (select dep_id from emp group by dep_id having avg(age)>25); 查询技术部员工的姓名 select name from emp where dep_id = (select id from dep where name = '技术'); 查看<=1人的部门名 select name from dep where id in (select dep_id from emp group by dep_id having count(id)<=1); 查询大于所有人平均年龄的员工名与年龄 select name,age from emp where age > (select avg(age) from emp); 查询大于本部门内平均年龄的员工名,年龄 select * from emp as ta inner join (select dep_id,avg(age) as avg_num from emp group by dep_id) as tb on ta.dep_id = tb.dep_id where age>avg_num; #先将部门的平均年龄,员工名称查询出来作为表tb,然后通过内连接将tb和emp表进行合并,然后用where过滤。 查询每个部门最新入职的员工名字 select t1.name,t1.hire_date,t2.* from employee as t1 inner join (select post,max(hire_date) max_date from employee group by post) as t2 on t1.post = t2.post where t1.hire_date=t2.max_date;
#not null default create table t12 (name char(19) not null default 'aaaa'); insert into t12 values(); #传入空值,查询是aaaa ######key ###1.primary key 索引里面 primery 大于等于 not null unique 如果没有制定的话,InnoDB 会将第一个不为空,且唯一的字段当做主键。 ###2.unique 唯一 create talbe t13 (id int unique name char(19)); desc t13; +-------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+----------+------+-----+---------+-------+ | id | int(11) | YES | UNI | NULL | | | name | char(16) | YES | | NULL | | +-------+----------+------+-----+---------+-------+ insert into t13 values (1,'zym'), (1,'zzz'); 这样插入会报错,因为unique是唯一,不能有两个一样的id号"1". 也可以这样形式的插入 create table t15 (id int ,name char(19),unique(id)); ###联合唯一: 联合主键 联合唯一 create table t17 ( id int primary key auto_increment,host char(19),port int,unique(host,port)); 会报错: insert into t17 (host,port) values('1.1.1.1',3306),('1.1.1.1',3306); ERROR 1062 (23000): Duplicate entry '1.1.1.1-3306' for key 'host' ###3.foreign key ###4.index ###5.auto_increment (自增长) create table t16 (id int unique auto_increment); id 会随着你的插入自行增长。 指定步长: set global auto_increment_increment=2 #步长为2 show create table student; ter table student auto_increment=xxx;(只能设置成大于当前id的值) #设置步长 sqlserver:自增步长 基于表级别 create table t1( id int。。。 )engine=innodb,auto_increment=2 步长=2 default charset=utf8 mysql自增的步长: show session variables like 'auto_inc%'; #基于会话级别 set session auto_increment_increment=2 #修改会话级别的步长 #基于全局级别的 set global auto_increment_increment=2 #修改全局级别的步长(所有会话都生效) #!!!注意了注意了注意了!!! If the value of auto_increment_offset is greater than that of auto_increment_increment, the value of auto_increment_offset is ignored. 翻译:如果auto_increment_offset的值大于auto_increment_increment的值,则auto_increment_offset的值会被忽略 比如:设置auto_increment_offset=3,auto_increment_increment=2 mysql> set global auto_increment_increment=5; Query OK, 0 rows affected (0.00 sec) mysql> set global auto_increment_offset=3; Query OK, 0 rows affected (0.00 sec)