SQL不区分大小写,但建议关键字大写
**show databases; //查看当前用户下所有的数据库
** use 数据库名 //切换数据库
** show tables; //查看当前数据库名下所有的表
** 创建数据库:CREATE DATABASE [IF NOT EXISTS] 数据库 [CHARSET=utf8]
** 删除数据库:DROP DATABASE [IF EXISTS] 数据库名
** 修改数据库编码类型:ALTER DATABASE mysb1 CHARACTER SET UTF8
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
查询语法: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。
一个项目创建一个用户,一个项目对应的数据库只有一个
这个用户只能对这个数据库有权限,其他数据库你就操作不了
创建用户
CREATE USER 用户名@IP IDENTIFIED BY ‘密码’;
CREATE USER 用户名@‘%’ IDENTIFIED BY ‘密码’; //任意ip
登陆:mysql -u用户名 -p密码 -hIP地址
注意;切换用户时需要先退出当前用户,exit/quit
授权用户----需要在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
撤销权限
REVOKE 权限1,2…,ON 数据库.* TO 用户名@IP;
撤销指定用户在指定数据库上的指定权限
查看权限
SHOW GRANT FOR 用户名@IP;
删除用户
DROP USER 用户名@IP;
查看当前有哪些用户
select user,host from mysql.user;
五、DQL
基础查询
(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可以省略
条件控制
(1)条件查询 WHERE
条件:=、<>、!=、<、>、>=、<=、
between … and … 、IN(…)、IS NULL 、IS NOT NULL、NOT、 OR、 AND
(2)模糊查询 LIKE
下划线‘_’表示一个任意字符
百分号‘%’表示0个或n个字符
排序 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排序。。。。
聚合函数
聚合函数用来做某一列的纵向
(1)COUNT(列名或者*)
COUNT(数字)与COUNT(*)的作用一样的
(2)SUM(列名) 求和
(3)MAX(列名) 最大值
(4)MIN(列名) 最小值
(5)AVG(列名) 平均值
分组查询 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]
**
**
查询出部门编号为30的所有员工
SELECT * FROM emp1 WHERE deptno = 30;
查询出所有销售员的姓名,编号以及部门编号
SELECT ename,empno,deptno FROM emp1 WHERE job = ‘销售员’;
找出奖金高于工资的员工
SELECT * FROM emp1 WHERE comm > sal;
找出奖金高于工资60%的员工
SELECT * FROM emp1 WHERE comm > sal*0.6;
找出部门编号为10中的所有经理,和部门编号为20中所有的销售员的详细资料
SELECT * FROM emp1 WHERE (job=‘经理’ AND deptno=10) OR (deptno=20 AND job=‘销售员’);
【用数学集合的概念去理解OR ,求的并集】
找出部门编号为10中的所有经理,部门编号为20中的所有销售员,还有既不是经理也不是销售员但其工资大于或等于2w的所有员工详细资料。
SELECT * FROM emp1 WHERE (job=‘经理’ AND deptno=10) OR (deptno=30 AND job=‘销售员’) or( job not in(‘经理’,‘销售员’) and sal>20000;)
无奖金或奖金低于1000的员工
SELECT ename FROM emp1 WHERE comm is NULL OR comm <1000;
查询姓名由三个字组成的员工
SELECT ename FROM emp1 WHERE ename LIKE ‘___’;
查询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-%’;
查询所有员工的详细信息,并用编号升序排序
SELECT * from emp1 ORDER BY empno ASC;
查询所有员工的详细信息,并用工资降序排序,如果工资相同使用入职时间升序排序
SELECT * from emp1 ORDER BY sal DESC,hiredate ASC;
查询每个部门的平均工资
SELECT deptno ,AVG(sal) FROM emp GROUP BY deptno;
查询每个部门员工数
SELECT deptno,COUNT(*) FROM emp1 GROUP BY deptno;
查询每种工作的最高工资、最低工资、人数
SELECT job,MAX(sal),MIN(sal),COUNT(*) FROM emp1 GROUP BY job;
有奖金的工种
select job from emp1 where comm is not null;
非销售人员job以及从事同一工作的员工的月工资的总和,并且要满足从事同一工作的雇员的月工资总和大于50000,输出结果按月工资升序排列
利用工具(第三方软件:如Navicat)进行备份和数据恢复。简单快捷
mysqldump -u用户名 -p密码 数据库名>生成的脚本文件路径
注意:不要登录mysql,离线状态下在cmd下运行
注意:生成的SQL脚本中没有创建数据库的语句,在恢复数据时需要自行create database 数据库名
mysql -u用户名 -p密码 数据库名<生成的脚本文件路径
注意:需要自己create database 数据库名,之后才行
(2)登录状态下:
source 路径xx.xxx.sql
约束是添加在列上的,是用来约束列的。
CREATE TABLE tb1(
列名1 列类型 PRIMARY KEY AUTO_INCREMENT,
…
);
非空约束:NOT NULL
唯一约束:UNIQUE
CREATE TABLE tb1(
列名1 列类型 NOT NULL UNIQUE,
…
);
概念模型
对象模型:在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 );
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;
SELECT e1.ename, IFNULL(e2.ename,'BOSS') '上司'
FROM emp1 e1 LEFT OUTER JOIN emp1 e2 ON e1.mgr=e2.empno;
分析:先获取受雇日期早于直接上级的所有员工的编号,姓名,部门
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;
SELECT e.*,d.* FROM emp1 e RIGHT JOIN dept1 d
ON e.deptno=d.deptno;
SELECT job,count(*) '人数'
FROM emp1
GROUP BY job
HAVING min(sal)>15000;
SELECT ename
FROM emp1
WHERE deptno =(SELECT deptno FROM dept1 WHERE dname='销售部');
SELECT e.*,d.dname
FROM emp1 e,dept1 d
WHERE sal>(SELECT avg(sal) FROM emp1) AND e.deptno=d.deptno;
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;
SELECT e.*,d.dname
FROM emp1 e,dept1 d
WHERE job=(SELECT job FROM emp1 WHERE ename='庞统') AND e.deptno=d.deptno;
SELECT e.*,d.dname
FROM emp1 e,dept1 d
WHERE sal> ALL(SELECT sal FROM emp1 WHERE deptno=30) AND e.deptno=d.deptno;
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;