MySQL常用操作彙總

MySQL之DDL常用命令

create database study1;
create database study2 character set gbk;
show databases;
show create database study2;
alter database study2 character set utf8;
show create database study2;
drop database study2;
use study1;
select database();
create table employee(
id int,
name varchar(20),
sex char(1),
birthday date,
job varchar(50),
salary double
);
show tables;
desc employee;
alter table employee add address varchar(100);
alter table employee modify  job varchar(30);
alter table employee drop address;
rename table employee to user;
show create table user;
alter table user character set gbk;
alter table user change name username varchar(20);
drop table user;

MySQL之DML常用命令

 delete只是刪除表中的數據,不刪除表,刪除後的數據可以恢復。
 truncate刪除是把表直接drop掉,然後再創建一個同樣的新表。刪除的數據不能找回。執行速度比delete快。

use study1;
create table emp(
id int,
name varchar(100),
sex char(6),
birthday date,
salary float(10,2)
);
insert into emp values (1,'andy','male','1995-05-15',10000);
insert into emp (id,name,sex,birthday,salary) values (2,'paul','male','1996-06-15',15000);
insert into emp (id,name,sex,birthday,salary) values (3,'lucy','female','1998-07-11',8000);
insert into emp (id,name,sex,birthday,salary) values (4,'james','male','1985-08-10',50000),
(5,'marry','female','1987-06-15',30000),
(6,'carter','male','1995-05-15',10000);
select * from emp;
update emp set salary=80000 where name='james';
delete from emp where name='lucy';
delete from emp;
truncate table emp; 

MySQL之DQL常用命令

create database monkey1024;
use monkey1024;
create table dept(
deptno int(2),
dname varchar(14),
loc varchar(13)
);
delete from dept;
insert into dept values(10,'accounting','new york');
insert into dept values(20,'research','dallas');
insert into dept values(30,'sales','chicago');
insert into dept values(40,'operations','boston');
select * from dept;
drop table dept;
create table emp(
empno int(4),
ename varchar(10),
job varchar(9),
mgr int(4),
hiredate date,
sal double(7,2),
comm double(7,2),
deptno int(2)
);
insert into emp values(7369,'smith','clerk',7902,'1980-12-17',800,null,20);
insert into emp values(7499,'allen','salesman',7698,'1981-02-20',1600,300,30);
insert into emp values(7521,'ward','salesman',7698,'1981-02-22',1250,500,30);
INSERT INTO emp values(7566,'JONES','MANAGER',7839,'1981-04-02',2975,NULL,20);
INSERT INTO emp values(7654,'MARTIN','SALESMAN',7698,'1981-09-28',1250,1400,30);
INSERT INTO emp values(7698,'BLAKE','MANAGER',7839,'1981-05-01',2850,NULL,30);
INSERT INTO emp values(7782,'CLARK','MANAGER',7839,'1981-06-09',2450,NULL,10);
INSERT INTO emp values(7788,'SCOTT','ANALYST',7566,'1987-04-19',3000,NULL,20);
INSERT INTO emp values(7839,'KING','PRESIDENT',NULL,'1981-11-17',5000,NULL,10);
INSERT INTO emp values(7844,'TURNER','SALESMAN',7698,'1981-09-08',1500,0,30);
INSERT INTO emp values(7876,'ADAMS','CLERK',7788,'1987-05-23',1100,NULL,20);
INSERT INTO emp values(7900,'JAMES','CLERK',7698,'1981-12-03',950,NULL,30);
INSERT INTO emp values(7902,'FORD','ANALYST',7566,'1981-12-03',3000,NULL,20);
INSERT INTO emp values(7934,'MILLER','CLERK',7782,'1982-01-23',1300,NULL,10);
select * from emp;
create table salgrade(
grade int(11),
hisal int(11),
losal int(11)
);
insert into salgrade values(1,1200,700);
insert into salgrade values(2,1400,1201);
insert into salgrade values(3,2000,1401);
insert into salgrade values(4,3000,2001);
insert into salgrade values(5,9999,3001);

