MySQL基础语法

一、SQL语句分类

  1. DDL(Data Definition Language):数据定义语言,用来定义数据库对象:库、表、列等
    –>创建、修改、删除:库、表结构
  2. DML(Data Manipulation Language):数据操作语言,用来定义数据库记录
    –>增删改查:表记录的更新
  3. DCL(Data Control Language):数据控制语言,定义访问权限和安全级别
    –>对于用户的创建,以及授权,一般不会有root权限
  4. DQL(Data Query Language):数据查询语言,用来查询记录

SQL不区分大小写,但建议关键字大写

二、DDL

  1. 数据库:

**show databases; //查看当前用户下所有的数据库
** use 数据库名 //切换数据库
** show tables; //查看当前数据库名下所有的表
** 创建数据库:CREATE DATABASE [IF NOT EXISTS] 数据库 [CHARSET=utf8]
** 删除数据库:DROP DATABASE [IF EXISTS] 数据库名
** 修改数据库编码类型:ALTER DATABASE mysb1 CHARACTER SET UTF8

  1. 数据类型(列类型)
    浮点型:double(5,2),表示最多5位,其中必须有2位小数,最大为999.99
    浮点型:decimal,和钱相关比较好用
    固定长度字符串:char(255)
    可变长度字符串:varchar(65535)
    字符串类型:text(clob) 超大字符串,可以存超长文本
    tinytext 252b
    text 64kb
    mediumtext 16Mb
    longtext 4Gb

blob(二进制) 可以存放音频视频等
tinyblob 256B
blob 64 KB
mediumblob 16mb
longblob 4Gb

date: 日期类型,格式为yyyy-MM-dd
time : 时间类型 hh:mm:ss
timestamp: 时间戳类型 yyyy-MM-dd hh:mm:ss


  1. 创建表:
    CREATE TABLE 表名(
    列名 列类型,
    列名 列类型,

    列名 列类型
    );
    ** 查看当前数据库中的所有表:SHOW TABLES;
    ** 查看指定表的结构:DESC 表名;
    ** 查看指定表的创建语句:SHOW CREATE TABLE 表名;
    ** 删除表: DROP TABLE 表名;
    ** 修改表:
    **** 增加列:ALTER TABLE 表名 ADD (
    列名 列类型,

    列名 列类型
    );
    **** 删除列:ALTER TABLE 表名 DROP 列名;
    **** 修改列类型:ALTER TABLE 表名 MODIFY 列名 新的列类型; -->精度不能低于已保存的数据
    **** 修改表名:ALTER TABLE 表名 RENAME TO 新表名;
    **** 修改列名:ALTER TABLE 表名 CHANGE 列名 新列名 列类型;

三、DML

查询语法:SELECT 列名1,列名2… FROM 表名 条件(WHERE…);
插入语法:INSERT INTO 表名(列1,列2…) VALUES(列1值, 列2值…);注意前后列表的顺序
INSERT INTO 表名 VALUES(列1值,列2值…);
修改数据:UPDATE 表名 SET 列1名=列1值,列2名=列2值… (WHERE 条件);
** WHERE条件是可选的
**>条件必须是一个boolean类型的值或者表达式
**>运算符:=、<>、!=、<、>、>=、<=、
between … and … 、IN(…)、IS NULL 、NOT、 OR、 AND
注意:>is null是可以用来判空的表达式,where a=null (这种条件是无法实现判空的)
>where a=‘n’ 相当于Java中的 a==“b”
>in() 相当于一个集合,里面可以是各种数据类型,表示一个取值范围。not in()
删除数据
DELETE FROM 表名 (WHERE 条件);
TRUNCATE TABLE 表名;它是先删除drop该表,再CREATE该表,无法rollback。

四、DCL

一个项目创建一个用户,一个项目对应的数据库只有一个
这个用户只能对这个数据库有权限,其他数据库你就操作不了

  1. 创建用户
    CREATE USER 用户名@IP IDENTIFIED BY ‘密码’;
    CREATE USER 用户名@‘%’ IDENTIFIED BY ‘密码’; //任意ip
    登陆:mysql -u用户名 -p密码 -hIP地址
    注意;切换用户时需要先退出当前用户,exit/quit

  2. 授权用户----需要在root用户下才能进行授权
    GRANT 权限1,2… ON 数据库. TO 用户名@IP;*
    给用户分派在指定数据库上的权限,
    如:GRANT CREATE,ALTER,UPDATE,DELETE,SELECT,INSERT,DROP ON mydata.* TO user@localhost;
    —>给user这个用户在mydata数据库上的上述权限
    或者 GRANT ALL ON mydata.* TO user@localhost ; //直接分派所有权限
    结构:REVOKE/GRANT … ON database.* TO user

  3. 撤销权限
    REVOKE 权限1,2…,ON 数据库.* TO 用户名@IP;
    撤销指定用户在指定数据库上的指定权限

  4. 查看权限
    SHOW GRANT FOR 用户名@IP;

  5. 删除用户
    DROP USER 用户名@IP;

  6. 查看当前有哪些用户
    select user,host from mysql.user;

