MySQL基础命令与案列解析

    技术2022-07-13  78

    SQL的基本语法规范

    1、sql不区分大小写,但是习惯上关键字、系统保留字、函数名称大写,表名和列名小写; 2、sql使用空格或者回车来分隔每个单词都一样,习惯上每个子句换行,WHERE子句中的每个条件占一行,子查询单独占一行; 3、复杂的语句最好加上注释进行说明; 4、sql语句中使用分号作为分隔符,系统读取到分号才会执行语句。

    数据定义语言(DDL)

    ​ 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后面必须有空格,不能换行*/

    存储过程可以有参数也可以没有,具体根据需要。即使没有参数括号必须有,存储过程具体要实现什么功能,相关的语句和代码写在begin和end之间。如打印helloworld:

    DELIMITER // CREATE PROCEDURE hello() BEGIN SELECT 'hello world'; END; // DELIMITER ; /*执行过后只是将存储过程创建并保存,并不会执行其中的语句,如果要调用存储过程,使用 call 存储过程名称*/ CALL hello()

    存储过程中根据需要可以定义参数,参数是临时存储和传递值的中间量,可以在存储过程外赋值,然后将值传递到存储过程内,参与运算,得到相应的结果;也可以在存储过程内获取运算的结果,传递到存储过程外。定义参数的方式:参数类型 参数名称 数据类型 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);

    要给参数或者变量赋值,有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);

    2.ALTER

    表结构修改

    在工作中,一般不推荐在表创建成功后再去改表结构,尤其是当表中已经有数据之后,如果确实因为特殊原因需要修改结构,使用alter语句。

    1)添加列,在语句最后可以使用first表示在表的第一列添加,也可以用 after 列名 ,放到某列之后

    alter table 表名 add 列名 数据类型;

    2)删除列

    alter table 表名 drop (column) 列名;

    3)修改列名/数据类型

    alter table 表名 change 原列名 新列名 数据类型;

    4)添加默认值

    alter table 表名 alter (column) 列名 set default 默认值;

    5)删除默认值

    alter table 表名 alter (column) 列名 drop default;

    约束修改

    约束就是数据应该满足的条件或者规则,不满足条件的数据不能被放入表中,约束以列为单位进行定义,规定某列的数据必须满足的条件

    主键(primary key)约束:定义某一列为主键,该列数据不能重复也不能为空,每张表主键只能有一个。

    外键(foreign key)约束:定义某一列为外键,参照其他表的主键,取值可以为空,如果不为空则必须与主键的值对应,外键只能定义成表级约束。

    定义语法:

    foreign key(列名) references 表名(列名)

    非空(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);

    创建表之后可以修改约束

    添加主键约束

    alter table 表名 add constraint 约束名称 primary key(列名);

    删除主键约束

    alter table 表名 drop constraint primary key;

    添加唯一约束

    alter table 表名 add unique 列名;

    删除唯一约束

    alter table 表名 drop index 列名;

    添加非空约束

    alter table 表名 change 原列名 新列名 数据类型 not null;

    删除非空约束

    alter table 表名 change 原列名 新列名 数据类型;

    添加外键约束

    alter table 表名 add foreign key(列名) references 表名(列名);

    删除外键约束

    alter table 表名 drop foreign key 外键名称; 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 就是系统自动分配给外键约束的名称 */

    3.DROP

    删除表DROP

    drop table 表名;

    4.TRUNCATE

    截取表中的数据TRUNCATE

    truncate table 表名;

    drop,truncate,delecte三者之间的区别:

    drop 属于DDL语句,删除整张表;直接生效不能回滚; truncate 属于DDL语句,只能快速删除所有数据,不能指定范围;直接生效不能回滚;站在表的层面,快速清空数据; delete 属于DML语句,可以删除全部也可以删除部分;需要提交才能生效,可以回滚;必须进入表,按照行来删除数据。

    数据操作语句(DML)

    1、INSERT

    INSERT INTO 语句用于向表格中插入新的行和数据

    insert into 表名 values (value1,value2,...valueN);

    按照表的原有结构放入数据

    INSERT INTO dept VALUES (60,'Tech','Mian Yang');

    执行的dml语句和ddl语句都是以事务的形式存在的,事务必须提交才能永久生效,可以回滚撤销操作,mysql默认自动提交是开启的,关闭自动提交: SET autocommit=0;

    COMMIT; #提交 ROLLBACK; #回滚

    DDL语句都是自动提交的,并且不能关闭

    insert into 表名(列名1,列名2,……列名n) values (value1,value2,...valueN);

    按照自定义的列放入数据

    INSERT INTO emp(empno,ename,job,sal) VALUES (8000,'xiaoming','HR',2500);

    未定义的列默认放入空值,也可以使用null放入空值

    INSERT INTO dept VALUES (80,'Training',NULL);

    使用函数放入数据

    INSERT INTO emp(empno,ename,job,hiredate,sal,deptno) VALUES (8001,'xiaoqiang','TESTER',CURDATE(),3000,20);

    insert into 表名 select …… ; 将查询结果直接放入另一张表,拷贝数据

    INSERT INTO bonus SELECT ename,job,sal,comm FROM emp WHERE comm IS NOT NULL; ROLLBACK;#回滚操作

    mysql允许一个insert语句同时放入多行数据

    insert into 表名 values (value1,value2,...valueN),(value1,value2,...valueN), (value1,value2,...valueN),...;

    2、UPDATE

    Update 语句用于修改表中的数据,格式为

    UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值

    如果不写where子句,会修改所有行的数据

    UPDATE emp SET sal=3000;#更新所有的sal UPDATE emp SET sal=1200 WHERE ename = 'SMITH';#只更新一条sql SELECT * FROM emp;#查询emp表校验 ROLLBACK;#回滚操作

    可以在已有数据的基础上进行修改,30号部门表现不错,每人涨薪300

    UPDATE emp SET sal=sal+300 WHERE deptno=30; ROLLBACK;#回滚操作

    注意,在set和where后面,都可以使用子查询,但不能使用本表数据的子查询

    3、DELETE

    DELETE 语句用于删除表中的行,如果不写where子句,会删除所有数据

    DELETE FROM 表名称 WHERE 列名称 = 值

    数据查询语句(DQL)

    1、select基础

    1)*代表所有列

    SELECT * FROM 表名称; #SQL 语句对大小写不敏感。SELECT 等效于 select。

    2)查询指定的列

    SELECT 列名称 FROM 表名称;

    3)对查询结果进行运算

    #+ - * / #查询每个员工的年薪 SELECT ename,12*sal FROM emp; #员工的年终奖定为年薪的10%再加上500 SELECT ename,(12*sal)*0.1+500 FROM emp;

    4)空值参与运算得到结果也是空值

    #计算员工的年收入,emp表不存在comm列 SELECT ename,sal,comm,12*(sal+comm) FROM emp;

    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,(12*sal)*0.1+500 AS nianzhongjiang FROM emp;

    6)表达式

    #表达式根据数据类型的不同分为数字表达式、字符表达式和日期表达式 #手动输入的表达式可以写在select后面,表中有多少行,表达式就显示多少次 #手动输入数字表达式可以直接写,日期和字符表达式必须加上单引号 SELECT 123.456,12*60*48,'I am the king' FROM emp; #mysql允许只写select,不写from;oracle必须要写select和from,不能缺少 #如果要查询的数据都是手动输入,与表中数据无关,可以不写from SELECT 123.456,12*60*48,'I am the king'; SELECT 'who are you',ename FROM emp; SELECT job,'JOB' FROM emp; #手动字符串必须加单引号,mysql在windows平台字符串不区分大小写,但是在linux区分大小写 #其他的数据库包括编程语言,字符串都要区分大小写

    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;

    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;

    2、限定和排序

    1)where子句限定范围

    #where子句后面必须是一个完整的逻辑表达式,结果只有两种true或者false #在where子句中,逻辑表达式通常是比较运算,比较条件是否满足

    = > < >= <= != <>

    where子句限定条件通常是用表中的某一列数据作为条件,返回满足条件的数据

    查询20号部门的员工信息

    SELECT * FROM emp WHERE deptno = 20;

    查询工资高于2000的员工信息

    SELECT * FROM emp WHERE sal > 2000;

    查询职位不是manager的员工信息

    SELECT * FROM emp WHERE job != 'MANAGER';

    手动输入字符串要加单引号,最好在匹配的时候大小写一致

    手动输入字符串要加单引号,最好在匹配的时候大小写一致

    查询年薪小于20000的员工信息 列的别名不能出现在where子句中

    SELECT ename,job,sal,12*sal nianxin,deptno FROM emp WHERE 12*sal < 20000;

    其他的数据库不支持*加上其他列一起查询,mysql允许

    SELECT *,12*sal nianxin FROM emp;

    where子句中的条件也可以是两列数据相互比较

    SELECT * FROM emp WHERE sal < comm;

    where子句中作为条件的列可以不出现在select后面,但是这样的语句结果不够直观

    SELECT ename,job,deptno FROM emp WHERE sal <= 1500;

    where子句中比较运算符的两端数据类型必须一致,如果是其他数据库,数据类型不一致时会直接报错,mysql由于是弱数据类型的语言,所以不会报错,只是这样的语句没有意义

    SELECT * FROM emp WHERE ename > 2;

    如果没有数据满足条件,则一行数据都没有

    SELECT * FROM emp WHERE deptno > 200;

    #如果有满足条件的数据,至少会返回一行,只是可能数据的值是空值

    SELECT comm FROM emp WHERE ename = 'SMITH';

    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个任意字符 # % 表示任意个任意字符,包括0个1个和多个

    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语句都是自动提交的,并且不能关闭

    Processed: 0.016, SQL: 9