select ename from emp;
select empno,ename from emp;
select * from emp;
select empno,ename,sal*12 from emp;
select empno,ename,sal*12 as yearsal from emp;
select empno,ename,sal*12 yearsal from emp;
select empno,ename,sal*12 as '年薪' from emp;
select empno,ename,sal from emp where sal=5000;
select empno,ename,job from emp where job='manager';
select empno,ename,sal from emp where sal<> 5000;
select empno,ename,sal from emp where sal>=1600 and sal<=3000;
select empno,ename,sal from emp where sal between 1600 and 3000;
select empno,ename,comm from emp where comm is null;
select empno,ename,comm from emp where comm is not null;
select empno,ename,job,sal from emp where job='manager' and sal>2500;
select ename,job from emp where job='salesman' or job='manager';
select * from emp where sal>1800 and (deptno=20 or deptno=30);
select ename,job from emp where job in('salesman','manager');
select ename,sal from emp where sal not in (1600,3000);
select ename from emp where ename like 'm%';
select ename from emp where ename like '%n';
select ename from emp where ename like '%o%';
select ename from emp where ename like '_a%';

MySQL排序和處理函數

select ename,sal from emp order by sal;
select ename,job,sal from emp where job='manager' order by sal;
select ename,sal from emp order by sal asc;
select ename,sal from emp order by sal desc;
select ename,job,sal from emp order by job desc,sal desc;
select * from emp order by 6;
select lower(ename) as ename from emp;
select upper(ename) as ename from emp;
select substr(ename,2,1) from emp;
select ename from emp where substr(ename,2,1)='a';
select ename from emp where ename like '_A%';
select ename,length(ename) as nameLength from emp;
select ename,ifnull(comm,0) from emp;
select sal+ifnull(comm,0) from emp;
select ename,(sal+ifnull(comm,100))*12 yearsal from emp;
select ename,sal,job,
(case job
	when 'manager' then sal*1.1
    when 'salesman' then sal*1.5
    else sal
end) as newsal
from emp;
select * from emp where job=trim('  manager  ');
select round(sal,1) from emp;
select rand(),sal from emp;
select round(rand()*100),sal from emp;
select ename,hiredate from emp where hiredate='1981-12-03';
select ename,hiredate from emp where hiredate = str_to_date('02-20-1981','%m-%d-%Y');
select ename,date_format(hiredate,'%m-%d-%Y') hiredate from emp;

MySQL分組和聚合函數

select sum(sal) from emp;
select sum(sal+ifnull(comm,0)) from emp;
select avg(sal) as avgsal from emp;
select max(sal) as maxsal from emp;
select max(hiredate) as lastemp from emp;
select min(sal) as minsal from emp;
select count(*) from emp;
select count(comm) from emp; /*count函數不會統計數據爲null的記錄*/
select count(*),sum(sal),avg(sal),max(sal),min(sal) from emp;
/*distinct去除重複記錄*/
select distinct job from emp;
select count(distinct job) from emp;
select distinct job,deptno from emp;
select sal from emp;
select max(sal) as maxsal from emp;
select max(sal) as maxsal from emp group by job; /*按職位分組,找出最高薪水*/
select job,max(sal) as maxsal from emp group by job;
/*在有group by的DQL詢問中,select語句後面只能跟聚合函數+參與分組的字段*/
select ename,job,max(sal) as maxsal from emp group by job;
select job,max(sal) as maxsal from emp group by job order by maxsal;
select deptno,avg(sal) as avgsal from emp group by deptno;
/*group by後面可以寫多個字段,數據庫會分別對這些字段進行分組*/
select deptno,job,max(sal) as maxsal from emp group by deptno,job;
select job,max(sal) as maxsal from emp where job <> 'manager' group by job;
/*下面寫法不正確,where後面不能直接使用聚合函數*/
select job,avg(sal) as avgsal from emp where avg(sal)>2000 group by job;
/*where和having的區別
where和having都是爲了完成數據的過濾,它們後面都是添加條件;
where是在group by之前完成過濾;
having是在group by之後完成過濾*/
select job,avg(sal) from emp group by job having avg(sal)>2000;
select xx from xx where xx group by xx having xx order by xx;
/*from:將硬盤上的表文件加載到內存
where:將符合條件的數據篩選出來。生成一張新的臨時表
group by:根據列中的數據種類,將當前臨時表劃分成若干個新的臨時表
having:可以過濾掉group by生成的不符合條件的臨時表
select:對當前臨時表進行整列讀取
order by:對select生成的臨時表,進行重新排序,生成新的臨時表
limit:對最終生成的臨時表的數據行,進行截取*/

