SQL的基本语法规范
1、sql不区分大小写,但是习惯上关键字、系统保留字、函数名称大写,表名和列名小写;
2、sql使用空格或者回车来分隔每个单词都一样,习惯上每个子句换行,WHERE子句中的每个条件占一行,子查询单独占一行;
3、复杂的语句最好加上注释进行说明;
4、sql语句中使用分号作为分隔符,系统读取到分号才会执行语句。
DDL是用于描述数据库中要存储的现实世界实体的语言,主要是用在定义或改变结构,数据类型,表之间的链接和约束等初始化工作上,大多在建立表时使用。
1.CREATE
create命令为创建,可创建数据库、数据表、存储过程。
创建数据库 create database
在登录MySQL服务后,使用create命令创建数据库,语法为:create database name;
创建数据表 create table
必须要有创建表的权限,表名,列名可以由字母、数字和下划线组成,必须以字母开头,不能是系统关键字
create table 表名(列名1 数据类型,列名2 数据类型,……列名n 数据类型);
/注释:创建test表/
CREATE TABLE test
(
#注释:属性(列名)testid,整数类型
testid INT,
testname VARCHAR(20),
age TINYINT,
gender CHAR(1),
birth DATE,
score FLOAT(4,2)
);
数字类型:
int 整数
float(m,n) 小数,最多位数为m,精确到小数点后n位
double(m,n) 双精度小数,最多位数为m,精确到小数点后n位
n会占用m的位数,float(7,2)表示5位整数2位小数
字符类型:
char(n) 最大长度是n,固定长度的字符类型,n的最大值是255字节
varchar(n) 最大长度是n,可变长度的字符类型,n的最大值是65535字节
char(n) 如果存储的数据长度不到n个字节,会用空格补齐到n个字节
varchar(n) 按照数据的实际长度存储
char浪费存储空间,查询效率高
varchar节省存储空间,查询效率低
时间和日期类型
date 日期
time 时间
datetime 时间+日期
timestamp 时间戳
创建存储过程 create procedure
存储过程是MySQL编程的容器,mysql编程是将编程语言和sql语句结合,自动执行很多数据库操作,完成复杂的功能。所有的代码必须写在存储过程中进行保存,当需要执行这些代码时,调用存储过程的名字,实现相应的功能。
固定版式为:
delimiter //
create procedure 存储过程名称(参数1,参数2,……参数n)
begin
程序代码;
end;
//
delimiter ;
/delimiter 就是分隔符的意思,在存储过程中,每一行代码结束后都会有一个分号,如果系统仍旧使用分号作为分隔,会将每一行看作是一个语句,直接执行。
delimiter // 表示告诉系统不要用分号作为分隔符,而是使用//,其他符号也可以,如$$
delimiter ; 表示告诉系统重新将分号作为分隔符,delimiter后面必须有空格,不能换行/
1
2
3
4
5
6
7
8
9
10
存储过程可以有参数也可以没有,具体根据需要。即使没有参数括号必须有,存储过程具体要实现什么功能,相关的语句和代码写在begin和end之间。如打印helloworld:
DELIMITER //
CREATE PROCEDURE hello()
BEGIN
SELECT ‘hello world’;
END;
//
DELIMITER ;
/执行过后只是将存储过程创建并保存,并不会执行其中的语句,如果要调用存储过程,使用 call 存储过程名称/
CALL hello()
1
2
3
4
5
6
7
8
9
存储过程中根据需要可以定义参数,参数是临时存储和传递值的中间量,可以在存储过程外赋值,然后将值传递到存储过程内,参与运算,得到相应的结果;也可以在存储过程内获取运算的结果,传递到存储过程外。定义参数的方式:参数类型 参数名称 数据类型
in 类型表示将数据从外部传递到内部的参数
out 类型表示将结果从内部传递到外部的参数
in out 上述两个功能都具备的参数
#编写一个存储过程,要求输入一个testid,在测试表(test表)查询出对应的testname
DELIMITER //
CREATE PROCEDURE p_testid (IN a INT)
BEGIN
SELECT testname FROM test
WHERE testid = a;
END;
//
DELIMITER ;
#调用过程,有参数的过程必须给参数赋值
CALL p_testid(17968);
1
2
3
4
5
6
7
8
9
10
11
要给参数或者变量赋值,有2种方法
1.手动赋值
set 参数/变量=value;
2.将查询结果赋值给参数或变量
select … into 参数/变量 from ……;
/输入两个人name,计算他们的score之差,使用out类型的参数获取/
DROP PROCEDURE IF EXISTS pro_minus;
#如果有名称为pro_minus的储存过程(procedure),则删除该储存过程
DELIMITER //
CREATE PROCEDURE pro_minus(IN a VARCHAR(20),IN b VARCHAR(20),OUT c FLOAT(7,2))
BEGIN
DECLARE ascore FLOAT(7,2) DEFAULT 0;
DECLARE bscore FLOAT(7,2) DEFAULT 0;
SELECT score INTO ascore FROM test
WHERE testname = a;
SELECT score INTO bscore FROM test
WHERE testname = b;
SET c=ascore-bscore;
END;
//
DELIMITER ;
/存储过程中可以声明变量来临时存储和传递值,但是只能在内部使用
不像参数可以从内部或外部双向传递值
变量声明:declare 变量名称 数据类型 [default 默认值];
必须先声明变量才可以使用/
CALL pro_minus(‘KING’,‘JACK’,@score);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2.ALTER
表结构修改
在工作中,一般不推荐在表创建成功后再去改表结构,尤其是当表中已经有数据之后,如果确实因为特殊原因需要修改结构,使用alter语句。
1)添加列,在语句最后可以使用first表示在表的第一列添加,也可以用 after 列名 ,放到某列之后
alter table 表名 add 列名 数据类型;
1
2)删除列
alter table 表名 drop (column) 列名;
1
3)修改列名/数据类型
alter table 表名 change 原列名 新列名 数据类型;
1
4)添加默认值
alter table 表名 alter (column) 列名 set default 默认值;
1
5)删除默认值
alter table 表名 alter (column) 列名 drop default;
1
约束修改
约束就是数据应该满足的条件或者规则,不满足条件的数据不能被放入表中,约束以列为单位进行定义,规定某列的数据必须满足的条件
主键(primary key)约束:定义某一列为主键,该列数据不能重复也不能为空,每张表主键只能有一个。
外键(foreign key)约束:定义某一列为外键,参照其他表的主键,取值可以为空,如果不为空则必须与主键的值对应,外键只能定义成表级约束。
定义语法:
foreign key(列名) references 表名(列名)
1
非空(not null)约束:定义某一列的取值不能为空,非空只能定义成列级约束
唯一(unique)约束:定义某一列的值必须唯一
检查(check)约束:mysql不支持
约束可以在创建表的同时创建,也可以在创建表之后创建,约束分为列级约束和表级约束两种,两者效果一样,只是定义的方式不一样
create table 表名
(
列名1 数据类型 [default 默认值] [列级约束1 列级约束2 ……],
列名2 数据类型 [default 默认值] [列级约束1 列级约束2 ……],
……
列名n 数据类型 [default 默认值] [列级约束1 列级约束2 ……],
constraint 约束名称1 约束类型(列名),
constraint 约束名称2 约束类型(列名),
……
);
*/
CREATE TABLE test3
(
testid INT PRIMARY KEY,
testname VARCHAR(20) NOT NULL,
deptno INT,
FOREIGN KEY(deptno) REFERENCES dept(deptno),
phone BIGINT UNIQUE
);
DESC test3;
INSERT INTO test3
VALUES (1000,‘xiaoming’,10,13800138000);
SELECT * FROM test3;
INSERT INTO test3
VALUES (1005,‘xiaoqiang’,40,13800138005);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
创建表之后可以修改约束
添加主键约束
alter table 表名 add constraint 约束名称 primary key(列名);
1
删除主键约束
alter table 表名 drop constraint primary key;
1
添加唯一约束
alter table 表名 add unique 列名;
1
删除唯一约束
alter table 表名 drop index 列名;
1
添加非空约束
alter table 表名 change 原列名 新列名 数据类型 not null;
1
删除非空约束
alter table 表名 change 原列名 新列名 数据类型;
1
添加外键约束
alter table 表名 add foreign key(列名) references 表名(列名);
1
删除外键约束
alter table 表名 drop foreign key 外键名称;
1
SHOW CREATE TABLE test3;
/*
CREATE TABLE test3
(
testid
int(11) NOT NULL,
testname
varchar(20) NOT NULL,
deptno
int(11) DEFAULT NULL,
phone
bigint(20) DEFAULT NULL,
PRIMARY KEY (testid
),
UNIQUE KEY phone
(phone
),
KEY deptno
(deptno
),
CONSTRAINT test3_ibfk_1
FOREIGN KEY (deptno
) REFERENCES dept
(deptno
)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
test3_ibfk_1 就是系统自动分配给外键约束的名称
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
3.DROP
删除表DROP
drop table 表名;
1
4.TRUNCATE
截取表中的数据TRUNCATE
truncate table 表名;
1
drop,truncate,delecte三者之间的区别:
drop 属于DDL语句,删除整张表;直接生效不能回滚;
truncate 属于DDL语句,只能快速删除所有数据,不能指定范围;直接生效不能回滚;站在表的层面,快速清空数据;
delete 属于DML语句,可以删除全部也可以删除部分;需要提交才能生效,可以回滚;必须进入表,按照行来删除数据。
数据操作语句(DML)
1、INSERT
INSERT INTO 语句用于向表格中插入新的行和数据
insert into 表名 values (value1,value2,…valueN);
1
按照表的原有结构放入数据
INSERT INTO dept VALUES (60,‘Tech’,‘Mian Yang’);
1
执行的dml语句和ddl语句都是以事务的形式存在的,事务必须提交才能永久生效,可以回滚撤销操作,mysql默认自动提交是开启的,关闭自动提交:
SET autocommit=0;
COMMIT; #提交
ROLLBACK; #回滚
DDL语句都是自动提交的,并且不能关闭
insert into 表名(列名1,列名2,……列名n) values (value1,value2,…valueN);
1
按照自定义的列放入数据
INSERT INTO emp(empno,ename,job,sal) VALUES (8000,‘xiaoming’,‘HR’,2500);
1
未定义的列默认放入空值,也可以使用null放入空值
INSERT INTO dept VALUES (80,‘Training’,NULL);
1
使用函数放入数据
INSERT INTO emp(empno,ename,job,hiredate,sal,deptno)
VALUES (8001,‘xiaoqiang’,‘TESTER’,CURDATE(),3000,20);
1
2
insert into 表名 select …… ; 将查询结果直接放入另一张表,拷贝数据
INSERT INTO bonus
SELECT ename,job,sal,comm FROM emp
WHERE comm IS NOT NULL;
ROLLBACK;#回滚操作
1
2
3
4
5
mysql允许一个insert语句同时放入多行数据
insert into 表名 values (value1,value2,…valueN),(value1,value2,…valueN), (value1,value2,…valueN),…;
1
2、UPDATE
Update 语句用于修改表中的数据,格式为
UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值
1
如果不写where子句,会修改所有行的数据
UPDATE emp SET sal=3000;#更新所有的sal
UPDATE emp SET sal=1200 WHERE ename = ‘SMITH’;#只更新一条sql
SELECT * FROM emp;#查询emp表校验
ROLLBACK;#回滚操作
1
2
3
4
可以在已有数据的基础上进行修改,30号部门表现不错,每人涨薪300
UPDATE emp SET sal=sal+300 WHERE deptno=30;
ROLLBACK;#回滚操作
1
2
注意,在set和where后面,都可以使用子查询,但不能使用本表数据的子查询
3、DELETE
DELETE 语句用于删除表中的行,如果不写where子句,会删除所有数据
DELETE FROM 表名称 WHERE 列名称 = 值
1
数据查询语句(DQL)
1、select基础
1)代表所有列
SELECT * FROM 表名称;
#SQL 语句对大小写不敏感。SELECT 等效于 select。
1
2
2)查询指定的列
SELECT 列名称 FROM 表名称;
1
3)对查询结果进行运算
#+ - * /
#查询每个员工的年薪
SELECT ename,12sal FROM emp;
#员工的年终奖定为年薪的10%再加上500
SELECT ename,(12*sal)0.1+500 FROM emp;
1
2
3
4
5
4)空值参与运算得到结果也是空值
#计算员工的年收入,emp表不存在comm列
SELECT ename,sal,comm,12(sal+comm) FROM emp;
1
2
5)别名
通过使用 SQL,可以为列名称和表名称指定别名(Alias)
#查询结果中可以给列起别名加以说明
/*
列名 别名
列名 AS 别名
别名中如果包含特殊字符(空格),需要加双引号
双引号只会在起别名的时候出现,其他的所有地方都只能用单引号而不能用双引号
*/
SELECT ename xingming,job zhiwei FROM emp;
SELECT ename AS xingming,job AS zhiwei FROM emp;
SELECT ename 姓名,job 职位 FROM emp;
SELECT ename “xing ming”,job “zhi wei” FROM emp;
#别名主要用来标识运算结果
SELECT ename,(12sal)0.1+500 AS nianzhongjiang FROM emp;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
6)表达式
#表达式根据数据类型的不同分为数字表达式、字符表达式和日期表达式
#手动输入的表达式可以写在select后面,表中有多少行,表达式就显示多少次
#手动输入数字表达式可以直接写,日期和字符表达式必须加上单引号
SELECT 123.456,126048,‘I am the king’ FROM emp;
#mysql允许只写select,不写from;oracle必须要写select和from,不能缺少
#如果要查询的数据都是手动输入,与表中数据无关,可以不写from
SELECT 123.456,126048,‘I am the king’;
SELECT ‘who are you’,ename FROM emp;
SELECT job,‘JOB’ FROM emp;
#手动字符串必须加单引号,mysql在windows平台字符串不区分大小写,但是在linux区分大小写
#其他的数据库包括编程语言,字符串都要区分大小写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
7)distinct去重
SELECT job FROM emp;
SELECT DISTINCT job FROM emp;
SELECT DISTINCT deptno FROM emp;
#多列去重
SELECT DISTINCT job,deptno FROM emp;
#普通列不能和去重的列同时查询,因为行数不匹配,不能组成一张表
#select ename,distinct job from emp;
1
2
3
4
5
6
7
8
9
10
8)limit分页查询
SELECT * FROM emp;
#如果在查询结果中,想要得到固定某几行的结果,使用limit
#limit 写在查询语句最后
#limit m,n 表示从第m行开始显示n行数据,第一行的行号是0
SELECT * FROM emp
LIMIT 2,5;
#limit n 表示显示前n行数据
SELECT * FROM emp
LIMIT 3;
1
2
3
4
5
6
7
8
9
10
2、限定和排序
1)where子句限定范围
#where子句后面必须是一个完整的逻辑表达式,结果只有两种true或者false
#在where子句中,逻辑表达式通常是比较运算,比较条件是否满足
= > < >= <= != <>
1
where子句限定条件通常是用表中的某一列数据作为条件,返回满足条件的数据
查询20号部门的员工信息
SELECT * FROM emp WHERE deptno = 20;
1
查询工资高于2000的员工信息
SELECT * FROM emp WHERE sal > 2000;
1
查询职位不是manager的员工信息
SELECT * FROM emp WHERE job != ‘MANAGER’;
1
手动输入字符串要加单引号,最好在匹配的时候大小写一致
手动输入字符串要加单引号,最好在匹配的时候大小写一致
查询年薪小于20000的员工信息 列的别名不能出现在where子句中
SELECT ename,job,sal,12sal nianxin,deptno FROM emp WHERE 12sal < 20000;
1
其他的数据库不支持*加上其他列一起查询,mysql允许
SELECT ,12sal nianxin FROM emp;
1
where子句中的条件也可以是两列数据相互比较
SELECT * FROM emp WHERE sal < comm;
1
where子句中作为条件的列可以不出现在select后面,但是这样的语句结果不够直观
SELECT ename,job,deptno FROM emp WHERE sal <= 1500;
1
where子句中比较运算符的两端数据类型必须一致,如果是其他数据库,数据类型不一致时会直接报错,mysql由于是弱数据类型的语言,所以不会报错,只是这样的语句没有意义
SELECT * FROM emp WHERE ename > 2;
1
如果没有数据满足条件,则一行数据都没有
SELECT * FROM emp WHERE deptno > 200;
1
#如果有满足条件的数据,至少会返回一行,只是可能数据的值是空值
SELECT comm FROM emp WHERE ename = ‘SMITH’;
1
2)常用的特殊比较运算
in(value1,value,2…valueN), 列表匹配
SELECT * FROM emp WHERE job IN (‘MANAGER’,‘CLERK’,‘PRESIDENT’);
between操作符:
最小值 and 最大值,范围匹配,最大值和最小值的位置不能变
SELECT * FROM emp WHERE sal BETWEEN 1500 AND 3000;
like操作符
LIKE 操作符用于在 WHERE 子句中搜索列中的指定模式,模糊匹配(对字符)
通配符,可以匹配或者代表其他字符的特殊符号,SQL 通配符必须与 LIKE 运算符一起使用。
1
2
SELECT * FROM emp
WHERE ename LIKE ‘S%’;
SELECT * FROM emp
WHERE ename LIKE ‘%S’;
SELECT * FROM emp
WHERE ename LIKE ‘%A%’;
SELECT * FROM emp
WHERE ename LIKE ‘_A%’;
SELECT * FROM emp
WHERE ename LIKE ‘_____’;
#is null, 匹配空值(不能写成 =null)
SELECT * FROM emp
WHERE comm IS NULL;
3)逻辑运算
and 与运算,所有的条件都要满足才能返回结果
SELECT * FROM emp WHERE deptno = 20 AND sal > 2000;
or 或运算,多个条件满足任意一个就能返回结果
SELECT * FROM emp WHERE deptno = 20 OR sal > 2000;
not 非运算,返回不满足条件的结果
SELECT * FROM emp WHERE NOT sal > 2000;
如果是数学符号的比较运算,not必须写在最前面
如果是英文的比较运算,not可以写在最前也可以写在运算符中间
SELECT * FROM emp
WHERE deptno NOT IN (10,20);
4)运算优先级
数学运算>比较运算>NOT>AND>OR
可以使用括号改变运算优先级
SELECT * FROM emp
WHERE deptno = 20
OR sal > 2000
AND job IN (‘MANAGER’,‘CLERK’);
SELECT * FROM emp
WHERE (deptno = 20
OR sal > 2000)
AND job IN (‘MANAGER’,‘CLERK’);
5)排序ORDER BY子句
order by也在查询语句的后面,但是在limit之前
asc 表示升序排列,默认可以不写
desc 表示降序排列
SELECT * FROM emp ORDER BY sal ASC;
所有的数据类型都可以排序
SELECT * FROM emp WHERE deptno = 20 ORDER BY hiredate DESC;
SELECT * FROM emp ORDER BY ename;
可以使用别名排序
SELECT ,12sal nianxin FROM emp ORDER BY nianxin DESC;
多列排序
SELECT * FROM emp ORDER BY deptno,sal DESC;
多列排序时,有重复数据的列写在前面
#查询工资排名前三的员工信息
SELECT * FROM emp
ORDER BY sal DESC
LIMIT 3;
3、单行函数
#函数可以实现特定的功能或者运算,给函数输入数据,函数经过处理,得到相应的结果
f1(X)=3x+2
f1(4)=14
f2(X,Y)=5x+4y
f2(3,2)=23
#mysql中系统自带的单行函数,提供了数据特殊处理的方式
#可以协助我们快速对特定数据进行处理
#系统中的函数数量非常多,这里介绍一些常用函数
#单行数据针对表中的每一行数据分别进行处理或运算,得到相应的结果
#单行函数按照处理的数据类型分为:数值函数,字符函数,日期函数,逻辑函数
1)数值函数
#round(m,n) 将数字m四舍五入到小数点后n位
SELECT ROUND(123.456,1),ROUND(123.456,2),ROUND(123.456,0);
#n可以不写,默认精确到整数
SELECT ROUND(123.456);
#n可以为负数,精确到小数点前n位
SELECT ROUND(126.456,-1),ROUND(173.456,-2),ROUND(823.456,-3);
#truncate(m,n) 将数字m截取到小数点后n位
SELECT TRUNCATE(123.456,1),TRUNCATE(123.456,2),TRUNCATE(123.456,0);
#truncate必须两个参数都有,不能省略n
#n可以为负数,截取到小数点前n位
SELECT TRUNCATE(126.456,-1),TRUNCATE(173.456,-2),TRUNCATE(823.456,-3);
#floor(m) 向下取整,返回小于等于m的最大整数
#ceil(m) 向上取整,返回大于等于m的最小整数
SELECT FLOOR(23),FLOOR(23.45),FLOOR(-23.45);
SELECT CEIL(23),CEIL(23.45),CEIL(-23.45);
#mod(m,n) 计算m除以n的余数
SELECT MOD(12,5),MOD(123.45,5.7),MOD(12,0);
#rand() 生成一个0到1之间的随机数
SELECT RAND();
#要得到一个1到10之间的随机整数
SELECT ROUND(1+RAND()*9);
2)字符函数
#concat(str1,str2,…,strN) 将多个字符串连接在一起
SELECT CONCAT(‘abcdefg’,‘xyz’);
SELECT CONCAT(ename,job) FROM emp;
SELECT CONCAT(ename,’ is a ',job) FROM emp;
#length(str) 计算字符串的长度
SELECT LENGTH(‘abcdefg’);
SELECT ename,LENGTH(ename) FROM emp;
#函数处理过后的数据也可以写在where子句中作为条件
SELECT * FROM emp
WHERE LENGTH(ename)=4;
#left(str,n) 截取字符串最左边n个字符
#right(str,n) 截取字符串最右边n个字符
SELECT ename,LEFT(ename,2),RIGHT(ename,2) FROM emp;
#mid(str,m,n) 从字符串的第m个字符开始截取长度为n的字符串
SELECT ename,MID(ename,2,3) FROM emp;
#n可以不写,默认截取后面所有的字符
SELECT ename,MID(ename,3) FROM emp;
#m可以为负数,从右向左数第m个字符开始截取
SELECT ename,MID(ename,-2) FROM emp;
#replace(str1,str2,str3) 在str1中找到str2替换为str3
SELECT REPLACE(‘He love you’,‘He’,‘I’);
SELECT ename,REPLACE(ename,‘A’,‘XXXXX’) FROM emp;
3)日期函数
#日期的格式是’YYYY-MM-DD’
#时间的格式是’HH:MM:SS’
#查询1981年6月之前入职的员工信息
SELECT * FROM emp
WHERE hiredate < ‘1981-06-01’;
#curdate() 返回当前系统日期,curtime 返回当前系统时间
SELECT CURDATE(),CURTIME();
#now() 返回当前系统日期+时间
SELECT NOW();
#year(date) 返回日期所在的年份,month(date) 返回日期所在的月份,day(date)返回日期的天数
SELECT *,YEAR(hiredate),MONTH(hiredate),DAY(hiredate) FROM emp;
#查看冬天入职的员工
SELECT * FROM emp
WHERE MONTH(hiredate) IN (10,11,12);
#DATE_ADD(date,interval n 单位) 给日期加上n个单位时间,单位可以是year,month,day
SELECT DATE_ADD(CURDATE(),INTERVAL -5 MONTH);
4)逻辑函数
#if(条件判断,value1,value2) 如果条件成立则返回value1,如果条件不成立则返回value2
#对员工的工资进行判断,员工工资大于等于3000的显示高富帅,其他显示矮矬穷
SELECT *,IF(sal>=3000,‘高富帅’,‘矮矬穷’) FROM emp;
#对员工的工资进行判断,员工工资大于等于3000的显示高富帅,
#2000到3000之间的显示中产
#1000到2000之间显示小资
#1000以下矮矬穷
SELECT *,IF(sal>=3000,‘高富帅’,IF(sal>=2000,‘中产’,IF(sal>=1000,‘小资’,‘矮矬穷’))) FROM emp;
#ifnull(x,y) 如果x的值为空,则返回y,如果x不为空则返回x
SELECT ,12(sal+IFNULL(comm,0)) nianshouru FROM emp;
/*
case x
when value1 then result1
when value2 then result2
…
when valueN then resultN
else resultN+1
end
判断x的值,如果x=value1则返回result1
如果x=value2则返回result2
……
如果x=valueN则返回resultN
如果以上值都不满足返回resultN+1
/
#根据员工不同的职位涨不同幅度的工资
#clerk涨10%,salesman涨15%
#manager涨20%,其他人不变
SELECT ,
CASE job
WHEN ‘CLERK’ THEN sal1.1
WHEN ‘SALESMAN’ THEN sal1.15
WHEN ‘MANAGER’ THEN sal*1.2
ELSE sal
END addsal
FROM emp;
4、多表查询
1)笛卡尔积
#查询员工的信息和其所在部门的信息
SELECT * FROM emp;
SELECT * FROM dept;
SELECT ename,job,sal,dname,loc FROM emp,dept;
#集合A中的所有元素和集合B中的所有元素,组成的有序对成为笛卡尔积,记作A×B
#在关系型数据库中,多表查询时如果没有连接条件,会产生笛卡尔积
#连接条件就是两张表之间数据的关系,是A表中的某几列和B表中的某几列数据的联系
#连接条件写在where子句中,通常为:表1.列1=表2.列2
#多表查询本质是先生成笛卡尔积,再在笛卡尔积中筛选满足条件的数据
#查询n张表,至少要有n-1个连接条件
2)多表查询的语法规范
#多表查询时,必须使用表名来限定所有列名,表名.列名
#1是为了避免重名的列报错
#2是为了提高查询效率
SELECT emp.ename,emp.job,emp.sal,emp.deptno,dept.dname,dept.loc FROM emp,dept;
#多表查询时,给表起别名,再使用表的别名来限定列名
#表的别名尽量简单,用一个字母能够区分多个表就可以
#多表查询时,先写from,from单独占一行
SELECT e.ename,e.job,e.sal,e.deptno,d.dname,d.loc
FROM emp e,dept d;
#多表查询时,如果查询结果中有同名的列,起不同的别名加以区分
SELECT e.ename,e.job,e.sal,e.deptno eno,d.deptno,d.dname,d.loc
FROM emp e,dept d;
3)等值连接
#两张表之间数据的关系是相等关系
#通常是指主键和外键的对应
#查询员工的信息和其所在部门的信息
SELECT e.ename,e.job,e.sal,e.deptno eno,d.deptno,d.dname,d.loc
FROM emp e,dept d
WHERE e.deptno = d.deptno;
#如果多表查询时还有其他的普通限定条件,也写在where子句中,用and和连接条件连接
#查询工资高于2000的员工信息以及其所在的部门信息
SELECT e.*,d.deptno dno,d.dname,d.loc
FROM emp e,dept d
WHERE e.deptno = d.deptno
AND e.sal > 2000;
4)不等值连接
SELECT * FROM salgrade;
#查询员工的信息和其所在的工资等级
SELECT e.,s.
FROM emp e,salgrade s
WHERE e.sal BETWEEN s.losal AND s.hisal;
5)自连接
#如果一张表的数据内部有联系,主键和外键在同一张表
#要将这样的关系体现出来使用自连接
#首先将一张表看作是两张表,再将两张表的主键和外键进行对应
#给同一张表起不同的别名,用不同的别名代表不同的表
#查询emp表中员工的姓名和其上级的姓名
SELECT w.ename,m.ename manager
FROM emp w,emp m
WHERE w.mgr = m.empno;
6)外连接
#在多表查询中,有的数据不满足连接条件,在内连接中是无法显示
#如果要显示这样的数据,使用外连接
#如果要显示左边表中不满足连接条件的数据,使用左外连接:left outer join
#如果要显示右边表中不满足连接条件的数据,使用右外连接:right outer join
#查询emp表中员工的姓名和其上级的姓名,没有上级的员工也显示
SELECT w.ename,m.ename manager
FROM emp w LEFT OUTER JOIN emp m
ON w.mgr = m.empno;
#查询员工信息和部门信息,没有员工的部门也显示
SELECT e.*,d.deptno dno,d.dname,d.loc
FROM emp e RIGHT OUTER JOIN dept d
ON e.deptno = d.deptno;
#全外连接full outer join,mysql暂时不支持
【练习】
1.查询EMP、DEPT表,输出的列包含员工姓名、工资、部门编号、部门名称、部门地址.
SELECT e.ename,e.sal,d.deptno,d.dname,d.loc
FROM emp e,dept d
WHERE e.deptno = d.deptno;
2.查询工资等级为3/4/5级的员工姓名,工资,工资等级
SELECT e.ename,e.sal,s.grade
FROM emp e,salgrade s
WHERE e.sal BETWEEN s.losal AND s.hisal
AND s.grade > 2;
3.显示职位是CLERK的员工姓名,工资,工资等级,部门名称
SELECT e.ename,e.job,e.sal,s.grade,d.dname
FROM emp e,dept d,salgrade s
WHERE e.deptno = d.deptno
AND e.sal BETWEEN s.losal AND s.hisal
AND e.job = ‘CLERK’;
4.查询emp表,显示员工姓名及其经理的姓名,没有经理的员工也需要显示
SELECT w.ename,m.ename manager
FROM emp w LEFT OUTER JOIN emp m
ON w.mgr = m.empno;
5.列出EMP表中部门名称和这些部门的员工信息,同时列出那些没有员工的部门
SELECT d.dname,e.*
FROM emp e RIGHT OUTER JOIN dept d
ON e.deptno = d.deptno;
5、多行函数
1)多行函数
#针对多行数据进行运算,只得到一个结果,就是多行函数
#又称为分组函数,或聚合函数
#sum() 求和
SELECT SUM(sal) FROM emp;
#avg() 求平均值
SELECT AVG(sal) FROM emp;
#sum和avg都只能对数字进行运算
#count() 计数(行数)
SELECT COUNT(ename) FROM emp;
SELECT COUNT(*) FROM emp;
#max() 最大值,min() 最小值
SELECT MAX(sal),MIN(sal) FROM emp;
SELECT MAX(hiredate),MIN(hiredate) FROM emp;
SELECT MAX(ename),MIN(ename) FROM emp;
#分组函数在计算时会忽略空值
SELECT AVG(comm),COUNT(comm) FROM emp;
SELECT SUM(comm)/14,SUM(comm)/4 FROM emp;
#如果要考虑空值,使用ifnull转换
SELECT AVG(IFNULL(comm,0)) FROM emp;
#可以使用where子句去限定分组函数计算的范围
#找出职位是salesman的员工的最高工资
SELECT MAX(sal) FROM emp
WHERE job = ‘SALESMAN’;
#找出10号部门的平均工资
SELECT AVG(sal) FROM emp
WHERE deptno = 10;
#oracle中普通列和分组函数是不能直接一起查询的
#mysql虽然允许这样的语句执行,但是结果没有意义
#select ename,count(sal) from emp;
2)group BY子句
#查询每个部门的平均工资
SELECT deptno,AVG(sal) FROM emp
GROUP BY deptno;
#select后面既有普通列又有分组函数时,必须写group by子句
#并且出现在select后面的普通列必须也在group by后面
#查询每个职位的人数
SELECT job,COUNT(*) FROM emp
GROUP BY job;
#可以多列分组
#查询每个部门各个职位的最低工资
SELECT deptno,job,MIN(sal) FROM emp
GROUP BY deptno,job;
3)having子句
#查询部门人数多于5人的部门编号
/*
select deptno,count() from emp
where count() > 5
group by deptno;
where子句中不能出现分组函数
/
#要对分组函数的结果进行限定,使用having子句
#having必须在group by后面
#使用group by可以不用having,但是使用having必须使用group by
SELECT deptno,COUNT() FROM emp
GROUP BY deptno
HAVING COUNT(*) > 5;
6、子查询
#查询工资高于allen的员工信息
SELECT sal FROM emp
WHERE ename = ‘ALLEN’;
SELECT * FROM emp
WHERE sal > 1600;
#当查询语句的条件不是客观数据,而是表中的数据时,使用子查询
#子查询又叫做嵌套查询,将一个查询的结果作为另一个查询的条件
#子查询写在主查询中,必须使用括号表示运算顺序
SELECT * FROM emp
WHERE sal >
(SELECT sal FROM emp WHERE ename = ‘ALLEN’) ;
#习惯上,将子查询写在比较运算的右边,而且子查询单独占一行
#主查询中作为条件的列,必须和子查询的结果数据类型一致
1)单行子查询
#子查询的结果如果是一行一列数据,就是单行子查询
#查询跟allen的部门和职位都一样的员工信息
SELECT * FROM emp
WHERE deptno =
(SELECT deptno FROM emp WHERE ename = ‘ALLEN’)
AND job =
(SELECT job FROM emp WHERE ename = ‘ALLEN’);
#主查询和子查询的数据可以不在同一张表
#查询allen所在的部门名称
1.多表查询
SELECT d.dname
FROM emp e,dept d
WHERE e.deptno = d.deptno
AND e.ename = ‘ALLEN’;
#多表查询先生成笛卡尔积,再在笛卡尔积中找满足条件的数据
#一共找了14*4=56次
2.子查询
SELECT dname FROM dept
WHERE deptno =
(SELECT deptno FROM emp WHERE ename = ‘ALLEN’);
#先执行子查询,找了14次,再在主查询中查询,找了4次
#一共找了14+4=18次
#子查询的效率高于多表查询
#如果查询结果来自多张表,只能使用多表查询
#如果查询结果来自一张表,只是用到另一张表的数据作为条件
#可以用子查询也可以用多表查询,推荐使用子查询
#子查询中可以使用分组函数
#查询emp表中工资最高的员工姓名
SELECT ename FROM emp
WHERE sal =
(SELECT MAX(sal) FROM emp);
#having子句中可以使用子查询
#查询部门的平均工资高于所有员工平均工资的部门
SELECT deptno,AVG(sal) FROM emp
GROUP BY deptno
HAVING AVG(sal) >
(SELECT AVG(sal) FROM emp);
2)多行子查询
#子查询的结果如果是多行一列数据,就是多行子查询
#多行子查询必须使用多行比较运算符
#in 匹配多个值
#查询工资大于等于3000的员工所在的部门名称
SELECT dname FROM dept
WHERE deptno IN
(SELECT DISTINCT deptno FROM emp WHERE sal >= 3000);
#any,多个条件满足其中任意一个就可以返回结果
#查询工资高于任意一个部门的平均工资的员工信息
SELECT * FROM emp
WHERE sal > ANY
(SELECT AVG(sal) FROM emp GROUP BY deptno);
#大于any表示大于最小值,小于any表示小于最大值
#all,多个条件必须全部满足才能返回结果
SELECT * FROM emp
WHERE sal > ALL
(SELECT AVG(sal) FROM emp GROUP BY deptno);
#大于all表示大于最大值,小于all表示小于最小值
3)多列子查询
#子查询的结果如果是多行多列数据,就是多列子查询
#in 匹配多列的值
#查询跟allen的部门和职位都一样的员工信息
SELECT * FROM emp
WHERE (deptno,job) IN
(SELECT deptno,job FROM emp WHERE ename = ‘ALLEN’);
#主查询中列的数量、顺序以及数据类型必须和子查询中的列一致
#子查询的结果可以看作是一张表,再进行查询
#此时子查询写在from后面,必须起别名
SELECT * FROM
(SELECT ename,job,sal,comm,12*sal nianxin,sal+IFNULL(comm,0) yongjin FROM emp) e
WHERE yongjin > 2000;
#先用一个查询语句构造出一张表,再和其他表做多表查询
7、集合操作
#集合操作是指,将查询结果看作是一个集合,集合与集合之间可以做集合操作
#集合操作:合集、交集、差集、补集
#mysql中只支持合集操作,union,union all
#集合操作的效率高于条件组合的查询效率
#进行集合操作的查询语句,查询的列必须一致
SELECT ename,job,sal,deptno FROM emp
WHERE deptno = 20
UNION
SELECT ename,job,sal,deptno FROM emp
WHERE sal < 2000;
#union all会显示重复数据
SELECT ename,job,sal,deptno FROM emp
WHERE deptno = 20
UNION ALL
SELECT ename,job,sal,deptno FROM emp
WHERE sal < 2000;
数据控制语句(DCL)
DCL(Data Control Language)是数据库控制语言。是用来设置或更改数据库用户或角色权限的语句,包括(grant,deny,revoke等)语句。在默认状态下,只有sysadmin,dbcreator,db_owner或db_securityadmin等人员才有权力执行DCL
事物控制语句(TCL)
执行的dml语句和ddl语句都是以事务的形式存在的,事务必须提交才能永久生效,可以回滚撤销操作,mysql默认自动提交是开启的,关闭自动提交:
SET autocommit=0;
COMMIT; #提交
ROLLBACK; #回滚
DDL语句都是自动提交的,并且不能关闭
————————————————
版权声明:本文为CSDN博主「测试熊」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_43400993/article/details/107081829