比如:查询员工年薪(字段可以参与数学运算):
再比如把年薪的查询结果那个字段重命名为年薪yearsal:
若想用中文年薪,那必须在年薪上加单引号:‘年薪’
查询工资为5K的员工姓名:
查询名字为SMITH员工的工资(注意字符串类型(varchar)查询要加单引号‘ ’):
找出工资大于3k的员工:
找出工资不等于3k的员工(不等于为:<>):
select ename from emp where sal <> 3000;
找出工资在1100和3000之间的员工:
select enma ,sal from emp where sal>=1100 and sal <= 3000;
或者:
select ename , sal from emp where sal between 1100 and 3000;
但是注意:between and中的这两个数据,大小不能颠倒,前小后大,否则会找不到数据。。。
查询名字在between ‘A’ and 'C’的员工:
select ename from emp where ename between ‘A’ and ‘C’;
查询名字在between ‘A’ and 'D’的员工:
select ename from emp where ename between ‘A’ and ‘D’;
找出哪些津贴为空(不是为0,是null)的员工:
select ename from emp where comm is null;
找出津贴为0的员工:
select ename from emp where comm = 0;
找出津贴为null以及为0的员工:
select ename from emp where comm is null and comm = 0;
找出津贴不为null以及为0的员工:
select ename from emp where comm is not null;
找出工作岗位为manager和salesman的员工:
select ename , job from emp where job = ‘manager’ or job = ‘salesman’;
找出薪资大于1000并且部门编号为20或者30部门的员工:
select ename , sal, deptno from emp where sal > 1000 and (deptno = 20 or deptno = 30);
找出名字中含有o的员工:
select ename from emp where ename like ‘%o%’;
找出名字中第二个字母是A的员工:
select ename from emp where ename like ‘_A%’;
找出名字带有下划线_的员工:使用转义字符\来表示:
select ename from emp where ename like ‘%_%’;
按照工资升序,找出员工名和薪资:
select ename , sal from emp order by sal;
按照工资降序,找出员工名和薪资:
select ename , sal from emp order by sal desc;
按照工资降序排列,当工资相同时,按照名字升序排列:
select ename , sal from emp order by sal desc , ename asc;
按照第二列的大小进行排序:
select ename , sal from emp order by 2;
找出工作岗位是salesman,并且要求薪资按照降序排列:
select ename ,job , sal from emp where job = ‘salesman’ order by sal desc;
找出工资高于平均公司的员工:
错误范例:
select ename , sal from emp where sal >avg(sal);
###注意 :SQL语句的语法规则中,分组函数不可以直接使用在where子句中,因此上述代码出错。
正确格式:
方案一:可以分成两步:首先求出平均,然后sal>平均sal即可
方案二:即将上述两步合并即可(语句的嵌套,又称为子查询)
select ename ,sal from emp where sal >(select avg(sal) from emp );
具体到某个字段,count记录的是该字段不为空的记录数;
而count(*),统计的是总记录条数,与具体的某个字段无关。
比如:
select count(*) , sum(sal) , avg(sal) , min(sal) , max(sal) from emp;
比如计算每个员工的年薪(月薪+月补助相加再乘12):
select ename , (sal + comm) * 12 as yearsal from emp;
仍以上述的计算每个员工的年薪(月薪+月补助相加再乘12):
select ename , (sal + ifnull(comm,0) * 12) as yearsal from emp;
如果使用ifnull,此时再次对comm进行计数:
select count( ifnull(comm , 0) ) from emp;
比如找出每个工作岗位的最高薪资:
错误范例:
select ename, sal group by ‘salesman’ having max(sal);
正确代码:
select job, max(sal) from emp group by job;
错误示例:
每个工作岗位的平均薪资:
select job , avg(sal) from emp group by job;
找出每个部门不同工作岗位的最高薪资:
select max(sal), job , deptno from emp group by deptno , job;
找出每个部门的最高薪资,同时要求显示薪资大于2500的数据:
方式一:select ename, max(sal) from emp group by deptno having max(sal) > 2500;
但是这种效率比较低
方式二:
select deptno , max(sal) from emp where sal > 2900 group by deptno;
这种方式相比第一种效率高,因为先过滤掉sal>2900的,再按照部门求;而第一种先求出各个部门的最高薪资,然后部门编号30的因为最高薪资2850小于2900被过滤掉了,那么寻找部门编号30的最高薪资的工作相当于白干了。
找出每个部门的平均薪资,要求显示薪资大于2000的数据:
错误范例:
select deptno, avg(sal) from emp where (select avg(sal) from emp) > 2000 group by deptno;
以上并没有把小于2000的过滤掉,why???
正确代码:
select deptno, avg(sal) from emp group by deptno having avg(sal) >2000;
比如:
查询公司的工作岗位:
select distinct job from emp;
比如:
select ename, distinct job from emp;
会报语法错误。从逻辑上也很好分析:distinct去重之后,剩下的job岗位(5个)肯定少于表中的总记录数14条,而ename是公司每个员工的记录表,14名员工的ename和5种工作岗位是无法在表中正确显示的。
再比如:
select distinct deptno , job from emp;
统计岗位的数量:
select count(distinct job) from emp;
比如:
select ename , dname from emp , dept;或者
select e.ename , d,dname from emp as e, dept as d;(结果一样,只是可读性和执行效率提高了)
表长完整图略
注意:避免了笛卡尔积现象,并不会减少记录的匹配次数,只是输出的结果少了(因为通过添加限制,得出我们想要的有效记录,去除无效或者无用的记录)
找出每一个员工的部门名称,要求显示员工名和部门名:
方法一(sql92旧方法):
select
e.ename , d.dname
from
emp as e , dept as d
where e.deptno = d.deptno;
方法二(sql99常用):主要是把连接条件和过滤条件分开了,连接条件用join on,过滤条件用where,更加清晰
select
e.ename , d.dname
from
emp as e
join
dept as d
on
e.deptno = d.deptno;
找出每个员工的工资等级,要求显示员工名、工资、工资等级:
select
e.ename,e.sal,s.grade
from
emp as e
inner join
salgrade as s
on
e.sal between s.losal and s.hisal;
找出每个员工的上级领导,要求显示员工名和对应的领导命:
即在同一张emp表中进行查找,但是在第一张表中所有人都是员工,在第二张表中全为领导,然后进行联合查询
select
e1.name ,e2.name
from
emp as e1
inner join
emp as e2
on
e1.mgr = e.empno;
select
e1.name as '员工名' ,e2.name as '领导名'
from
emp as e1
inner join
emp as e2
on
e1.mgr = e.empno;
仍以上面的那额查询出所有员工的上级领导(要求所有员工都查到,包括那个KING),此时用左外连接(以e1员工表作为主表):
select
e1.name as '员工名' ,e2.name as '领导名'
from
emp as e1
left join
emp as e2
on
e1.mgr = e.empno;
此时,即使KING没有上级领导,但是同样输出了。
也可以用右外连接:
select
e1.name as '员工名' ,e2.name as '领导名'
from
emp as e2
right join
emp as e1
on
e1.mgr = e.empno;
这里的左和右,其实就是为了确定将哪个表作为主表。
找出哪个部门没有员工:
错误范例:
select d.dname , count(e.ename) from dept as d left join emp as e where e.deptno = d.deptno;
正确代码:
select
d.*
from
dept as d
left join
emp as e
on
e.deptno = d.deptno
where
e,ename is null;
select
d.* , count(e.ename)
from
dept as d
left join
emp as e
on
e.deptno = d.deptno
where
e,ename is null;
找出每名员工的部门名称以及员工等级:
先找出员工的部门名称:
select e.name , e.empno , e.deptno from emp e left join dept d where e.deptno = d.deptno;
再找出每名员工的员工等级:
select e.ename, e.empno ,e.deptno , s.grade from emp e left join salgrade s on e.sal between losal and hisal;
将二者结合一下:
select
e.ename , d.dname , 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;
找出每一个员工的部门名称,工资等级以及上级领导(由于emp中存在员工KING的上级领导是null的情况,因此为了保证输出结果中包括每一名员工,必须采用外连接):
select
e1.ename , e2.name , d.dname , s.grade
from
emp e1
left join
emp e2
on
e1.mgr = e2.empno
join
dept d
on
e1.deptno = d.deptno
join
salgrade s
on
e1.sal between s.losal and s.hisal;
select
e1.ename , d.dname , s.grade , e2.ename
from
emp e1
join
dept d
on
e1.deptno = d.deptno
join
salgrade s
on
e1.sal between s.losal and s.hisal
left join
e1.mgr = e2.empno;
之前讲过,如:找出薪资高于平均薪资的员工信息:
select * from emp where sal >(select avg(sal) from emp);
找出每个部门平均薪水的薪资等级(这个没写出来):
首先:平均薪水:
select deptno , avg(sal) from emp group by deptno;
然后将上一步的执行结果作为一个新表,进行查询:
错误范例(语法错误,a.avg不合法):
select a.deptno , a.avg(sal) , s.grade from (select deptno , avg(sal) from emp group by deptno) a , salgrade s where a.avg(sal) between s.losal and s.hisal;
正确代码:
select
t.* , s.grade
from
(select deptno , avg(sal) as avgsal from emp group by deptno) as t
join
salgrade as s
on
t.avgsal between s.losal and s.hisal;
找出每个员工做在的部门名称,要求显示员工名和部门名:
select e.ename , d.dname from emp e, dept d where e.deptno = d.deptno;
还可以使用嵌套子查询的方式:
select
e.ename , (select d.dname from dept d where e.deptno = d.deptno) as dname
from
emp e;
找出工作岗位是salesman和manager的员工:
方法一:select e.ename , e.job from emp e where e.job = ‘salesman’ or e.job = ‘manager’;
方法二:select ename, job from emp where job in (‘salesman’ , ‘manager’);
方法三:使用union
select ename , job from emp where job = 'salesman'
union
select ename , job from emp where job ='manager';
取出工资前五名的员工(思路就是降序取出前5个):
select ename , sal , job from emp order by sal desc limit 0 , 5;
默认从0开始,如果从0开始查询,可以缺省0
找出工资排名第四名到第九名的员工:
select ename , job ,sal from emp order by sal desc limit 3,6;
每页显示3条记录:
第1页:0,3
第2页:3,3
第3页:6,3
第4页:9,3
第5页:12,3
每页显示pageSize条记录:
第pageNo页:(pageNo-1)*pageSize , pageSize
建表语句格式:
create table 表名(
字段名1 数据类型,
字段名2 数据类型,
字段名3 数据类型,
....
);
比如:出生日期:yyyy-mm-dd 标准10个长度 用char;性别:男/女,标准1个长度,用char;
比如:姓名:中文有两个字,有三个字,有四个字的,用varchar;
创建学生表:
学生信息包括:学号(bigint)、姓名(varchar)、性别(char)、班级编号(varchar)、生日(char)
create table t_student(
stuno bigint,
name varchar(255),
sex char(1),
classno varchar(255),
birthday char(10)
);
语法格式:
insert into 表名(字段名1,字段名2,字段名3,...) values(值1,值2, 值3,...);
要求:字段的数量要和值的数量相同,并且数据类型要对应相同。
向学生信息表中插入数据:
insert into t_student(stuno , name , sex , classno , birthday) values(1 , 'ykk' , 'm' , 'gaosan0ban' , '2000-01-31');
insert into t_student(stuno , name , sex) values(5, 'zhangsan' , 'f');
这是因为我们在创建表的时候,设置了各个字段的默认值(若不手动设置,会默认值为null):
create table t_student(
stuno bigint,
name varchar(255),
sex char(1) default 'm',
classno varchar(255),
birthday char(10) default '1970-01-01'
);
此时再插入一个:
insert into t_student(stuno , name ) values(5, 'zhangsan');
比如:
insert into t_student values(2 , 'lisi' , 'f' , 'gaosan0ban' , '2000-01-24' );
insert into t_student(stuno , name , sex , classno , birthday) values(10 , 'rose' , 'f' , 'Titanic' , '1975-10-23'),(11 , 'jack' , 'm' , 'Titanic' ,'1972-12-03');
语法:
create table 表名 as select 语句;
//这里其实是将查询结果当做表创建出来
比如完全复制一张表:
create table emp1 as select * from emp;
create table emp2 as select empno , ename from emp;
比如我们先创建一张表:
create table dept1 as select * from dept;
再将dept表插入dept1中:
insert into dept1 select * from dept;
语法格式:
update 表名 set 字段名1 = 值1, 字段名2 = 值2... where 条件;
// 倘若后面不加条件,整张表的数据都会全部更新
将dept1 表中部门编号为10 的LOC 修改为shanghai,将部门名称修改为renshibu:
update dept1 set LOC = 'SHANGHAI' , DNAME = 'RENSHIBU' where deptno = 10;
update dept1 set LOC = 'BEIJING' , DNAME = 'YANFA';
语法格式:
delete from 表名 where 条件;
注意:不加条件,会删除整张表;
删除dept1表中部门10 的数据:
delete from dept1 where DEPTNO = 10;
delete from dept1;
truncate table 表名;
在创建表时,可以给表的字段添加相应的约束,其目的是为了保证表中数据的合法性、有效性、完整性。
先创建个表做测试:
create table t_users(
id int ,
username varchar(255) not null ,
password carchar(255)
);
此时,给username字段添加了非空约束,我们此时插入一条数据:
insert into t_user(id , password) values(1 , '123');
因此,设置了非空约束的字段,插入时必须要赋值,不能为null。
新建一个用户表,要求用户名字段不能重复(即要求有唯一性):
create table u_users(
id int ,
username varchar(255) unique,
password varchar(255)
);
然后向表中插入两条username均为jack的记录:
insert into t_users values(1, 'jack' ,'123');
insert into t_users values(2, 'jack' ,'456');
比如:
插入两条username为空的记录是允许的:
insert into t_users(id , password) values(2 , '456'),(2, '789');
比如:不允许username和usercode都相同(要和既不允许username相同,又不允许usercode相同区别开):
create table t_users(
id int ,
username varchar(255),
usercode varchar(255),
unique(username , usercode)// 表级约束
);
此时,插入以下数据测试:
insert into t_users values(1 , '111' , 'zs');
insert into t_users values(2 , '111' , 'ww');
insert into t_users values(3 , '222' , 'zs');
是可以在username不同的前提下允许usercode重复,反之亦可;
即username和usercode联合起来不能重复。
而考虑如下情况:
create table t_users(
id int ,
username varchar(255) unique,// 列级约束
usercode varchar(255) unique
);
此时再插入上例中的相同三条数据:
insert into t_users values(1 , '111' , 'zs');
insert into t_users values(2 , '111' , 'ww');
insert into t_users values(3 , '222' , 'zs');
此时,usercode字段值不允许重复,username字段值也不允许重复,即两个字段分别都不允许重复。
例:
create table t_users(
id int primary key ,
username varchar(255) ,
password varchar(255)
);
插入3条数据:
insert into t_users values(1 , 'jack' , '123');
insert into t_users values(2, 'rose' , '456');
insert into t_users values(3 , 'ben' , '789');
insert into t_users values(1 , 'simmons' , '321');
insert into t_users( username , password) values( 'simmons' , '321');
create table t_user(
id int primary key auto_increment ,
username varchar(255)
);
不给主键赋值,插入数据:
insert into t_user( username ) values('jack');
insert into t_user( username ) values('rose');
insert into t_user( username ) values('jackson');
insert into t_user( username ) values('robin');
在数据库中如何维护班级和学生表?
第一种方案:将学号、姓名、班级代码、班级全称放在一张表中维护。
缺点:冗余。
第二种方案:
删表先删子表再删子:
drop if exists t_class;
drop if exists t_student;
建表先创建父表再创建子表:
create table t_class(
cno int ,
cname varchar(255) ,
primary key(cno)
);
create table t_student(
sno int ,
sname varchar(255) ,
classno int ,
foreign key(classno) references t_class(cno)
);
insert into t_class values(101 , 'cs1001');
insert into t_class values(102 , 'cs1002');
insert into t_class values(103 , 'cs1003');
insert into t_student values(18611 , 'jack' , 101);
insert into t_student values(18522 , 'rose' , 102);
insert into t_student values(18933, 'robin' , 103);
insert into t_student values(18844, 'ben' , 104);
insert into t_student values(123678, 'sophia' , null);
指定存储引擎的完整的表语句:
create table t_x(
id int default null
)ENGINE = InnoDB DEFAULT CHARSET = utf8;
mysql默认存储引擎是InnoDB,默认字符集CHARSET是utf8.
查看当前mysql使用的存储引擎:
show engines \G;
演示1:mysql中的事务支持自动提交,只要执行一条DML语句,就会自动提交一次。
执行rollback并不能将插入的记录删除,说明插入username为john这条语句作为事务已经提交,因此不可回滚。
演示2:使用start transaction关闭自动提交机制(标志着事务执行的开始):
start transaction;
然后再插入数据:
insert into t_user(username) values('simmons');
insert into t_user(username) values('joe');
然后回滚rollback,查看此时的t_user表中记录:
设置事务的全局隔离级别
set global transaction isolation level 具体级别(包括read uncommitted , read committed , repeatable-read , serializable );
查看当前事务的全局隔离级别
select @@global.tx_isolation;
添加索引:
create index 索引名 on 表名(字段名);
例如:
create index emp_sal_index on emp(sal);
删除索引:
drop index 索引名 on 表名;
例如:
drop index emp_sal_index on emp;
创建视图:
create view myview as select empno , ename from emp;
// 只有DQL语句才能以视图对象的方式创建出来。
删除视图:
drop view myview;
通过视图修改原表数据:
update myview set enam = 'hehe' , sal = 1 where empno = 7369;
通过视图删除原表数据:
delete from myview where empno = 7369 ;
create user username(用户名) identified by password(密码);
//例如:
create user jack identified by 123;
// grant to
grant all privileges on dbname , tbname to 'username'@'login ip' identified by 'password' with grant option;
// 例如:
grant all privileges on *.* to 'jack'@localhost identified by '123';
//如果希望在任何机器登陆mysql,只需将localhost改为%
revoke privileges on dbname[.tbname] from username;
// 例如:
revoke all privileges on *.* from jack;
导出整个数据库:
在dos窗口下执行此命令(不要登入到mysql执行)
mysqldump 数据库名 >要导出的地址路径 -u用户名 -p密码;
// 例如:
mysqldump bjpowernode>D:bjpowernode.sql -uroot -p;
导出指定表:
mysqldump 数据库名 要导出的表名>要导出的路径 -u用户名 -p密码;
//例如:
mysqldump bjpowernode emp>D:bjpowernode.sql -uroot -p;
先创建数据库:
create database bjpowernode;
use bjpowernode;
然后 source + 文件拖拽即可(或者sql文件绝对路径);
任何一张表都应该有主键,并且每一个字段原子性不可再分。
建立在第一范式的基础之上,所有非主键字段完全依赖主键,不能产生部分依赖(只有复合主键才会存在部分依赖,单一主键不存在部分依赖)。
建立在第二范式的基础之上,所有非主键字段直接依赖主键,不能产生传递依赖。
1.取得每个部门薪水最高的人员名称
错误示范:
select ename , deptno , max(sal) from emp group by deptno;
// 第一步 先取出各个部门的最高薪水
select deptno , max(sal) as maxsal from emp group by deptno;
// 第二步
select
e.ename , t.*
from
(select deptno , max(sal) as maxsal from emp group by deptno) t
join
emp e
on
t.deptno = e.deptno and t.maxsal = e.sal;