MySQL之連接查詢

use monkey1024;
# emp和dept兩張表中數量的乘積
select e.ename,d.dname from emp e,dept  d;
select e.ename,d.dname from emp e,dept d where e.deptno = d.deptno;
select d.dname,e.ename from emp e join dept d on e.deptno=d.deptno;
# 內連接查詢出的數據是兩張表的交集,即上圖中C所表示的部分
select d.dname,e.ename from emp inner join dept d on e.deptno=d.deptno;
# inner可以省略
select d.dname,e.ename from emp e join dept d on e.deptno = d.deptno;
select e.ename,d.dname from emp e join dept d on e.deptno=d.deptno;
select e.name,e.sal,s.grade from emp e join salgrade s on e.sal between s.losal and s.hisal;
select a.ename empname,b.ename leadername from emp a join emp b on a.mgr=b.empno; # 自連接
/*左外連接包含左邊表的全部行(不管右邊的表是否存在與它匹配的行),和
右邊表中全部匹配的行*/
select e.ename,d.dname from dept d left outer join emp e on e.deptno=d.deptno;
# outer可以省略
select e.ename,d.dname from dept d left join emp e on e.deptno=d.deptno;
/*右外連接包含右邊表的全部行(不管左邊的表中是否存在與它匹配的行),和
左邊表中全部匹配的行*/
select e.ename,d.dname from emp e right outer join dept d on e.deptno=d.deptno;
#outer可以省略
select e.ename,d.dname from emp e right join dept d on e.deptno=d.deptno;
# 右外連接都可以改寫成左外連接,左外連接都可改寫成右外連接
select a.ename empname,b.ename leadername from emp a left join emp b on a.mgr=b.empno;
select e.ename,d.dname,e.sal,s.grade
from emp e join dept d on e.deptno=d.deptno
join salgrade s on e.sal between s.losal and s.hisal;

MySQL查詢其他內容

# select語句嵌套select語句被稱爲子查詢
select ename,sal from emp where sal>(select avg(sal) from emp);
select t.deptno,t.avgsal,s.grade from
salgrade s join (select deptno,avg(sal) as avgsal from emp group by deptno) t on t.avgsal
between s.losal and s.hisal order by t.deptno;
# 使用union合併結果,合併結果集時查詢字段的個數必須一致
select empno,ename,job from emp where job='manager' union
select empno,ename,job from emp where job='salesman';
/*limit
limit起始下標m,長度n,
m:記錄開始的index,默認從0開始,表示第一條記錄;
n:指從第m+1條開始,取n條;*/
select * from emp limit 0,5;
select * from emp limit 5;
select ename,sal from emp order by sal desc limit 0,5;
select ename,sal from emp order by sal desc limit 5;
select ename,sal from emp order by sal desc limit 2,7;

MySQL存儲引擎簡介

什麼是存儲引擎?

存儲引擎是通過採用不同的技術將數據存儲在文件或內存中,不同的技術有不同的存儲機制,其功能和能力也不同,通過選擇不同的技術,可以獲得特殊的速度或功能,從而提高應用的性能,存儲引擎是MySQL特有的

常用的存儲引擎

MyIsam

節省數據庫空間,當數據讀遠大於修改時,可以使用該存儲引擎