五、DQL

  1. 基础查询
    (1)查询列: select * from 表名;
    select 列1,列2… from 表名;
    (2)去重查询:select DISTINCT 列1,列2… from 表名;
    (3)列运算:
    **数值型的可以做加、减、乘、除运算
    **非数值型的运算结果为0,null运算全为null
    **字符串连接:select CONCAT(’$’,sal) from emp ,注意区分oracle的 ||
    **转换NULL值:IFNULL(comm,o); comm里面的null值以0来运算
    (4)给列起别名:
    select 列名1 [AS] 别名1,列名2 [AS] 别名2… from 表名;
    AS可以省略

  2. 条件控制
    (1)条件查询 WHERE
    条件:=、<>、!=、<、>、>=、<=、
    between … and … 、IN(…)、IS NULL 、IS NOT NULL、NOT、 OR、 AND
    (2)模糊查询 LIKE
    下划线‘_’表示一个任意字符
    百分号‘%’表示0个或n个字符

  3. 排序 ORDER BY
    (1)升序:SELECT 列名 FROM EMP ORDER BY 列名 [ASC]; 默认为升序,故ASC可以省略
    (2)降序:ORDER BY 列名 DESC
    (3)多列排序:ORDER BY 列名1 DESC,列名2 ASC, 列名3 DESC;
    –>先按照列1排序,在列1中相同的情况下按照列2排序。。。。

  4. 聚合函数
    聚合函数用来做某一列的纵向
    (1)COUNT(列名或者*)
    COUNT(数字)与COUNT(*)的作用一样的
    (2)SUM(列名) 求和
    (3)MAX(列名) 最大值
    (4)MIN(列名) 最小值
    (5)AVG(列名) 平均值

  5. 分组查询 GROUP BY
    组信息只有聚合函数+分组名
    如:select job,max(sal) from emp group by job;
    分组前条件限制:WHERE 条件 GROUP BY …
    分组后条件限制: GROUP BY … HAVING + 聚合函数
    –> select deptno,count() from emp where sal>2000 group by deptno having count()>2;

总结:一般查询语句完整结构 SELECT 列名1, … FROM 表名 WHERE 条件限制 GROUP BY 列名 HAVING
条件(聚合函数) ORDER BY 列名 [ASC/DESC]

  1. LIMIT子句
    用来查询限定结果的起始行,以及总行数
    SELECT * FROM EMP LIMIT 0,5; -->表示从第一行开始,往下查询5行记录
    常用来做分页查询操作:
    limit (页数-1)*查询的行数 ,查询的行数

**

六、练习

