MySQL
Posted createtable
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL相关的知识,希望对你有一定的参考价值。
一 事务
事务:指逻辑上的一组操作,组成这组操作的各个逻辑单元,要么全都成功,要么全都失败。
事务的特性:
原子性:事务的不可分割,组成事务的各个逻辑单元不可分割。
一致性:事务执行的前后,数据完整性保持一致。
隔离性:事务执行不应该受到其他事务的干扰。
持久性:事务一旦结束,数据就持久化到数据库中。
如果不考虑隔离性,会引发一些安全问题,主要体现在读取数据上:
脏读: 一个事务读到了另一个事务未提交的数据,导致查询结果不一致
不可重复读:一个事务读到了另一个事务已经提交的update的数据,导致多次查询结果不一致。
虚读/幻读: 一个事务读到了另一个事务已经提交的insert的数据,导致多次查询结果不一致。
设置事务的隔离级别:
read uncommitted:脏读,不可重复读,虚读都有可能发生
read committed : 避免脏读。但是不可重复读和虚读是有可能发生
repeatable read : 避免脏读和不可重复读,但是虚读有可能发生
serializable : 避免脏读,不可重复读,虚读
设置事务隔离级别:SET SESSION TRANSACTION ISOLATION LEVEL 隔离级别
查看当前隔离级别:SELECT @@tx_isolation;
二 常用SQL语句
结构化查询语言(Structured Query Language)简称SQL
建库:
create database 数据库名;
create database 数据库名 character set 字符集;
查看所有库: show databases;
查看库定义信息: show create database 数据库名;
删库: drop database 数据库名称;
切换库: use 数据库名;
查看正在使用的数据库: select database();
建表:
create table 表名(
字段名 类型(长度) 约束,
字段名 类型(长度) 约束
);
查看所有表:show tables;
查看表结构:desc 表名;
删表:drop table 表名;
约束
A: 约束的作用:限制加入表的数据类型,限制每一列能写什么数据,不能写什么数据。用来保证数据完整性(多表之间)
create table 表名(
列名 类型(长度) 约束,
列名 类型(长度) 约束
);
B: 哪些约束:
主键约束
非空约束
唯一约束
外键约束
主键约束
* A:用于标识当前记录的字段。它的特点是非空,唯一。一般情况下主键不具备任何含义,只用于标识当前记录。
* B: 格式:
1.在创建表时创建主键,在字段后面加上 primary key.
create table tablename(
id int primary key,
.......
)
2. 在创建表时创建主键,在表创建的最后来指定主键
create table tablename(
id int,
.......,
primary key(id)
)
3.删除主键:alter table 表名 drop primary key;
4.主键自动增长:一般主键是自增长的字段,不需要指定。实现添加自增长语句,主键字段后加auto_increment(只适用mysql)
例如:
CREATE TABLE sort (
sid INT PRIMARY KEY auto_increment, #分类ID
sname VARCHAR(100) #分类名称
);
常见表的操作
修改表结构
* A: 添加列
alter table 表名 add 列名 类型(长度) 约束;
* B: 修改列的类型长度及约束
alter table 表名 modify 列名 类型(长度) 约束;
* C: 修改列名
alter table 表名 change 旧列名 新列名 类型(长度) 约束;
* D: 删除列
alter table 表名 drop 列名;
* E: 修改表名
rename table 表名 to 新表名;
* F: 修改表的字符集
salter table 表名 character set 字符集;
数据表添加数据_1
insert into 表 (列名1,列名2,列名3..) values (值1,值2,值3..); -- 向表中插入某些列
数据表添加数据_2
* A: 添加数据格式,不考虑主键
insert into 表名 (列名) values (值)
* B: 添加数据格式,所有值全给出
insert into 表名 values (值1,值2,值3..); --向表中插入所有列
* C: 添加数据格式,批量写入
insert into 表名 (列名1,列名2,列名3) values (值1,值2,值3),(值1,值2,值3)
更新数据
update 表名 set 字段名=值,字段名=值;
update 表名 set 字段名=值,字段名=值 where 条件;
* B: 注意:值如果是字符串或者日期需要加’’.
删除数据
delete from 表名 where 条件;
或者
truncate table 表名;
区别:
delete 一条一条删除,不清空auto_increment记录数。
truncate 直接删表并重新建表,auto_increment将置为零,从新开始。
* C: distinct用于去除重复记录
select distinct 字段 from 表名;
例如:
select distinct money from zhangwu;
sql语句的操作可以直接对列进行运算。
例如:将所有账务的金额+10000元进行显示.
select pname,price+10000 from product;
LIKE 通配符 -----------模糊查询,Like语句中有两个通配符:
% 用来匹配多个字符;例first_name like ‘a%’;
_ 用来匹配一个字符。例first_name like ‘a_’;
not ------------ 不成立,例:where not(salary>100);
聚合函数
* A: 聚合函数
* 之前我们做的查询都是横向查询,它们都是根据条件一行一行的进行判断,聚合函数查询是纵向查询,它是对一列的值进行计算,然后返回一个单一的值;聚合函数会忽略空值。
SELECT COUNT(*)AS‘count‘ FROM zhangwu
SELECT SUM(zmoney) FROM zhangwu
SELECT SUM(zname) FROM zhangwu WHERE zname LIKE‘%收入%‘
SELECT MAX(zmoney) FROM zhangwu
SELECT AVG(zmoney)FROM zhangwu
分组查询
* 分组查询是指使用group by字句对查询信息进行分组,例如:我们要统计出zhanguw表中所有分类账务的总数量,这时就需要使用group by 来对zhangwu表中的账务信息根据parent进行分组操作。
* SELECT 字段1,字段2… FROM 表名 GROUP BY 字段 HAVING 条件;
* 分组操作中的having子语句,是用于在分组后对数据进行过滤的,作用类似于where条件。
* b: having与where的区别
* having是在分组后对数据进行过滤.
* where是在分组前对数据进行过滤
* having后面可以使用分组函数(统计函数)
* where后面不可以使用分组函数。
* B: 案例代码
分组查询: group by 被分组的列名
必须跟随聚合函数
select 查询的时候,被分组的列,要出现在select 选择列的后面
SELECT SUM(zmoney),zname FROM zhangwu GROUP BY zname
-- 对zname内容进行分组查询求和,但是只要支出
SELECT SUM(zmoney)AS ‘getsum‘,zname FROM zhangwu WHERE zname LIKE‘%支出%‘
GROUP BY zname
ORDER BY getsum DESC
-- 对zname内容进行分组查询求和,但是只要支出, 显示金额大于5000
-- 结果集是分组查询后,再次进行筛选,不能使用where, 分组后再次过滤,关键字 having
SELECT SUM(zmoney)AS ‘getsum‘,zname FROM zhangwu WHERE zname LIKE‘%支出%‘
GROUP BY zname HAVING getsum>5000
在员工表上添加外键
alter table employee add foreign key (dno) references dept(did);
设置外键为非空
alter table employee modify dno int not null;
查询班级名称,和班级总人数
SELECT c.cname,COUNT(*) FROM classes c,student s
WHERE c.cid = s.cno
GROUP BY c.cname;
查询学生的姓名和学生所选的总课程平均成绩。
select s.sname,avg(sc.score) from student s,stu_cour sc
where s.sid = sc.sno
group by s.sname;
查询学生的姓名和学生的选课总数,显示选课超过2门学生姓名。
select s.sname,count(*) from student s,stu_cour sc
where s.sid = sc.sno
group by s.sname
having count(*) > 2;
查询平均成绩大于80分的学生的总数。
select count(*) from student s
where s.sid in (SELECT sc.sno FROM stu_cour sc GROUP BY sc.sno HAVING AVG(sc.score) > 80);
查询学生和平均成绩,但是平均成绩大于01班的任何一个学生的评价成绩。
SELECT s.sname,AVG(sc.score) FROM student s,stu_cour sc
WHERE s.sid = sc.sno
GROUP BY s.sname HAVING AVG(sc.score) > ANY(SELECT AVG(sc.score) FROM student s,stu_cour sc,classes c WHERE s.sid = sc.sno AND s.cno = c.cname AND c.cname =‘01班‘ GROUP BY s.sname);
三 SQL优化
1. 添加索引
1). 什么时候考虑添加索引? 数据量大; 查询频率高;
2). 针对什么样的字段添加索引? 经常在查询条件中出现的字段; 数据波动范围大字段;
3). 数据库表的索引太多会有什么影响? 可能影响插入的性能;
4). 索引的使用规则?
explain 解释器来查看select语句的执行计划 ;
比如 : explain select * from tbl_teacher where name = "zhangsan";
2. 尽量不适用 select * , 使用具体字段代替
3. where 和 having, where子句中不能跟组函数. 当使用where 和 having 都可以使用时, 尽量使用where.
1). select deptno, avg(sal) from emp where deptno = 10 group by deptno; ---> 先过滤,后分组, 分组的对象数据少, 效率高.
2). select deptno, avg(sal) from emp group by deptno having deptno = 10; ---> 先分组后过滤.
4. 如果需要查询多张表, 可以使用子查询, 也可以使用多表查询时, 理论上,尽量使用多表查询 ---> 因为性能高.
因为子查询, 对数据操作两次或多次, 而多表查询则只操作一次, 所以效率高---------> 不考虑笛卡尔积的情况下.
但是,如果表中的数据太多, 多表产生的笛卡尔积太大, 会影响多表查询的效率.
5. 尽量不使用集合运算.
参与运算的集合越多, 运行效率越低. UNION(并集) , UNION ALL(全并集) , INTERCEPT(交集) , MINUS(差集)
6. 尽量不适用in操作符.
ORACLE试图将其转换成多个表的连接,如果转换不成功则先执行IN里面的子查询,再查询外层的表记录,如果转换成功则直接采
用多个表的连接方式查询。由此可见用IN的SQL至少多了一个转换的过程
在业务密集的SQL当中尽量不采用IN操作符,用EXISTS 方案代替。
7. 强烈不建议使用 not in 操作符.因为它不能应用表的索引; 可以使用not exists来替代.
8. IS NULL 或IS NOT NULL操作(判断字段是否为空),判空一般是不会应用索引的,因为索引不索引空值;
用其它相同功能的操作运算代替,如:a is not null 改为 a>0 或a>’’等。不允许字段为空,
9. LIKE的模糊查询如果用的不好也会降低性能,如LIKE ‘%5400%‘ 这种查询不会引用索引,而LIKE ‘5400%‘则会使用索引
10. 查询表顺序的影响
以上是关于MySQL的主要内容,如果未能解决你的问题,请参考以下文章