InnoDB

支持事務,如果數據修改較多時,可以使用該存儲引擎

Memory

存儲在內存中,速度快,如果存儲非永久性數據時,可以使用該存儲引擎

 

show engines;
create table table_name(
no int)engine=myisam;
alter table table_name engine=innodb;
show create table emp;

事務transaction

什麼是事務

通常一個事務對應一個完整的業務,例如銀行轉賬,事務可以保證多個操作原子性,要麼全部成功要麼全部失敗

1001的賬戶向1002的賬戶進行轉賬500元的操作,此時將會執行兩條SQL語句

update t_bank set money=500 where account=1001;
update t_bank set money=2500 where account=1002;

如果上面的sql語句第一條執行成功了,但是由於某些原因第二條sql語句執行失敗了,此時賬戶1001上的金額變成了500,而賬戶1002上的金額是2000,這樣就不正確了。
爲了能夠正常的執行業務,上面兩條sql語句要麼全部執行成功,要麼全部執行失敗,因爲他們是最小的業務單元,不能再進行拆分了。

當一條sql語句執行結束後,並不會立即修改數據庫表中的數據,而是在內存中記錄一下,第二條sql語句執行成功後,纔會修改數據庫表中的數據,如果第二條sql語句執行失敗了,則將清空內存中的記錄,此時並不會修改數據庫表中的數據,要實現這樣的功能,就必須使用事務來完成。

事務具有四個特徵

原子性:

事務是最小單元,不可再分;

一致性:

事務要求所有的DML語句操作的時候,必須保證同時成功或同時失敗;

隔離性:

一個事務不會影響其他事務的執行

持久性:

在事務完成之後,該事務對數據庫所作的更改將持久地保存在數據庫中,並不會被回滾;

MySQL事務的提交和回滾

MySQL中默認情況下,事務是自動提交的,當執行一條DML語句時,就開啓並且自動提交了事務。可以通過下面的語句查看事務是否是自動提交的:

show variables like '%commit%';

如果想要關閉MySQL事務的自動提交,可以使用下面語句手動開啓事務:

create table t_bank(
account int(10) primary key,
money int(15)
);
insert into t_bank values (1001,1000),(1002,2000);
select * from t_bank;
start transaction;
update t_bank set money=500 where account=1001;
update t_bank set money=2500 where account=1002;
# 此時事務將會回滾,清空內存中的記錄,不會修改數據庫中的字段值
rollback;
# 提交事務
commit;

事務的隔離級別

read uncommitted讀未提交

事務A和事務B,事務A未提交的數據,事務B可以讀取,這裏讀取到的數據叫做“髒數據”,該級別最低,一般只是理論上存在,數據庫的默認隔離級別都高於該級別。

read committed讀已提交

事務A和事務B,事務A提交的數據,事務B纔可以讀取到,換句話說:對方事務提交之後的數據,當前事務纔可讀取到,可以避免讀取髒數據,但是改級別會有不可重複讀的問題,事務B讀取一條數據,當事務A修改這條數據並提交後,事務B再讀取這條數據時,數據發生了變化,即事務B每次讀取的數據有可能不一致,這種情況叫做“不可重複讀".

repeteable read重複讀

MySQL默認的隔離級別是重複讀,該級別可以達到”重複讀“的效果,但是會有”幻讀“的問題,即事務A 讀取數據,此時事務B修改了這條數據,但是事務A讀取的還是之前的舊數據,這樣就出現了幻讀。

serializable 串行化


事務A和事務B,事務A在操作數據庫表中數據的時候,事務B只能排隊等待,這樣保證了同一個時間點上只有一個事務操作數據庫,該級別可以解決“幻讀”的問題。但是這種級別一般很少使用,因爲吞吐量太低,用戶體驗不好。

MySQL索引和視圖

索引的作用