**

  1. 查询出部门编号为30的所有员工
    SELECT * FROM emp1 WHERE deptno = 30;

  2. 查询出所有销售员的姓名,编号以及部门编号
    SELECT ename,empno,deptno FROM emp1 WHERE job = ‘销售员’;

  3. 找出奖金高于工资的员工
    SELECT * FROM emp1 WHERE comm > sal;

  4. 找出奖金高于工资60%的员工
    SELECT * FROM emp1 WHERE comm > sal*0.6;

  5. 找出部门编号为10中的所有经理,和部门编号为20中所有的销售员的详细资料
    SELECT * FROM emp1 WHERE (job=‘经理’ AND deptno=10) OR (deptno=20 AND job=‘销售员’);
    【用数学集合的概念去理解OR ,求的并集】

  6. 找出部门编号为10中的所有经理,部门编号为20中的所有销售员,还有既不是经理也不是销售员但其工资大于或等于2w的所有员工详细资料。
    SELECT * FROM emp1 WHERE (job=‘经理’ AND deptno=10) OR (deptno=30 AND job=‘销售员’) or( job not in(‘经理’,‘销售员’) and sal>20000;)

  7. 无奖金或奖金低于1000的员工
    SELECT ename FROM emp1 WHERE comm is NULL OR comm <1000;

  8. 查询姓名由三个字组成的员工
    SELECT ename FROM emp1 WHERE ename LIKE ‘___’;

  9. 查询2000年入职的员工
    SELECT ename ,hiredate from emp1 where hiredate BETWEEN ‘2000-01-01’ and ‘2000-12-31’;
    SELECT ename ,hiredate from emp1 where hiredate LIKE ‘2000-%’;

  10. 查询所有员工的详细信息,并用编号升序排序
    SELECT * from emp1 ORDER BY empno ASC;

  11. 查询所有员工的详细信息,并用工资降序排序,如果工资相同使用入职时间升序排序
    SELECT * from emp1 ORDER BY sal DESC,hiredate ASC;

  12. 查询每个部门的平均工资
    SELECT deptno ,AVG(sal) FROM emp GROUP BY deptno;

  13. 查询每个部门员工数
    SELECT deptno,COUNT(*) FROM emp1 GROUP BY deptno;

  14. 查询每种工作的最高工资、最低工资、人数
    SELECT job,MAX(sal),MIN(sal),COUNT(*) FROM emp1 GROUP BY job;

  15. 有奖金的工种
    select job from emp1 where comm is not null;

  16. 非销售人员job以及从事同一工作的员工的月工资的总和,并且要满足从事同一工作的雇员的月工资总和大于50000,输出结果按月工资升序排列

七、备份与恢复

利用工具(第三方软件:如Navicat)进行备份和数据恢复。简单快捷

  1. 数据库导出SQL脚本

    mysqldump -u用户名 -p密码 数据库名>生成的脚本文件路径
    注意:不要登录mysql,离线状态下在cmd下运行
    注意:生成的SQL脚本中没有创建数据库的语句,在恢复数据时需要自行create database 数据库名

  2. 执行SQL脚本,恢复数据
    (1)离线状态下:

    mysql -u用户名 -p密码 数据库名<生成的脚本文件路径
    注意:需要自己create database 数据库名,之后才行
    (2)登录状态下:

    source 路径xx.xxx.sql

八、约束

约束是添加在列上的,是用来约束列的。

  1. 主键约束(唯一标识) :非空、唯一、被引用(外键就是引用主键的)
    (1)PRIMARY KEY在创建表时使用
    CREATE TABLE tb1(
    列名1 列类型 PRIMARY KEY,

    );
    CREATE TABLE tb1(
    列名1 列类型 ,

    列名n 列类型,
    PRIMARY KEY(列x)
    );
    (2)添加主键
    ALTER TABLE 表名 ADD PRIMARY KEY(列名);
    (3)删除主键
    ALTER TABLE 表名 DROP PRIMARY KEY;
  • 主键自增长: primary key auto_increment
    (1)主键特性是非空和唯一,所以通常会指定主键为整型,然后设置其自增长。
    (2)指定主键自增长后,如果第一条insert into语句主键值为null,那么自增长会从1开始,该条记录的主键为1。
    (3)如果当主键为1111时,清空当前表,再次插入数据时,如果不指定主键,则会从1112开始。
    (4)局限性:在群集环境下就不好用了,只能控制当前表单的,所有实际中使用UUID作为主键,不重复。
    (5)设置自增长

    CREATE TABLE tb1(
    列名1 列类型 PRIMARY KEY AUTO_INCREMENT,

    );

  • 修改为自增长:ALTER TABLE 表名 CHANGE 列名x 列名x 类型 AUTO_INCREMENT;
    ALTER TABLE tb1 CHANGE id id INT(4) AUTO_INCREMENT;
  • 删除自增长:ALTER TABLE 表名 CHANGE 列名x 列名x 类型;
  1. 非空约束:NOT NULL

  2. 唯一约束:UNIQUE

    CREATE TABLE tb1(
    列名1 列类型 NOT NULL UNIQUE,

    );

  3. 概念模型
    对象模型:在Java中是domain。如User、Student
    关系模型:在数据库中的表!只有多方引用一方的主键
    当我们要完成一个软件系统时,需要把系统中实体抽取出来新城概念模型,实习最终会成为Java中的类、数据库中的表。

    关系分析:
    1对1:夫妻关系 【不常见】
    1对多:一个员工属于一个部门,一个部门可以有多个员工
    多对多:老师和学生的关系,一个学生可以有多个老师,一位老师可以有多位学生
    主从关系:少数的为主,多数为从,【常见:多对1】
    概念模型中的实体在Java中成为实体类(JavaBean)
    类就使用成员变量来完成关系,一般为双向关联
    多对一双向关联,即员工关联部门,部门也关联员工

6. 外键约束
FOREGIN KEY
在表中实现关联关系,需要使用外键
外键必须引用另一张表的主键
外键可以重复
外键可以为空null
一张表可以有多个外键
可以引用自身的主键,自身关联
在表中,只有多方引用一方
例如:一个用户可以有多个订单,而一个订单只属于一个用户。
所以,只有在订单表中有用户ID作为外键,而用户表中没有引用订单的。

  CREATE TABLE emp(
    	empno INT PRIMARY KEY,
    	name  varchar(20),
    	deptno INT ,
    	CONSTRAINT fk_emp_dept FOREIGN KEY(deptno) REFERENCES dept(deptno)
    );

CONSTRAINT fk_xx_yy FOREIGN KEY(当前表中的字段) REFERENCES 关联表名(主键字段)

添加约束:
ALTER TABLE emp ADD CONSTRAINT pk_emp PRIMARY KEY(empno);
ALTER TABLE emp ADD CONSTRAINT fk_emp_dept FOREIGN KEY(deptno) REFERENCES dept(deptno);
(1)一对一关系
【从表的主键也是外键】
create table husband(
hid int primary key,
hname varchar(20)
);
create table wife(
wid int primary key,
wname varchar(20),
constraint fk_wife_husband foreign key(wid) reference husband(hid)
);
此时wife的wid既是wife表的主键,又是外键(会引用外键hid)
根据主键和外键的特性,可以保证一对一关系
(2)多对多关系
【利用中间表来建立关联】

九.多表查询

1. 分类:
合并结果集
连接查询:一次查询多个表
子查询
2. 合并结果集
要求两个结果集的结构相同(列数以及列类型相同)
注意:结果集可以是一张表也可以是表的一部分(select deptno from emp;也是结果集)
结果集1 UNION 结果集2;去除重复的行
结果集1 UNION ALL 结果集2;不去除重复行

3. 链接查询
3-1. 分类:

  • 内连接
  • 外连接
  • 左外连接
  • 右外连接
  • 全外连接(MySQL不支持)
  • 自然连接(简化方式)

3-2. 内连接:INNER JOIN … ON
利用主外键去除笛卡尔积【无效信息】
例如:SELECT e.ename ,e.sal, d.dname,d.loc FROM emp1 e,dept1 d WHERE e.deptno=d.deptno;
方言:SELECT 别名1.列名1 ,…别名2.列名1… FROM 表1 别名1,表2 别名2 WHERE 别名1.xx=别名2.yy;
标准:SELECT … FROM 表1 别名1 INNER JOIN 表2 别名2 ON 别名1.xx=别名2.yy;
自然:SELECT … FROM 表1 别名1 NATURAL JOIN 表2 别名2 ; (可读性不好)

尽量采用标准写法,扩展性比较好,方言只适用于MySQL

3-3. 外连接

  • 左外连接:LEFT OUTER JOIN … ON
    外连接有一主一次,左外即左表为主,那么左表所有数据都会被打印,
    如果左表数据不满足ON条件时,右表用null来补足。

  • 右外连接:RIGHT OUTER JOIN … ON
    外连接有一主一次,右外即右表为主,那么右表所有数据都会被打印,
    如果右表数据不满足ON条件时,右表用null来补足。

  • 全外连接(MySQL不支持)FULL JOIN … ON
    可以通过 左外 UNION 右外 来实现这种效果

4. 子查询
SELECT * FROM emp1 WHERE sal=(SELECT MAX(sal) FROM emp1 );
出现的位置:一般出现在WHERE/FROM 后
SELECT t.ename, t.empno FROM (SELECT * FROM emp1 where deptno=20 )t ;
子查询的结果集:
**单行单列:通常用在where条件里
**多行多列:通常用在from后作为一个结果集
**多行单列:可以用ALL / ANY / IN来对结果集进行比较

例1:查询emp1中比20部门的所有人工资都高的人。
SELECT * FROM emp1 WHERE sal > ALL (SELECT sal FROM emp1 WHERE deptno=20);
例2:查询emp1中比20部门的任意一个人的工资都高的人。
SELECT * FROM emp1 WHERE sal > ANY (SELECT sal FROM emp1 WHERE deptno=20);
例3:查询emp1中和20部门中工资相同的人
SELECT * FROM emp1 WHERE sal > IN (SELECT sal FROM emp1 WHERE deptno=20);