索引相當於一本字典目錄,能夠提高數據庫的查詢效率,表中每一個字段都可添加索引。主鍵會自動添加索引,在查詢時,如果能通過主鍵查詢的儘量使用主鍵查詢,效率高。
MySQL數據庫表中的檢索方式有兩種:

  • 全表掃描(效率低)
    例如:select * from emp where ename = ‘KING';如果ename字段沒有添加索引的話,就會發生全表掃描。
  • 通過索引檢索

什麼情況下適合添加索引

  • 該字段數據量龐大;
  • 該字段很少的DML操作(由於索引也需要維護,DML操作多的話,也影響檢索效率);
  • 該字段經常出現在where條件中;

注意:實際開發中會根據項目需求等綜合因素來做調整,添加索引並不能保證一定能夠提升檢索效率,索引添加不當也有可能會導致效率降低。

create index 索引名 on 表名 (列名);
create index dept_dname_index on dept(dname);
# 查看索引
show index from 表名;
show index from dept;
# 刪除索引
drop index 索引名 on 表名;
drop index dept_dname_index on dept;
/*視圖
視圖其實就是一個查詢結果,視圖的作用可以隱藏表的實現細節*/
create view 視圖名稱 as 查詢語句;
create view e_info as select empno,ename,sal from emp;
# 使用視圖
select * from e_info;
# 修改視圖
alter view 視圖名稱 as 查詢語句
alter view e_info as select ename,job from emp;
# 刪除視圖
drop view if exists 視圖名稱;
drop view if exists e_info;

練習

use monkey1024;
select deptno,max(sal) as maxsal from emp group by deptno;
select e.ename, t.deptno,t.maxsal from emp e join
(select deptno,max(sal) as maxsal from emp group by deptno) t on e.deptno=t.deptno
where t.maxsal = e.sal;
select deptno,avg(sal) as avgSal from emp group by deptno;
select e.ename,t.deptno,e.sal from emp e join
(select deptno,avg(sal) as avgSal from emp group by deptno) t on e.deptno=t.deptno
where e.sal>t.avgSal;
select deptno,avg(sal) as avgSal from emp group by deptno;
select t.deptno,t.avgSal,s.grade from salgrade s join (select deptno,avg(sal) as avgSal from emp group by deptno) t
on t.avgSal between s.losal and s.hisal;
select ename,sal from emp order by sal desc limit 0,1;
select deptno,avg(sal) from emp group by deptno;
select max(t.avgSal) as maxSal from (select deptno,avg(sal) as avgSal from emp group by deptno) t;
select deptno,avg(sal) as avgSal from emp group by deptno
having avgSal = (select max(t.avgSal) as maxSal from (select deptno,avg(sal) as avgSal from emp group by deptno ) t);
select deptno,avg(sal) as avgSal from emp group by deptno order by avgSal desc limit 0,1;
select d.dname, t.deptno,t.avgSal from dept d join 
(select deptno,avg(sal) as avgSal from emp group by deptno order by avgSal desc limit 0,1) t on d.deptno=t.deptno;
select deptno,avg(sal) as avgSal from emp group by deptno;
select distinct mgr from emp where mgr is not null;
select max(sal) as maxSal from emp where empno not in(select distinct mgr from emp where mgr is not null);
select e.ename from emp e join (select distinct (mgr) as mgr from emp where mgr is not null) t on e.empno =t.mgr where 
e.sal>(select max(sal) as maxSal from emp where empno not in (select distinct (mgr) from emp where mgr is not null));
select e.empno,s.grade from emp e join salgrade s on e.sal between s.losal and s.hisal;
select t.grade,count(t.empno) from (select e.empno,s.grade from emp e join salgrade s on e.sal between s.losal and s.hisal) t group by t.grade;
select a.empno,a.ename,a.hiredate from emp a join emp b on a.mgr = b.empno where a.hiredate < b.hiredate;
select count(e.empno),e.deptno from emp e group by e.deptno having count(e.empno)>=5;
select d.dname from dept d join (select count(e.empno),e.deptno from emp e group by e.deptno having count(e.empno)>=5) t on d.deptno=t.deptno;
select job,min(sal) as minSal from emp group by job having min(sal)>1500;
select job,min(sal) as minSal,count(*) as total from emp group by job having min (sal)>1500;
select deptno from dept where dname='salse';
select e.ename from emp e where e.deptno=(select deptno from dept where dname='sales');
select d.dname,count(e.ename) as total,sum(e.sal) as totalSal from emp e right join dept d on e.deptno=d.deptno group by d.dname;
select d.dname,count(e.ename) as total,sum(e.sal) as totalSal from emp e right join dept d on e.deptno=d.deptno 
where d.dname like '%s%' group by d.dname;