**单行多列
可以拿来表示一个对象
例如:查询和empno=1003的工资、工作以及部门相同的人。
SELECT * FROM emp1 WHERE
( sal, job, deptno ) IN ( SELECT sal, job, deptno FROM emp1 WHERE empno = 1003 );

十. 实例

  1. 查出至少有一个员工的部门。显示部门编号,部门名称,部门位置,部门人数。
SELECT d.*, e.num1 '人数'
FROM dept1 d INNER JOIN 
(SELECT deptno,count(*) num1 FROM emp1 GROUP BY deptno HAVING COUNT(*)>1)e
ON e.deptno=d.deptno;
  1. 列出所有员工的姓名及其直接上级的姓名
SELECT e1.ename, IFNULL(e2.ename,'BOSS') '上司' 
FROM emp1 e1 LEFT OUTER JOIN emp1 e2 ON e1.mgr=e2.empno;

  1. 列出受雇日期早于直接上级的所有员工的编号,姓名,部门名称。
分析:先获取受雇日期早于直接上级的所有员工的编号,姓名,部门
SELECT e1.ename, e1.empno,e1.deptno
FROM emp1 e1 INNER JOIN emp1 e2 ON e1.mgr=e2.empno AND e1.hiredate>e2.hiredate;

正式版:
SELECT e.ename,e.empno,d.dname 
FROM emp1 e INNER JOIN emp1 m INNER JOIN dept1 d
ON e.mgr=m.empno AND e.hiredatem.hiredate AND  d.deptno = e.deptno;
  1. 列出部门名称和这些员工信息,同时列出那些没有员工的部门。
SELECT e.*,d.* FROM emp1 e RIGHT JOIN dept1 d
ON e.deptno=d.deptno;
  1. 列出最低薪酬大于15000的各种工作以及从事此工作的员工人数
SELECT job,count(*) '人数'
FROM emp1 
GROUP BY job
HAVING min(sal)>15000;
  1. 列出在销售部工作的员工的姓名,假定不知怎的销售部的部门编号
SELECT ename 
FROM emp1 
WHERE deptno =(SELECT deptno FROM dept1 WHERE dname='销售部');
  1. 列出薪水高于公司平均薪水的所有员工及部门名称
SELECT e.*,d.dname 
FROM emp1 e,dept1 d
WHERE sal>(SELECT avg(sal) FROM emp1) AND e.deptno=d.deptno;
  1. 列出薪水高于公司平均薪水的所有员工信息,所在部门名称,上级领导,工资等级
SELECT e.*,d.dname,IFNULL(m.ename,'BOSS') '上司',s.grade
FROM emp1 e INNER JOIN dept1 d ON e.deptno=d.deptno
	         LEFT JOIN emp1 m ON e.mgr=m.empno
	         INNER JOIN salgrade1 s ON e.sal BETWEEN s.lowsal AND s.hisal
WHERE e.sal>(SELECT avg(sal) FROM emp1);	

—>如果全部是内连接,可以采用方言形式,但是内连接与外连接嵌套使用需要
每连接一次ON一次条件

SELECT e.*,d.dname,IFNULL(m.ename,'BOSS') '上司',s.grade
FROM emp1 e , dept1 d ,emp1 m ,salgrade1 s 
WHERE e.sal>(SELECT avg(sal) FROM emp1) AND e.deptno=d.deptno AND 		e.mgr=m.empno
AND e.sal BETWEEN s.lowsal AND s.hisal;
  1. 列出与庞统从事相同工作的所有员工及部门名称
SELECT e.*,d.dname 
	FROM emp1 e,dept1 d  
	WHERE job=(SELECT job FROM emp1 WHERE ename='庞统') AND 				e.deptno=d.deptno;
  1. 列出薪水高于在部门30工作的所有员工的薪水的员工 的姓名和薪金、部门名称
SELECT e.*,d.dname 
FROM emp1 e,dept1 d
WHERE sal> ALL(SELECT sal FROM emp1 WHERE deptno=30) AND e.deptno=d.deptno;
  1. 【面试题】根据tb_year中的年份和营业额,计算年增长率
SELECT t1.*,IFNULL(CONCAT((t1.zz-t2.zz)/t2.zz*100,'%'),'0%') '增长比'
FROM tb_year t1 LEFT JOIN tb_year t2
ON t1.year=(t2.year+1)
ORDER BY t1.year;

你可能感兴趣的:(MySQL)