面試題

有3個表S(學生表),C(課程表),SC(學生選課表)
S(SNO,SNAME)代表(學號,姓名)
C(CNO,CNAME,CTEACHER)代表(課號,課名,教師)
SC(SNO,CNO,SCGRADE)代表(學號,課號,成績)
問題:

  1. 找出沒選過“黎明”老師的所有學生姓名。
  2. 列出2門以上(含2門)不及格學生姓名及平均成績。
  3. 即學過1號課程又學過2號課所有學生的姓名。

初始化數據:

drop table if exists sc;
create table sc(
sno varchar(200),
cno varchar(200),
scgrade varchar(200)) default charset=utf8;
drop table if exists c;
create table c(
cno varchar(200),
cname varchar(200),
cteacher varchar(200)) default charset=utf8;
drop table if exists s;
create table s(
sno varchar(200),
sname varchar(200)) default charset=utf8;
desc sc;
insert into c (cno,cname,cteacher) values ('1','語文','張');
insert into c (cno,cname,cteacher) values ('2','政治','王');
insert into c (cno,cname,cteacher) values ('3','英語','李');
insert into c (cno,cname,cteacher) values ('4','數學','趙');
insert into c (cno,cname,cteacher) values ('5','物理','黎明');

insert into s (sno,sname) values ('1','學生1');
insert into s (sno,sname) values ('2','學生2');
insert into s (sno,sname) values ('3','學生3');
insert into s (sno,sname) values ('4','學生4');

insert into sc (sno,cno,scgrade) values ('1','1','40');
INSERT INTO sc (sno,cno,scgrade) VALUES ( '1', '2', '30'); 
INSERT INTO sc (sno,cno,scgrade) VALUES ( '1', '3', '20'); 
INSERT INTO sc (sno,cno,scgrade) VALUES ( '1', '4', '80'); 
INSERT INTO sc (sno,cno,scgrade) VALUES ( '1', '5', '60'); 
INSERT INTO sc (sno,cno,scgrade) VALUES ( '2', '1', '60'); 
INSERT INTO sc (sno,cno,scgrade) VALUES ( '2', '2', '60'); 
INSERT INTO sc (sno,cno,scgrade) VALUES ( '2', '3', '60'); 
INSERT INTO sc (sno,cno,scgrade) VALUES ( '2', '4', '60'); 
INSERT INTO sc (sno,cno,scgrade) VALUES ( '2', '5', '40'); 
INSERT INTO sc (sno,cno,scgrade) VALUES ( '3', '1', '60'); 
INSERT INTO sc (sno,cno,scgrade) VALUES ( '3', '3', '80'); 
select * from s;
select cno from c where cteacher='黎明';
select sno from sc where CNO='5';
select sno,sname from s where sno not in (select
sno from sc where cno=(select cno from c where cteacher='黎明'));
select sno from sc where scgrade<60 group by sno having count(*)>=2;
select t2.sn,avg(t1.scgrade) as avgScgrade from
sc t1 join (select sno from sc where scgrade<60 group by sno having count(*)>=2) t2 on t1.sno=t2.sno group by t2.sno;
select s.sname from s join (select t1.sno from (select sno from sc where cno=1) t1 join (select sno from sc where cno=2) t2 
on t1.sno=t2.sno) t3 on s.sno=t3.sno;

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章