1.端口号
- 端口号Port是任何一个软件/运用都会有的,端口号是运用的仅有代表。
- 端口号一般和IP地址在一块,IP地址用来定位核算机的,端口号port
- 是用来定位核算机上某个服务的/某个运用的!
- 在同一台核算机上,端口号不能重复。具有仅有性。
Mysql数据库发动的时分,这个服务占有的默许端口号是3306,这是咱们都知道的事儿。记住。
2.发动和封闭mysql服务
在windows操作系统傍边,怎样运用指令来发动和封闭mysql服务呢?
- 语法:
- net stop服务称号:net stop MySql
- net start服务称号;net satrt MySql
1.运用客户端登录MySql
1.本地登录(显现编写密码的方法)
PS C:\WINDOWS\system32> mysql -uroot -p123456
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.5.36 MySQL Community Server (GPL)
Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
2.本地登录(躲藏编写密码的方法)
PS C:\WINDOWS\system32> mysql -uroot -p
Enter password: ******
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.5.36 MySQL Community Server (GPL)
Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
3.mysql常用指令
-
退出mysql:exit
-
检查数据库
检查mysql中有哪些数据库?
show databases;
注:以分号完毕,分号是英文的分号。
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| test |
+--------------------+
4 rows in set (0.01 sec)
- 运用数据库
ysql默许自带了4个数据库。
如何挑选运用某个数据库呢?
mysql>use test;
Database changed
表明正在运用一个名字叫做test的数据库。
检查数据库中的表 show tables
- 怎样创立数据库
create database 数据库名字;
mysql> create database j;
- 检查当时数据库的版别号
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.5.36 |
+-----------+
1 row in set (0.00 sec)
- 检查当时运用的是哪个数据库
mysql> select database();
+-------------+
| database() |
+-------------+
| bjpowernode |
+-------------+
留意 以上的指令不区分大小写
mysql是不见“;”不履行,“;”表明完毕
mysql> show
->
-> databases
->
-> ;
+--------------------+
| Database |
+--------------------+
| information_schema |
| bjpowernode |
| j |
| mysql |
| performance_schema |
| test |
+--------------------+
mysql> show
->
->
->
-> \c
mysql>
- \c用来终止一条指令的输入
4.table
数据库中最根本的单元是表:table
数据库傍边是以表格的方法表明数据的。 由于表比较直观
任何一张表都有行和列:
行(row):被称为数据/记载。
列(column):被称为字段。
5.Sql句子分类
分为
DQL:
数据查询语言(但凡带有select关键字的都是查询句子)
select...
DML:
数据操作语言(但凡对表傍边的数据进行增修正的都是DML)
insert delete update
insert增
delete删
update改
这个首要是操作表中的数据data。
DDL:
数据界说语言
但凡带有create、drop、alter的都是DDL.
DDL首要操作的是表的结构。不是表中的数据。
create:新建,等同于增
drop:删去
alter:修正
这个增修正和D匹不同,这个首要是对表结构进行操作。
TCL
是业务操控语言
包含:业务提交:commit
业务回滚:rollback
DCl
是数据操控语言
例如:授权grant,吊销权限revoke....
6.导入数据库
登录 -> 创立数据库
create database bjpowernode; ->
运用数据库 use bjpowernode->
导入数据库source D:\bjpowernode.sql
7.数据库中的表
mysql> show tables;
+-----------------------+
| Tables_in_bjpowernode |
+-----------------------+
| dept |
| emp |
| salgrade |
+-----------------------+
3 rows in set (0.00 sec)
- dept是部分表
- emp是职工表
- salgrade是薪酬等级表
1.检查表中的数据
select * from emp;
+-------+--------+-----------+------+------------+---------+---------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+--------+-----------+------+------------+---------+---------+--------+
| 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 |
| 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
| 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 |
| 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 |
| 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
| 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 |
| 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
| 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | 0.00 | 30 |
| 7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100.00 | NULL | 20 |
| 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | NULL | 30 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
| 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 |
+-------+--------+-----------+------+------------+---------+---------+--------+
14 rows in set (0.00 sec)
2. 看结构
不看表中的数据,只看结构
descirbe
mysql> desc emp;
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| EMPNO | int(4) | NO | PRI | NULL | |
| ENAME | varchar(10) | YES | | NULL | |
| JOB | varchar(9) | YES | | NULL | |
| MGR | int(4) | YES | | NULL | |
| HIREDATE | date | YES | | NULL | |
| SAL | double(7,2) | YES | | NULL | |
| COMM | double(7,2) | YES | | NULL | |
| DEPTNO | int(2) | YES | | NULL | |
+----------+-------------+------+-----+---------+-------+
8 rows in set (0.01 sec)
3.简单查询
- 查询一个字段(列)
select 字段名
from 表名;
其间要留意:
select和from都是关键字.
字段名和表名都是标识符
强调:
关于SQL句子来说,是通用的,
一切的SQL句子以";"完毕。
另外SQL句子不区分大小写,都行。
查询部分名字?
select ename from emp;
+--------+
| ename |
+--------+
| SMITH |
| ALLEN |
| WARD |
| JONES |
| MARTIN |
| BLAKE |
| CLARK |
| SCOTT |
| KING |
| TURNER |
| ADAMS |
| JAMES |
| FORD |
| MILLER |
+--------+
- 查询两个字段,或许多个字段怎样办? 运用逗号离隔”,”
mysql> select ename,job from emp;
- 查询一切字段 榜首种方法 能够把每个字段都写上 select a,b,c,d,e,f, ….from tablename; 第二种方法select * from dept;
这种方法的缺陷:
- 功率低
- 可读性差
在实践开发中不主张,能够自己玩没问题。你能够在D0S指令窗口中想快速的看一看全表数据能够选用这种方法。
实践开发中仍是主张把一切的字段都写上
4.给查询的列起别号
mysql> select ename as b,job as a from emp;
+--------+-----------+
| b | a |
+--------+-----------+
| SMITH | CLERK |
| ALLEN | SALESMAN |
| WARD | SALESMAN |
| JONES | MANAGER |
| MARTIN | SALESMAN |
| BLAKE | MANAGER |
| CLARK | MANAGER |
| SCOTT | ANALYST |
| KING | PRESIDENT |
| TURNER | SALESMAN |
| ADAMS | CLERK |
| JAMES | CLERK |
| FORD | ANALYST |
| MILLER | CLERK |
运用as关键字起别号。
留意:仅仅将显现的查询成果列名显现为deptname,原表列名仍是叫:dname
记住:select句子是永久都不会进行修正操作的。(由于只负责查询)
as关键字能够省掉吗?能够的
mysql> select ename as b,job a from emp;
假定起别号的时分,别号里面有空格,怎样办
mysql> select ename as b,job a b from emp;
编译报错
处理方法
mysql> select ename as b,job 'a b' from emp;//加单引号
mysql> select ename as b,job "a b" from emp;//加双引号
留意:在一切的数据库傍边,字符串一起运用单引号括起来,
单引号是标准,双引号在oracle数据库中用不了。可是在mysql
中能够运用。
5.数学运算
mysql> select ename as b,sal * 12 from emp;//字段能够运用数学表达式
+--------+----------+
| b | sal * 12 |
+--------+----------+
| SMITH | 9600.00 |
| ALLEN | 19200.00 |
| WARD | 15000.00 |
| JONES | 35700.00 |
| MARTIN | 15000.00 |
| BLAKE | 34200.00 |
| CLARK | 29400.00 |
| SCOTT | 36000.00 |
| KING | 60000.00 |
| TURNER | 18000.00 |
| ADAMS | 13200.00 |
| JAMES | 11400.00 |
| FORD | 36000.00 |
| MILLER | 15600.00 |
+--------+----------+
mysql> select ename as b,sal * 12 '年薪'from emp;//起别号,别号是中文,用单引号括起来
6.条件查询
什么是条件查询
select
字段1,字段2...
from
表名
where
条件;
= 等于
查询薪资等于800的职工名字和编号?
mysql> select ename ,empno from emp where sal = 800;
+-------+-------+
| ename | empno |
+-------+-------+
| SMITH | 7369 |
+-------+-------+
<> 或 != 不等于
mysql> select ename ,empno from emp where sal != 800;
+--------+-------+
| ename | empno |
+--------+-------+
| ALLEN | 7499 |
| WARD | 7521 |
| JONES | 7566 |
| MARTIN | 7654 |
| BLAKE | 7698 |
| CLARK | 7782 |
| SCOTT | 7788 |
| KING | 7839 |
| TURNER | 7844 |
| ADAMS | 7876 |
| JAMES | 7900 |
| FORD | 7902 |
| MILLER | 7934 |
<
<=
>
>=
between ....and...两个值中间,等同于 >= and <=
mysql> select ename ,empno from emp where sal between 2450 and 3000;
+-------+-------+
| ename | empno |
+-------+-------+
| JONES | 7566 |
| BLAKE | 7698 |
| CLARK | 7782 |
| SCOTT | 7788 |
| FORD | 7902 |
+-------+-------+
select ename ,empno from emp where sal >= 2450 and sal<= 3000;
留意:运用between and的时分,有必要遵从左小右大。
是闭区间,包含两头的值
null
查询那些职工的补贴/补助为null is null
mysql> select ename ,empno comm from emp where comm is null;
+--------+------+
| ename | comm |
+--------+------+
| SMITH | 7369 |
| JONES | 7566 |
| BLAKE | 7698 |
| CLARK | 7782 |
| SCOTT | 7788 |
| KING | 7839 |
| ADAMS | 7876 |
| JAMES | 7900 |
| FORD | 7902 |
| MILLER | 7934 |
+--------+------+
mysql> select ename ,empno comm from emp where comm is not null;
留意:在数据库傍边null不能运用等号进行衡量。需求运用isnu11
由于数据库中的nu11代表什么也没有,它不是一个值,所以不能运用
等号衡量。
and 而且
or 或许
and 的优先级 比or高假如想让or先履行就加()就好了,假如不确定优先级直接加()
查询薪酬大于2500,而且部分编号为10或20的职工
mysql> select * from emp where sal> 2500 and deptno = 10 or deptno = 20;
+-------+-------+-----------+------+------------+---------+------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+-------+-----------+------+------------+---------+------+--------+
| 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 |
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 |
| 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
| 7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100.00 | NULL | 20 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
+-------+-------+-----------+------+------------+---------+------+--------+
找出薪酬大于2500而且部分编号为10的职工,或许20部分的一切职工
mysql> select * from emp where sal> 2500 and (deptno = 10 or deptno = 20);
+-------+-------+-----------+------+------------+---------+------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+-------+-----------+------+------------+---------+------+--------+
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 |
| 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
+-------+-------+-----------+------+------------+---------+------+--------+
in 包含,相当于多个or
select empno,ename,job from emp where job = 'MANAGER' or job = 'SALESMAN';
select empno,ename,job from emp where job in ('MANAGER','SALESMAN');
留意:in 不是一个区间,in 后边跟的是详细的值
查询薪资是800和5000的职工信息
mysql> select ename ,empno sal from emp where sal = 800 or sal = 5000
-> ;
+-------+------+
| ename | sal |
+-------+------+
| SMITH | 7369 |
| KING | 7839 |
+-------+------+
2 rows in set (0.00 sec)
mysql> select ename ,empno sal from emp where sal in (800,5000);//不是表明800-5000
+-------+------+
| ename | sal |
+-------+------+
| SMITH | 7369 |
| KING | 7839 |
+-------+------+
not in
7.含糊查询
称为含糊查询,支撑%号或下划线匹配
%匹配任意多个字符
下划线:任意一个字符。
(%是一个特殊的符号,也是一个特殊符号)
找出名字中带o的
mysql> select ename ,empno sal from emp where ename like '%o%';
+-------+------+
| ename | sal |
+-------+------+
| JONES | 7566 |
| SCOTT | 7788 |
| FORD | 7902 |
+-------+------+
找出以T完毕的
mysql> select ename ,empno sal from emp where ename like '%T';
+-------+------+
| ename | sal |
+-------+------+
| SCOTT | 7788 |
+-------+------+
找出名字以K开端的
mysql> select ename ,empno sal from emp where ename like 'K%';
+-------+------+
| ename | sal |
+-------+------+
| KING | 7839 |
+-------+------+
找出第二个字母是A的
mysql> select ename ,empno sal from emp where ename like '_A%';
+--------+------+
| ename | sal |
+--------+------+
| WARD | 7521 |
| MARTIN | 7654 |
| JAMES | 7900 |
+--------+------+
找出第三个字母是R的
mysql> select ename ,empno sal from emp where ename like '__R%';
+--------+------+
| ename | sal |
+--------+------+
| WARD | 7521 |
| MARTIN | 7654 |
| TURNER | 7844 |
| FORD | 7902 |
+--------+------+
找出带名字中有下滑线的
select ename ,empno sal from emp where ename like '%\_%';//转义字符
8.排序
1. 单字段排序
指定升序asc
mysql> select ename ,empno sal from emp order by sal;//默许是 升序
+--------+------+
| ename | sal |
+--------+------+
| SMITH | 7369 |
| ALLEN | 7499 |
| WARD | 7521 |
| JONES | 7566 |
| MARTIN | 7654 |
| BLAKE | 7698 |
| CLARK | 7782 |
| SCOTT | 7788 |
| KING | 7839 |
| TURNER | 7844 |
| ADAMS | 7876 |
| JAMES | 7900 |
| FORD | 7902 |
| MILLER | 7934 |
+--------+------+
指定降序加desc
mysql> select ename ,empno sal from emp order by sal desc;
+--------+------+
| ename | sal |
+--------+------+
| MILLER | 7934 |
| FORD | 7902 |
| JAMES | 7900 |
| ADAMS | 7876 |
| TURNER | 7844 |
| KING | 7839 |
| SCOTT | 7788 |
| CLARK | 7782 |
| BLAKE | 7698 |
| MARTIN | 7654 |
| JONES | 7566 |
| WARD | 7521 |
| ALLEN | 7499 |
| SMITH | 7369 |
+--------+------+
2.两、多字段排序
查询职工名字和薪资,要求依照薪资升序,假如薪资一样的话, 再依照名字升序摆放。
mysql> select ename ,empno sal from emp order by sal asc,ename asc;//sal在前,起主导,只要sal持平的时分,才会考虑启用ename排序
3.根据字段方位排(了解)
依照查询成果的第2 列sal排序
mysql> select ename ,empno sal from emp order by 2;//2表明第二列。第二列是sa1,
了解一下,不主张在开发中这样写,由于不健壮。由于列的次序很容易发生改变,列次序修正之后,2就废了。
4.综合事例
找出薪酬在1250到3000之间的职工信息,要求依照薪资降序摆放。
select ename, sal from emp where sal bewteen 1250 and 3000 order by sal;
关键字次序不能变
select
....
from
....
where
....
order by
....
以上句子的履行次序有必要把握:
榜首步:from
第二步:where
第三步:select
第四步:order by(排序总是在终究履行!)
8.数据处理函数
1.根本介绍
- 数据处理函数又被称为单行处理函数
- 单行处理函数的特色:一个输入对应一个输出。
- 和单行处理函数相对的是:多行处理函数。(多行处理函数特色:多个输入,对应1个输出!)
2.单行处理函数常见的有哪些?
Lower转换小写
mysql> select lower(ename) from emp;
+--------------+
| lower(ename) |
+--------------+
| smith |
| allen |
| ward |
| jones |
| martin |
| blake |
| clark |
| scott |
| king |
| turner |
| adams |
| james |
| ford |
| miller |
+--------------+
14 rows in set (0.00 sec)
mysql> select lower(ename)as ename from emp;
+--------+
| ename |
+--------+
| smith |
| allen |
| ward |
| jones |
| martin |
| blake |
| clark |
| scott |
| king |
| turner |
| adams |
| james |
| ford |
| miller |
+--------+
14个输入,终究仍是14个输出。这是单行处理函数的特色。、
upper转换大写
select upper(name) as name from t_student;
substr取子串(substr(被截取的字符串,开端下标,截取的长度))
mysql> select substr(ename,1,1) as ename from emp;
+-------+
| ename |
+-------+
| S |
| A |
| W |
| J |
| M |
| B |
| C |
| S |
| K |
| T |
| A |
| J |
| F |
| M |
+-------+
找出职工名字榜首个字母是A的职工信息?
榜首种含糊查询
select ename from emp where ename like 'A%'
第二种方法substr函数
select ename from emp where substr(ename,1,1) = 'A';
首字母大写
select concat (upper(substr(name,1,1)),substr(name,2,length (name)-1))as result from t_student;
concat函数进行字符串的拼接
select concat (empno,ename)from emp;
length取长度
select length(ename) as enamelength from emp;
+-------------+
| enamelength |
+-------------+
| 5 |
| 5 |
| 4 |
| 5 |
| 6 |
| 5 |
| 5 |
| 5 |
| 4 |
| 6 |
| 5 |
| 5 |
| 4 |
| 6 |
+-------------+
trim去空格
select *from emp where ename = trim(' KING')
+-------+-------+-----------+------+------------+---------+------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+-------+-----------+------+------------+---------+------+--------+
| 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
+-------+-------+-----------+------+------------+---------+------+--------+
str_to_date将字符串转换成日期
date format格局化日期
format设置千分位
round四舍五入
mysql> select 1000 as num from emp;//1000也是被作为一个字面量/字面值。
+------+
| num |
+------+
| 1000 |
| 1000 |
| 1000 |
| 1000 |
| 1000 |
| 1000 |
| 1000 |
| 1000 |
| 1000 |
| 1000 |
| 1000 |
| 1000 |
| 1000 |
| 1000 |
+------+
定论:select后边能够跟某个表的字段名,也能够跟字面量/字面值。
mysql> select round(123.45,0) as num from emp
-> ;
+-----+
| num |
+-----+
| 123 |
| 123 |
| 123 |
| 123 |
| 123 |
| 123 |
| 123 |
| 123 |
| 123 |
| 123 |
| 123 |
| 123 |
| 123 |
| 123 |
+-----+
14 rows in set (0.00 sec)
mysql> select round(123.45,1) as num from emp;
+-------+
| num |
+-------+
| 123.5 |
| 123.5 |
| 123.5 |
| 123.5 |
| 123.5 |
| 123.5 |
| 123.5 |
| 123.5 |
| 123.5 |
| 123.5 |
| 123.5 |
| 123.5 |
| 123.5 |
| 123.5 |
+-------+
mysql> select round(123.45,-1) as num from emp;
+-----+
| num |
+-----+
| 120 |
| 120 |
| 120 |
| 120 |
| 120 |
| 120 |
| 120 |
| 120 |
| 120 |
| 120 |
| 120 |
| 120 |
| 120 |
| 120 |
+-----+
rand()生成随机数
ifnul1能够将nul1转换成一个详细值
mysql> select ename , (sal+comm)*12 from emp;\
+--------+---------------+
| ename | (sal+comm)*12 |
+--------+---------------+
| SMITH | NULL |
| ALLEN | 22800.00 |
| WARD | 21000.00 |
| JONES | NULL |
| MARTIN | 31800.00 |
| BLAKE | NULL |
| CLARK | NULL |
| SCOTT | NULL |
| KING | NULL |
| TURNER | 18000.00 |
| ADAMS | NULL |
| JAMES | NULL |
| FORD | NULL |
| MILLER | NULL |
+--------+---------------+
留意:NULL只需参与运算,终究成果必定是NULL。为了防止这个现象,需求运用ifnull函数。
ifnu11函数用法:ifnul1(数据,被作为娜个值)
假如"数据"为NULL的时分,把这个数据结构作为哪个值。
mysql> select ename , (sal+ifnull(comm,0))*12 from emp;
+--------+-------------------------+
| ename | (sal+ifnull(comm,0))*12 |
+--------+-------------------------+
| SMITH | 9600.00 |
| ALLEN | 22800.00 |
| WARD | 21000.00 |
| JONES | 35700.00 |
| MARTIN | 31800.00 |
| BLAKE | 34200.00 |
| CLARK | 29400.00 |
| SCOTT | 36000.00 |
| KING | 60000.00 |
| TURNER | 18000.00 |
| ADAMS | 13200.00 |
| JAMES | 11400.00 |
| FORD | 36000.00 |
| MILLER | 15600.00 |
+--------+-------------------------+
case ...when..then...when..then..else..end
select ename, job, sal as oldsal, (case job when 'MANAGER' then sal*1.1 when 'SALESMAN' then sal*1.5 else sal end ) as newsal from emp;
3.分组函数/多行处理函数
多行处理函数的特色:输入多行,终究输出一行。
5个:
count
计数
sum
求和
avg
均匀值
max
最大值
min
最小值
核算最大薪酬
mysql> select max(sal) from emp;
+----------+
| max(sal) |
+----------+
| 5000.00 |
+----------+
1 row in set (0.00 sec)
核算最小薪酬
mysql> select min(sal) from emp;
+----------+
| min(sal) |
+----------+
| 800.00 |
+----------+
1 row in set (0.00 sec)
核算薪酬总和
mysql> select sum(sal) from emp;
+----------+
| sum(sal) |
+----------+
| 29025.00 |
+----------+
1 row in set (0.00 sec)
核算均匀薪酬
mysql> select avg(sal) from emp;
+-------------+
| avg(sal) |
+-------------+
| 2073.214286 |
+-------------+
1 row in set (0.00 sec)
mysql> select count(ename) from emp;
+--------------+
| count(ename) |
+--------------+
| 14 |
+--------------+
分组函数留意事项
-
分组函数主动忽略null,不需求对null进行处理
-
分组函数中count(*)和count(详细字段)有什么区别
mysql> select count(*) from emp;
+----------+
| count(*) |
+----------+
| 14 |
+----------+
1 row in set (0.00 sec)
mysql> select count(comm) from emp;
+-------------+
| count(comm) |
+-------------+
| 4 |
+-------------+
cout(详细字段):表明统计该字段下一切不为NULL的元素的总数。
count():统计表傍边的总行数。(只需有一行数据count则++)
由于每一行记载不或许都为NULL,一行数据中有一列不为NULL,则这行数据便是有用的。
- 分组函数不能够直接运用在where子句中。
找出比最低薪酬高的职工信息。
select ename,sal from emp where sal min(sal)i
表面上没问题,运行一下?
ERROR 1111 (HY000):Invalid use of group
function
- 一切的分组函数能够组合起来一重用。
mysql> select sum(sal),min(sal),max(sal),avg(sal),count(*) from emp;
+----------+----------+----------+-------------+----------+
| sum(sal) | min(sal) | max(sal) | avg(sal) | count(*) |
+----------+----------+----------+-------------+----------+
| 29025.00 | 800.00 | 5000.00 | 2073.214286 | 14 |
+----------+----------+----------+-------------+----------+
9.分组查询(十分重要)
在实践的运用中,或许有这样的需求,需求先进行分组,然后对每一组的数据进行操作这个时分咱们需求运用分组查询,怎样进行分组查询呢?
select
...
from
...
group by
...
核算每个部分的薪酬和?
核算每个作业岗位的均匀薪资?
找出每个作业岗位的最高薪资?
将之前的关键字悉数组合在一起,来看一下他们的履行次序?
select
...
from
...
where
...
group by
...
having
...
order by
...
以上关键字的次序不能颠倒,需求记忆。
履行次序是什么?
1.from
2.where
3.group by
4.having
5.select
6.order by
为什么分组函数不能直接运用在where后边?
select ename,sal from emp where sal>min(sal);//报错。
由于分组函数在运用的时分有必要先分组之后才干运用
where履行的时分,还没有分组。所以where后边不能呈现分组函数。
select sum(sal)from emp;
这个没有分组,为啥sum()函数能够用呢?
由于select在group by 之后履行,没有运用group by 默许进行分组
核算每个部分的薪酬和?
完结思路:依照作业岗位分组,然后对薪酬求和。
mysql> select job ,sum(sal) from emp group by job;
+-----------+----------+
| job | sum(sal) |
+-----------+----------+
| ANALYST | 6000.00 |
| CLERK | 4150.00 |
| MANAGER | 8275.00 |
| PRESIDENT | 5000.00 |
| SALESMAN | 5600.00 |
+-----------+----------+
以上这个句子的履行次序?
先从emp
先从emp表中查询数据。
根据job字段进行分组。
然后对每一组的数据进行sum(sal)
select ename,job,sum(sal)from emp group by job;
以上句子在ysql中能够履行,可是毫无意义。
以上句子在oracle中履行报错。
oracle的语法比mysql的语法严厉。(mysql的语法相对来说松懈一些!)
要点定论:
在一条select句子傍边,假如有group by句子的话,
select后边只能跟:参与分组的字段,以及分组函数。
其它的一律不能跟。
找出每个部分中最高薪资
依照部分编号分组,求每一组的最大值。
mysql> select deptno,max(sal) from emp group by deptno ;
+--------+----------+
| deptno | max(sal) |
+--------+----------+
| 10 | 5000.00 |
| 20 | 3000.00 |
| 30 | 2850.00 |
+--------+----------+
找出每个部分,不同作业岗位的最高薪资
mysql> select job,deptno,max(sal) from emp group by deptno,job ;
+-----------+--------+----------+
| job | deptno | max(sal) |
+-----------+--------+----------+
| CLERK | 10 | 1300.00 |
| MANAGER | 10 | 2450.00 |
| PRESIDENT | 10 | 5000.00 |
| ANALYST | 20 | 3000.00 |
| CLERK | 20 | 1100.00 |
| MANAGER | 20 | 2975.00 |
| CLERK | 30 | 950.00 |
| MANAGER | 30 | 2850.00 |
| SALESMAN | 30 | 1600.00 |
+-----------+--------+----------+
找出每个部分最高薪资,要求显现最高薪资于3000的?
运用having能够对分完组之后的数据进一步过滤。
having天能独自运用,having不能替代where,having有必要
和group by联合运用。
select deptno,max(sal) from emp group by deptno having max(sal) > 3000;
考虑一个问题:以上的sc1句子履行功率是不是低?
比较低,实践上能够这样考虑:先将大于3000的都找出来,然后再分组。
mysql> select deptno,max(sal) from emp where sal > 3000 group by deptno;
+--------+----------+
| deptno | max(sal) |
+--------+----------+
| 10 | 5000.00 |
+--------+----------+
优化战略:where和having,优先挑选where,where实在完结不了了,再挑选having.
where 没办法的????
我出每个部分均匀薪资,要求显现均匀薪资高于2500的
select deptno,avg(sal) from emp group by deptno having avg(sal ) > 2500
从某张表中查询数据,
先经过where条件挑选出有价值的数据。
对这些有价值的数据进行分组。
分组之后能够运用having继续挑选。
se1ect查询出来.
终究排序输出!
找出每个岗位的均匀薪资,要求显现均匀薪资大于1500的,除ANAGER岗位之外,
要求依照均匀薪资降序排。
select
job,avg(sal)as avgsal
from
emp
where
job !='MANAGER'
group by
job
having
avg(sa1)>1500
order by
avgsal desc;
10.去除重复记载(distinct)
留意:原表数据不会被修正,仅仅查询成果去重。 去重需求运用一个关键字:distinct
mysql> select distinct job from emp;;
+-----------+
| job |
+-----------+
| CLERK |
| SALESMAN |
| MANAGER |
| ANALYST |
| PRESIDENT |
+-----------+
//这样编写是过错的,语法过错
//distinct只能呈现在一切字段的最前方。
mysql> select ename,distinct job from emp;
distinct呈现在job,deptno两个字段之前,表明两个字段联合起来去重。
mysql> select distinct job,deptno from emp;;
+-----------+--------+
| job | deptno |
+-----------+--------+
| CLERK | 20 |
| SALESMAN | 30 |
| MANAGER | 20 |
| MANAGER | 30 |
| MANAGER | 10 |
| ANALYST | 20 |
| PRESIDENT | 10 |
| CLERK | 30 |
| CLERK | 10 |
+-----------+--------+
统计一下作业岗位的数量?
mysql> select count(distinct job) from emp;
+---------------------+
| count(distinct job) |
+---------------------+
| 5 |
+---------------------+
11.联接查询
1.根本介绍
- emp表和dept表联合起来查询数据,从emp表中取职工名字,从dept表中取部分名字。
- 这种跨表查询,多张表联合起来查询数据,被称为联接查询。
2.分类
根据表联接的方法分类:
内联接:
等值联接
非等值联接
自联接
外联接:
左外联接(左联接)
右外联接(右链接)
全联接
3.笛卡尔积现象
事例:查询每个职工地点部分称号?
mysql> select ename,deptno from emp;
+--------+--------+
| ename | deptno |
+--------+--------+
| SMITH | 20 |
| ALLEN | 30 |
| WARD | 30 |
| JONES | 20 |
| MARTIN | 30 |
| BLAKE | 30 |
| CLARK | 10 |
| SCOTT | 20 |
| KING | 10 |
| TURNER | 30 |
| ADAMS | 20 |
| JAMES | 30 |
| FORD | 20 |
| MILLER | 10 |
+--------+--------+
14 rows in set (0.00 sec)
mysql> select deptno,dname from dept;
+--------+------------+
| deptno | dname |
+--------+------------+
| 10 | ACCOUNTING |
| 20 | RESEARCH |
| 30 | SALES |
| 40 | OPERATIONS |
+--------+------------+
4 rows in set (0.00 sec)
mysql> select ename,dname from emp,dept;
+--------+------------+
| ename | dname |
+--------+------------+
| SMITH | ACCOUNTING |
| SMITH | RESEARCH |
| SMITH | SALES |
| SMITH | OPERATIONS |
| ALLEN | ACCOUNTING |
| ALLEN | RESEARCH |
| ALLEN | SALES |
| ALLEN | OPERATIONS |
56 rows in set (0.00 sec)
14 *4 = 56
当两张表进行联接查询,没有任何条件束缚的时分,终究查询成果条数,是
两张表条数的乘积,这种现象被称为:笛卡尔积现象。(笛卡尔发现的,这是
一个数学现象。)
怎样防止笛卡尔积现象?
联接时加条件,满意这个条件的记载被挑选出来!
select ename,dname from emp,dept where emp.deptno = dept.deptno;
+--------+------------+
| ename | dname |
+--------+------------+
| CLARK | ACCOUNTING |
| KING | ACCOUNTING |
| MILLER | ACCOUNTING |
| SMITH | RESEARCH |
| JONES | RESEARCH |
| SCOTT | RESEARCH |
| ADAMS | RESEARCH |
| FORD | RESEARCH |
| ALLEN | SALES |
| WARD | SALES |
| MARTIN | SALES |
| BLAKE | SALES |
| TURNER | SALES |
| JAMES | SALES |
+--------+------------+
考虑:终究查询的成果条数是14条,可是匹配的过程中,匹配的次数削减了吗?
仍是56次,只不过进行了四选一。次数没有削减。|
留意:经过笛卡尔积现象得出,表的联接次数越多功率越低,尽量防止表的
联接次数。
4.内联接
1.等值联接
查询每个职工地点部分称号,显现职工名和部分名?
emp e和dept d表进仃联接。条件是:e.deptno=d.deptno
sql 92
select e.ename,d.dname from emp e,dept e where e.deptno = d.deptno; //起别号
sql92的缺陷:结构不明晰,表的联接条件,和后期进一步挑选的条件,都放到了where后边。
sql99
select e.ename,d.dname from emp e join dept d on e.deptno = d.deptno;
inner能够省掉()
select e.ename,d.dname from emp e inner join dept d on e.deptno = d.deptno;
sq199长处:表联接的条件是独立的,联接之后,假如还需求进一步挑选,再往后继续增加where挑选
select
...
from
a
join
b
on
a和b的联接条件
where
...
2.非等值联接
事例:我出每个职工的薪资等级,要求显现职工名、薪资、薪资等级?
mysql> select * from emp;
+-------+--------+-----------+------+------------+---------+---------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+--------+-----------+------+------------+---------+---------+--------+
| 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 |
| 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
| 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 |
| 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 |
| 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
| 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 |
| 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
| 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | 0.00 | 30 |
| 7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100.00 | NULL | 20 |
| 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | NULL | 30 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
| 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 |
+-------+--------+-----------+------+------------+---------+---------+--------+
14 rows in set (0.00 sec)
mysql> select * from salgrade;
+-------+-------+-------+
| GRADE | LOSAL | HISAL |
+-------+-------+-------+
| 1 | 700 | 1200 |
| 2 | 1201 | 1400 |
| 3 | 1401 | 2000 |
| 4 | 2001 | 3000 |
| 5 | 3001 | 9999 |
+-------+-------+-------+
5 rows in set (0.01 sec)
mysql> select e.ename,e.sal,s.grade from emp e join salgrade s on e.sal between s.losal and s.hisal;//条件不是一个等量联系,称为非等值联接。
+--------+---------+-------+
| ename | sal | grade |
+--------+---------+-------+
| SMITH | 800.00 | 1 |
| ALLEN | 1600.00 | 3 |
| WARD | 1250.00 | 2 |
| JONES | 2975.00 | 4 |
| MARTIN | 1250.00 | 2 |
| BLAKE | 2850.00 | 4 |
| CLARK | 2450.00 | 4 |
| SCOTT | 3000.00 | 4 |
| KING | 5000.00 | 5 |
| TURNER | 1500.00 | 3 |
| ADAMS | 1100.00 | 1 |
| JAMES | 950.00 | 1 |
| FORD | 3000.00 | 4 |
| MILLER | 1300.00 | 2 |
+--------+---------+-------+
3.自联接
事例:查阿职工的上级领导,要求显现职工名和对应的领导名?
mysql> select empno,ename,mgr from emp;
+-------+--------+------+
| empno | ename | mgr |
+-------+--------+------+
| 7369 | SMITH | 7902 |
| 7499 | ALLEN | 7698 |
| 7521 | WARD | 7698 |
| 7566 | JONES | 7839 |
| 7654 | MARTIN | 7698 |
| 7698 | BLAKE | 7839 |
| 7782 | CLARK | 7839 |
| 7788 | SCOTT | 7566 |
| 7839 | KING | NULL |
| 7844 | TURNER | 7698 |
| 7876 | ADAMS | 7788 |
| 7900 | JAMES | 7698 |
| 7902 | FORD | 7566 |
| 7934 | MILLER | 7782 |
+-------+--------+------+
技巧:一张表看成两张表。
emp a职工表
+-------+--------+------+
| empno | ename | mgr |
+-------+--------+------+
| 7369 | SMITH | 7902 |
| 7499 | ALLEN | 7698 |
| 7521 | WARD | 7698 |
| 7566 | JONES | 7839 |
| 7654 | MARTIN | 7698 |
| 7698 | BLAKE | 7839 |
| 7782 | CLARK | 7839 |
| 7788 | SCOTT | 7566 |
| 7839 | KING | NULL |
| 7844 | TURNER | 7698 |
| 7876 | ADAMS | 7788 |
| 7900 | JAMES | 7698 |
| 7902 | FORD | 7566 |
| 7934 | MILLER | 7782 |
+-------+--------+------+
emp b领导表
+-------+--------+------+
| empno | ename | mgr |
+-------+--------+------+
| 7369 | SMITH | 7902 |
| 7499 | ALLEN | 7698 |
| 7521 | WARD | 7698 |
| 7566 | JONES | 7839 |
| 7654 | MARTIN | 7698 |
| 7698 | BLAKE | 7839 |
| 7782 | CLARK | 7839 |
| 7788 | SCOTT | 7566 |
| 7839 | KING | NULL |
| 7844 | TURNER | 7698 |
| 7876 | ADAMS | 7788 |
| 7900 | JAMES | 7698 |
| 7902 | FORD | 7566 |
| 7934 | MILLER | 7782 |
+-------+--------+------+
mysql> select a.ename as '职工名',b.ename as '领导名' from emp a join emp b on a.mgr = b.empno;//职工的领导编号=领导的职工编号
+--------+--------+
| 职工名 | 领导名 |
+--------+--------+
| SMITH | FORD |
| ALLEN | BLAKE |
| WARD | BLAKE |
| JONES | KING |
| MARTIN | BLAKE |
| BLAKE | KING |
| CLARK | KING |
| SCOTT | JONES |
| TURNER | BLAKE |
| ADAMS | SCOTT |
| JAMES | BLAKE |
| FORD | JONES |
| MILLER | CLARK |
+--------+--------+
13 rows in set (0.00 sec)
13条记载,没有KING。《内联接》
以上便是内联接中的:自联接,技巧:一张表看做两张表。
5.外联接(右外联接)
mysql> select e.ename,d.dname from emp e right join dept d on e.deptno = d.deptno;
+--------+------------+
| ename | dname |
+--------+------------+
| CLARK | ACCOUNTING |
| KING | ACCOUNTING |
| MILLER | ACCOUNTING |
| SMITH | RESEARCH |
| JONES | RESEARCH |
| SCOTT | RESEARCH |
| ADAMS | RESEARCH |
| FORD | RESEARCH |
| ALLEN | SALES |
| WARD | SALES |
| MARTIN | SALES |
| BLAKE | SALES |
| TURNER | SALES |
| JAMES | SALES |
| NULL | OPERATIONS |
+--------+------------+
15 rows in set (0.00 sec)
right代表什么:表明将join关键字右边的这张表看成主表,首要是为了将这张表的数据悉数查询出来,梢带着关联查询左面的表。
在外联接傍边,两张表联接,发生了主次联系。
左外联接
mysql> select e.ename,d.dname from emp e left join dept d on e.deptno = d.deptno;
带有right的是右外联接,又叫做右联接
带有1eft的是左外联接,又叫做左联接
任何一个右联接都有左联接的写法
任何一个左联接都有右联接的写法
相同的out也能够省掉
考虑:外联接的查询成果条数必定是>=内联接的查询成果条数?
正确。
事例:查询每个职工的上级领导,要求显现一切职工的名字和领导名?
mysql> select b.ename,a.ename from emp a right join emp b on a.empno = b.mgr;
+--------+-------+
| ename | ename |
+--------+-------+
| SMITH | FORD |
| ALLEN | BLAKE |
| WARD | BLAKE |
| JONES | KING |
| MARTIN | BLAKE |
| BLAKE | KING |
| CLARK | KING |
| SCOTT | JONES |
| KING | NULL |
| TURNER | BLAKE |
| ADAMS | SCOTT |
| JAMES | BLAKE |
| FORD | JONES |
| MILLER | CLARK |
+--------+-------+
select
...
from
a
join
b
on
a和b的联接条件
join
c
on
a和c的联接条件
right join
d
on a和d的联接条件
where
...
一条SQL中内联接和外联接能够混合。都能够呈现!
三表查询
事例
事例:找出每个职工的部分称号以及薪酬等级,
要求显现职工名、部分名、薪资、蕲资等级?
select
e.ename,e.sal,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;
12.子查询
什么是子查询?
select句子中嵌套select句子,被嵌套的select句子称为子查询。
子查询都能够呈现在哪里呢
select
(select)
from
(select)
where
(select)
- where 子句中的子查询
事例:找出比最低薪酬高的职工名字和薪酬?
完结思路:
榜首步:查询最低薪酬是多少
select min(sal) from emp;
+----------+
| min(sal) |
+----------+
| 800.00 |
+----------+
第二步:找出>800的
select ename,sal from emp where sal > 800;
第三步:兼并
select ename,sal from emp where sal > (select min(sal) from emp);
+--------+---------+
| ename | sal |
+--------+---------+
| ALLEN | 1600.00 |
| WARD | 1250.00 |
| JONES | 2975.00 |
| MARTIN | 1250.00 |
| BLAKE | 2850.00 |
| CLARK | 2450.00 |
| SCOTT | 3000.00 |
| KING | 5000.00 |
| TURNER | 1500.00 |
| ADAMS | 1100.00 |
| JAMES | 950.00 |
| FORD | 3000.00 |
| MILLER | 1300.00 |
+--------+---------+
- from子句中的子查询
留意:from后边的子查询,能够将子查询的查询成果作为一张暂时表。(技巧)
事例:找出每个岗位的均匀薪酬的薪资等级。
榜首步:找出每个岗位的均匀薪酬(依照岗位分组求均匀值)
select job,avg(sal) from emp group by job;
+-----------+-------------+
| job | avgsal |
+-----------+-------------+
| ANALYST | 3000.000000 |
| CLERK | 1037.500000 |
| MANAGER | 2758.333333 |
| PRESIDENT | 5000.000000 |
| SALESMAN | 1400.000000 |
+-----------+-------------+t表
第二步:把以上的查询成果就作为一张实在存在的表t。
mysql> select * from salgrade; s表
+-------+-------+-------+
| GRADE | LOSAL | HISAL |
+-------+-------+-------+
| 1 | 700 | 1200 |
| 2 | 1201 | 1400 |
| 3 | 1401 | 2000 |
| 4 | 2001 | 3000 |
| 5 | 3001 | 9999 |
+-------+-------+-------+
t表和s表进行表联接,条件:t表avg(sal) between s.losal and s.hisal;
select
t.*, s.grade
from
(select job,avg(sal) as avgsal from emp group by job) t
join
salgrade s
on
t.avgsal between s.losal and s.hisal;//假如不给avg(sal)起别号,会以为他是一个函数就会报错,实践上这儿便是要的上面暂时表的列名
+-----------+-------------+-------+
| job | avgsal | grade |
+-----------+-------------+-------+
| CLERK | 1037.500000 | 1 |
| SALESMAN | 1400.000000 | 2 |
| ANALYST | 3000.000000 | 4 |
| MANAGER | 2758.333333 | 4 |
| PRESIDENT | 5000.000000 | 5 |
+-----------+-------------+-------+
- select后边呈现的子查询(这个内容不需求把握,了解即可!!!)
事例:找出每个职工的部分称号,要求显现职工名,部分名?
select
e.ename,e.deptno,(select d.dname from dept d where e.deptno = d.deptno) as dname
from
emp e;
+--------+--------+------------+
| ename | deptno | dname |
+--------+--------+------------+
| SMITH | 20 | RESEARCH |
| ALLEN | 30 | SALES |
| WARD | 30 | SALES |
| JONES | 20 | RESEARCH |
| MARTIN | 30 | SALES |
| BLAKE | 30 | SALES |
| CLARK | 10 | ACCOUNTING |
| SCOTT | 20 | RESEARCH |
| KING | 10 | ACCOUNTING |
| TURNER | 30 | SALES |
| ADAMS | 20 | RESEARCH |
| JAMES | 30 | SALES |
| FORD | 20 | RESEARCH |
| MILLER | 10 | ACCOUNTING |
+--------+--------+------------+
//过错:ERROR 1242 (21000): Subquery returns more than 1 row
select
e.ename,e.deptno,(select dname from dept) as dname
from
emp e;
留意:关于select后边的子查询来说,这个子查询只能一次回来1条成果,
多于1条,就报错了。!
13.unit兼并查询成果集
事例:查询作业岗位是MANAGER和SALESMAN的职工?
select ename,job from emp where job = 'MANAGER' or job = 'SALESMAN';
select ename,job from emp where job in('MANAGER','SALESMAN');
+--------+----------+
| ename | job |
+--------+----------+
| ALLEN | SALESMAN |
| WARD | SALESMAN |
| JONES | MANAGER |
| MARTIN | SALESMAN |
| BLAKE | MANAGER |
| CLARK | MANAGER |
| TURNER | SALESMAN |
+--------+----------+
select ename,job from emp where job = 'MANAGER'
union
select ename,job from emp where job = 'SALESMAN';
+--------+----------+
| ename | job |
+--------+----------+
| JONES | MANAGER |
| BLAKE | MANAGER |
| CLARK | MANAGER |
| ALLEN | SALESMAN |
| WARD | SALESMAN |
| MARTIN | SALESMAN |
| TURNER | SALESMAN |
+--------+----------+
union的功率要高一些。关于表联接来说,每联接一次新表,
则匹配的次数满意笛卡尔积,成倍的翻。。。
可是union能够削减匹配的次数。在削减匹配次数的状况下,
还能够完结两个成果集的拼接。
a 联接 b 联接 c
a 10条记载
b 10条记载
c 10条记载
匹配次数是:1000
a 联接 b一个成果:10 * 10 --> 100次
a 联接 c一个成果:10 * 10 --> 100次
运用union的话是:100次 + 100次 = 200次。(union把乘法变成了加法运算)
union在运用的时分有留意事项吗?
//过错的:union在进行成果集兼并的时分,要求两个成果集的列数相同。
select ename,job from emp where job = 'MANAGER'
union
select ename from emp where job = 'SALESMAN';
// MYSQL能够,oracle语法严厉 ,不能够,报错。要求:成果集兼并时列和列的数据类型也要一起。
select ename,job from emp where job = 'MANAGER'
union
select ename,sal from emp where job = 'SALESMAN';
+--------+---------+
| ename | job |
+--------+---------+
| JONES | MANAGER |
| BLAKE | MANAGER |
| CLARK | MANAGER |
| ALLEN | 1600 |
| WARD | 1250 |
| MARTIN | 1250 |
| TURNER | 1500 |
+--------+---------+
14.limit(十分重要)
-
limit效果:将查询成果集的一部分取出来。一般运用在分页查询傍边。
-
百度默许:一页显现10条记载。
-
分页的效果是为了提高用户的体验,由于一次悉数都查出来,用户体验差。
-
能够一页一页翻页看。
limit怎样用呢?(不加括号)
完好用法:limit startIndex, length
startIndex是开端下标,length是长度。
开端下标从0开端。
缺省用法:limit 5; 这是取前5.
依照薪资降序,取出排名在前5名的职工?
select
ename,sal
from
emp
order by
sal desc
limit 5; //取前5
select
ename,sal
from
emp
order by
sal desc
limit 0,5;
+-------+---------+
| ename | sal |
+-------+---------+
| KING | 5000.00 |
| SCOTT | 3000.00 |
| FORD | 3000.00 |
| JONES | 2975.00 |
| BLAKE | 2850.00 |
+-------+---------+
留意:mysql傍边limit在order by之后履行!!!!!!
5.4、取出薪酬排名在[3-5]名的职工?
select
ename,sal
from
emp
order by
sal desc
limit
2, 3;
2表明开端方位从下标2开端,便是第三条记载。
3表明长度。
+-------+---------+
| ename | sal |
+-------+---------+
| FORD | 3000.00 |
| JONES | 2975.00 |
| BLAKE | 2850.00 |
+-------+---------+
取出薪酬排名在[5-9]名的职工?
select
ename,sal
from
emp
order by
sal desc
limit
4, 5;
+--------+---------+
| ename | sal |
+--------+---------+
| BLAKE | 2850.00 |
| CLARK | 2450.00 |
| ALLEN | 1600.00 |
| TURNER | 1500.00 |
| MILLER | 1300.00 |
+--------+---------+
分页
每页显现3条记载
第1页:limit 0,3 [0 1 2]
第2页:limit 3,3 [3 4 5]
第3页:limit 6,3 [6 7 8]
第4页:limit 9,3 [9 10 11]
每页显现pageSize条记载
第pageNo页:limit (pageNo - 1) * pageSize , pageSize
public static void main(String[] args){
// 用户提交过来一个页码,以及每页显现的记载条数
int pageNo = 5; //第5页
int pageSize = 10; //每页显现10条
int startIndex = (pageNo - 1) * pageSize;
String sql = "select ...limit " + startIndex + ", " + pageSize;
}
记公式:
limit (pageNo-1)*pageSize , pageSize
关于SQL句子的大总结:
select
...
from
...
where
...
group by
...
having
...
order by
...
limit
...
履行次序?
1.from
2.where
3.group by
4.having
5.select
6.order by
7.limit..
15.表的创立
建表的语法格局:(建表归于DDL句子,DDL包含:create drop alter)
create table 表名(字段名1 数据类型, 字段名2 数据类型, 字段名3 数据类型);
create table 表名(
字段名1 数据类型,
字段名2 数据类型,
字段名3 数据类型
);
表名:主张以t_ 或许 tbl_开端,可读性强。见名知意。
字段名:见名知意。
表名和字段名都归于标识符。
关于mysql中的数据类型?
许多数据类型,咱们只需求把握一些常见的数据类型即可。
varchar(最长255)
可变长度的字符串
比较智能,节约空间。
会根据实践的数据长度动态分配空间。
长处:节约空间
缺陷:需求动态分配空间,速度慢。
char(最长255)
定长字符串
不论实践的数据长度是多少。
分配固定长度的空间去存储数据。
运用不恰当的时分,或许会导致空间的糟蹋。
长处:不需求动态分配空间,速度快。
缺陷:运用不当或许会导致空间的糟蹋。
varchar和char咱们应该怎样挑选?
性别字段你选什么?由于性别是固定长度的字符串,所以挑选char。
名字字段你选什么?每一个人的名字长度不同,所以挑选varchar。
int(最长11)
数字中的整数型。等同于java的int。
bigint
数字中的长整型。等同于java中的long。
float
单精度浮点型数据
double
双精度浮点型数据
date
短日期类型
datetime
长日期类型
clob
字符大目标
最多能够存储4G的字符串。
比方:存储一篇文章,存储一个阐明。
超过255个字符的都要选用CLOB字符大目标来存储。
Character Large OBject:CLOB
blob
二进制大目标
Binary Large OBject
专门用来存储图片、声音、视频等流媒体数据。
往BLOB类型的字段上刺进数据的时分,例如刺进一个图片、视频等,
你需求运用IO流才行。
t_movie 电影表(专门存储电影信息的
编号 名字 故事情节 上映日期 时长 海报 类型
no(bigint) name(varchar) history(clob) playtime(date) time(double) image(blob) type(char)
------------------------------------------------------------------------------------------------------------------
10000 哪吒 2019-10-11 2.5 .... '1'
10001 林正英之娘娘 ........... 2019-11-11 1.5 .... '2'
....
创立一个学生表?
学号、名字、年龄、性别、邮箱地址
create table t_student(
no int,
name varchar(32),
sex char(1),
age int(3),
email varchar(255)
);
删去表:
drop table t_student; // 当这张表不存在的时分会报错!
// 假如这张表存在的话,删去
drop table if exists t_student;
16.刺进数据insert (DML)
语法格局:
insert into 表名(字段名1,字段名2,字段名3...) values(值1,值2,值3);
留意:字段名和值要一一对应。什么是一一对应?
数量要对应。数据类型要对应。
留意:insert句子但但凡履行成功了,那么必然会多一条记载。没有给其它字段指定值的话,默许值是NULL。
insert刺进多条记载
一次能够刺进多条记载:
insert into t_user(id,name,birth,create_time) values
(1,'zs','1980-10-11',now()),
(2,'lisi','1981-10-11',now()),
(3,'wangwu','1982-10-11',now());
语法:insert into t_user(字段名1,字段名2) values(),(),(),();
17.指定默许值
mysql> desc t_student;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| no | varchar(20) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| sex | char(1) | YES | | NULL | |
| age | int(11) | YES | | NULL | |
| email | varchar(25) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
drop table if exists t_student;
create table t_student(
no int,
name varchar(32),
sex char(1) default 'm',
age int(3),
email varchar(255)
);
mysql> desc t_student;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| no | int(11) | YES | | NULL | |
| name | varchar(32) | YES | | NULL | |
| sex | char(1) | YES | | m | |
| age | int(3) | YES | | NULL | |
| email | varchar(255) | YES | | NULL | |
+-------+--------------+------+-----+---------+-------+
insert句子中的“字段名”能够省掉吗?能够
insert into t_student values(2); //过错的
// 留意:前面的字段名省掉的话,等于都写上了!所以值也要都写上!
insert into t_student values(2, 'lisi', 'f', 20, 'lisi@123.com');
mysql> select * from t_student;
+------+------+------+------+--------------+
| no | name | sex | age | email |
+------+------+------+------+--------------+
| 2 | lisi | f | 20 | lisi@123.com |
+------+------+------+------+--------------+
18.格局化format
数字格局化:format
ysql> select ename,sal from emp;
+--------+---------+
| ename | sal |
+--------+---------+
| SMITH | 800.00 |
| ALLEN | 1600.00 |
| WARD | 1250.00 |
| JONES | 2975.00 |
| MARTIN | 1250.00 |
| BLAKE | 2850.00 |
| CLARK | 2450.00 |
| SCOTT | 3000.00 |
| KING | 5000.00 |
| TURNER | 1500.00 |
| ADAMS | 1100.00 |
| JAMES | 950.00 |
| FORD | 3000.00 |
| MILLER | 1300.00 |
+--------+---------+
mysql> select ename,format(sal,'$999,999') from emp;
+--------+------------------------+
| ename | format(sal,'$999,999') |
+--------+------------------------+
| SMITH | 800 |
| ALLEN | 1,600 |
| WARD | 1,250 |
| JONES | 2,975 |
| MARTIN | 1,250 |
| BLAKE | 2,850 |
| CLARK | 2,450 |
| SCOTT | 3,000 |
| KING | 5,000 |
| TURNER | 1,500 |
| ADAMS | 1,100 |
| JAMES | 950 |
| FORD | 3,000 |
| MILLER | 1,300 |
+--------+------------------------+
str_to_date:将字符串varchar类型转换成date类型
date_format:将date类型转换成具有必定格局的varchar字符串类型。
drop table if exists t_user;
create table t_user(
id int,
name varchar(32),
birth date // 生日也能够运用date日期类型
);
create table t_user(
id int,
name varchar(32),
birth char(10) // 生日能够运用字符串,没问题。
);
生日:1990-10-11 (10个字符)
留意:数据库中的有一条命名标准:
一切的标识符都是悉数小写,单词和单词之间运用下划线进行联接。
mysql> DESC T_USER;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(32) | YES | | NULL | |
| birth | date | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
刺进数据
刺进数据?
insert into t_user(id,name,birth) values(1, 'zhangsan', '01-10-1990'); // 1990年10月1日
出问题了:原因是类型不匹配。数据库birth是date类型,这儿给了一个字符串varchar。
怎样办?能够运用str_to_date函数进行类型转换。
str_to_date函数能够将字符串转换成日期类型date?
语法格局:
str_to_date('字符串日期', '日期格局')
mysql的日期格局:
%Y 年
%m 月
%d 日
%h 时
%i 分
%s 秒
insert into t_user(id,name,birth) values(1, 'zhangsan', str_to_date('01-10-1990','%d-%m-%Y'));
str_to_date函数能够把字符串varchar转换成日期date类型数据,
一般运用在刺进insert方面,由于刺进的时分需求一个日期类型的数据,
需求经过该函数将字符串转换成date。
好消息?
假如你供给的日期字符串是这个格局,str_to_date函数就不需求了!!!
%Y-%m-%d
insert into t_user(id,name,birth) values(2, 'lisi', '1990-10-01');
查询的时分能够以某个特定的日期格局展现吗?
date_format
这个函数能够将日期类型转换成特定格局的字符串。
mysql> select id,name,date_format(birth,'%Y/%m/%d') from t_user
-> ;
+-------+-------+-------------------------------+
| id | name | date_format(birth,'%Y/%m/%d') |
+-------+-------+-------------------------------+
| 11111 | smith | 2003/06/01 |
+-------+-------+-------------------------------+
date_format函数怎样用?
date_format(日期类型数据, '日期格局')
这个函数一般运用在查询日期方面。设置展现的日期格局。
mysql> select id,name,birth from t_user;
+-------+-------+------------+
| id | name | birth |
+-------+-------+------------+
| 11111 | smith | 2003-06-01 |
+-------+-------+------------+
以上的SQL句子实践上是进行了默许的日期格局化,
主动将数据库中的date类型转换成varchar类型。
而且选用的格局是mysql默许的日期格局:'%Y-%m-%d'
select id,name,date_format(birth,'%Y/%m/%d') as birth from t_user;
java中的日期格局?
yyyy-MM-dd HH:mm:ss SSS
date和datetime两个类型的区别?
date是短日期:只包含年月日信息。
datetime是长日期:包含年月日时分秒信息。
drop table if exists t_user;
create table t_user(
id int,
name varchar(32),
birth date,
create_time datetime
);
id是整数
name是字符串
birth是短日期
create_time是这条记载的创立时刻:长日期类型
mysql短日期默许格局:%Y-%m-%d
mysql长日期默许格局:%Y-%m-%d %h:%i:%s
insert into t_user(id,name,birth,create_time) values(1,'zhangsan','1990-10-01','2020-03-18 15:49:50');
在mysql傍边怎样获取系统当时时刻?
now() 函数,而且获取的时刻带有:时分秒信息!!!!是datetime类型的。
insert into t_user(id,name,birth,create_time) values(2,'lisi','1991-10-01',now());
19.修正update(DML)
语法格局:
update 表名 set 字段名1=值1,字段名2=值2,字段名3=值3... where 条件;
留意:没有条件束缚会导致一切数据悉数更新。
update t_user set name = 'jack', birth = '2000-10-11' where id = 2;
update t_user set name = 'jack', birth = '2000-10-11', create_time = now() where id = 2;
更新一切?
update t_user set name = 'abc';
20.删去数据 delete (DML)
语法格局?
delete from 表名 where 条件;
留意:没有条件,整张表的数据会悉数删去!
delete from t_user where id = 2;
insert into t_user(id) values(2);
delete from t_user; // 删去一切!
21.快速创立表?【了解内容】
mysql> create table emp2 as select * from emp;
原理:
将一个查询成果作为一张表新建!!!!!
这个能够完结表的快速仿制!!!!
表创立出来,一起表中的数据也存在了!!!
查询一部分当作一个表新建
create table mytable as select empno,ename from emp where job = 'MANAGER';
将查询成果刺进到一张表傍边?insert相关的!!!
mysql> create table dept_bak as select * from dept;
Query OK, 4 rows affected (0.01 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> select * from dept_bak;
+--------+------------+----------+
| DEPTNO | DNAME | LOC |
+--------+------------+----------+
| 10 | ACCOUNTING | NEW YORK |
| 20 | RESEARCH | DALLAS |
| 30 | SALES | CHICAGO |
| 40 | OPERATIONS | BOSTON |
+--------+------------+----------+
mysql> insert into dept_bak select * from dept;//很少用
Query OK, 4 rows affected (0.01 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> select * from dept_bak;
+--------+------------+----------+
| DEPTNO | DNAME | LOC |
+--------+------------+----------+
| 10 | ACCOUNTING | NEW YORK |
| 20 | RESEARCH | DALLAS |
| 30 | SALES | CHICAGO |
| 40 | OPERATIONS | BOSTON |
| 10 | ACCOUNTING | NEW YORK |
| 20 | RESEARCH | DALLAS |
| 30 | SALES | CHICAGO |
| 40 | OPERATIONS | BOSTON |
+--------+------------+----------+
22.快速删去表中的数据?【truncate比较重要,有必要把握】
truncate不能删去单条
//删去dept_bak表中的数据
delete from dept_bak; //这种删去数据的方法比较慢。
mysql> select * from dept_bak;
Empty set (0.00 sec)
delete句子删去数据的原理?(delete归于DML句子!!!)
表中的数据被删去了,可是这个数据在硬盘上的实在存储空间不会被释放!!!
这种删去缺陷是:删去功率比较低。
这种删去长处是:支撑回滚,后悔了能够再康复数据!!!
truncate句子删去数据的原理?
这种删去功率比较高,表被一次切断,物理删去。
这种删去缺陷:不支撑回滚。
这种删去长处:快速。
用法:truncate table dept_bak; (这种操作归于DDL操作。)
大表十分大,上亿条记载????
删去的时分,运用delete,也许需求履行1个小时才干删去完!功率较低。
能够挑选运用truncate删去表中的数据。只需求不到1秒钟的时刻就删去完毕。功率较高。
可是运用truncate之前,有必要细心问询客户是否真的要删去,并正告删去之后不行康复!
truncate是删去表中的数据,表还在!
删去表操作?
drop table 表名; // 这不是删去表中的数据,这是把表删去。
23.对表结构的增修正?
什么是对表结构的修正?
增加一个字段,删去一个字段,修正一个字段!!!
对表结构的修正需求运用:alter
归于DDL句子
DDL包含:create drop alter
榜首:在实践的开发中,需求一旦确定之后,表一旦规划好之后,很少的
进行表结构的修正。由于开发进行中的时分,修正表结构,本钱比较高。
修正表的结构,对应的java代码就需求进行大量的修正。本钱是比较高的。
这个责任应该由规划人员来承当!
第二:由于修正表结构的操作很少,所以咱们不需求把握,假如有一天
真的要修正表结构,你能够运用东西!!!!
修正表结构的操作是不需求写到java程序中的。实践上也不是java程序员的范畴。
24.束缚(十分重要,五颗星)
1. 什么是束缚?
束缚对应的英语单词:constraint
在创立表的时分,咱们能够给表中的字段加上一些束缚,来确保这个表中数据的
完好性、有用性!!!
束缚的效果便是为了确保:表中的数据有用!!
2. 束缚包含哪些?
非空束缚:not null
仅有性束缚: unique
主键束缚: primary key (简称PK)
外键束缚:foreign key(简称FK)
检查束缚:check(mysql不支撑,oracle支撑)
咱们这儿要点学习四个束缚:
not null
unique
primary key
foreign key
1. 非空束缚:not null
非空束缚not null束缚的字段不能为NULL。
drop table if exists t_vip;
create table t_vip(
id int,
name varchar(255) not null // not null只要列级束缚,没有表级束缚!
);
insert into t_vip(id,name) values(1,'zhangsan');
insert into t_vip(id,name) values(2,'lisi');
insert into t_vip(id) values(3);
ERROR 1364 (HY000): Field 'name' doesn't have a default value
小插曲:
xxxx.sql这种文件被称为sql脚本文件。
sql脚本文件中编写了大量的sql句子。
咱们履行sql脚本文件的时分,该文件中一切的sql句子会悉数履行!
批量的履行SQL句子,能够运用sql脚本文件。
在mysql傍边怎样履行sql脚本呢?
mysql> source D:\course\03-MySQL\document\vip.sql
你在实践的作业中,榜首天到了公司,项目经理会给你一个xxx.sql文件,
你履行这个脚本文件,你电脑上的数据库数据就有了!
2.仅有性束缚: unique
仅有性束缚unique束缚的字段不能重复,可是能够为NULL。
drop table if exists t_vip;
create table t_vip(
id int,
name varchar(255) unique,
email varchar(255)
);
insert into t_vip(id,name,email) values(1,'zhangsan','zhangsan@123.com');
insert into t_vip(id,name,email) values(2,'lisi','lisi@123.com');
insert into t_vip(id,name,email) values(3,'wangwu','wangwu@123.com');
select * from t_vip;
insert into t_vip(id,name,email) values(4,'wangwu','wangwu@sina.com');
ERROR 1062 (23000): Duplicate entry 'wangwu' for key 'name'
insert into t_vip(id) values(4);
insert into t_vip(id) values(5);
+------+----------+------------------+
| id | name | email |
+------+----------+------------------+
| 1 | zhangsan | zhangsan@123.com |
| 2 | lisi | lisi@123.com |
| 3 | wangwu | wangwu@123.com |
| 4 | NULL | NULL |
| 5 | NULL | NULL |
+------+----------+------------------+
name字段虽然被unique束缚了,可是能够为NULL。
新需求:name和email两个字段联合起来具有仅有性!!!!
drop table if exists t_vip;
create table t_vip(
id int,
name varchar(255) unique, // 束缚直接增加到列后边的,叫做列级束缚。
email varchar(255) unique
);
这张表这样创立是不契合我以上“新需求”的。
这样创立表明:name具有仅有性,email具有仅有性。各自仅有。
以下这样的数据是契合我“新需求”的。
但假如选用以上方法创立表的话,肯定创立失利,由于'zhangsan'和'zhangsan'重复了。
insert into t_vip(id,name,email) values(1,'zhangsan','zhangsan@123.com');
insert into t_vip(id,name,email) values(2,'zhangsan','zhangsan@sina.com');
怎样创立这样的表,才干契合新需求呢?
drop table if exists t_vip;
create table t_vip(
id int,
name varchar(255),
email varchar(255),
unique(name,email) // 束缚没有增加在列的后边,这种束缚被称为表级束缚。
);
insert into t_vip(id,name,email) values(1,'zhangsan','zhangsan@123.com');
insert into t_vip(id,name,email) values(2,'zhangsan','zhangsan@sina.com');
select * from t_vip;
name和email两个字段联合起来仅有!!!
insert into t_vip(id,name,email) values(3,'zhangsan','zhangsan@sina.com');
ERROR 1062 (23000): Duplicate entry 'zhangsan-zhangsan@sina.com' for key 'name'
什么时分运用表级束缚呢?
需求给多个字段联合起来增加某一个束缚的时分,需求运用表级束缚。
unique 和not null能够联合吗?
drop table if exists t_vip;
create table t_vip(
id int,
name varchar(255) not null unique
);
mysql> desc t_vip;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(255) | NO | PRI | NULL | |
+-------+--------------+------+-----+---------+-------+
在mysql傍边,假如一个字段一起被not null和unique束缚的话,
该字段主动变成主键字段。(留意:oracle中不一样!)
insert into t_vip(id,name) values(1,'zhangsan');
insert into t_vip(id,name) values(2,'zhangsan'); //过错了:name不能重复
insert into t_vip(id) values(2); //过错了:name不能为NULL。
3. 主键束缚(primary key,简称PK)十分重要五颗星
主键束缚的相关术语?
主键束缚:便是一种束缚。
主键字段:该字段上增加了主键束缚,这样的字段叫做:主键字段
主键值:主键字段中的每一个值都叫做:主键值。
什么是主键?有啥用?
主键值是每一行记载的仅有标识。
主键值是每一行记载的身份证号!!!
记住:任何一张表都应该有主键,没有主键,表无效!!
主键的特征:not null + unique(主键值不能是NULL,一起也不能重复!)
怎样给一张表增加主键束缚呢?
drop table if exists t_vip;
// 1个字段做主键,叫做:单一主键
create table t_vip(
id int primary key, //列级束缚
name varchar(255)
);
insert into t_vip(id,name) values(1,'zhangsan');
insert into t_vip(id,name) values(2,'lisi');
//过错:不能重复
insert into t_vip(id,name) values(2,'wangwu');
ERROR 1062 (23000): Duplicate entry '2' for key 'PRIMARY'
//过错:不能为NULL
insert into t_vip(name) values('zhaoliu');
ERROR 1364 (HY000): Field 'id' doesn't have a default value
能够这样增加主键吗,运用表级束缚?
drop table if exists t_vip;
create table t_vip(
id int,
name varchar(255),
primary key(id) // 表级束缚
);
insert into t_vip(id,name) values(1,'zhangsan');
//过错
insert into t_vip(id,name) values(1,'lisi');
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
表级束缚首要是给多个字段联合起来增加束缚?
drop table if exists t_vip;
// id和name联合起来做主键:复合主键!!!!
create table t_vip(
id int,
name varchar(255),
email varchar(255),
primary key(id,name)
);
insert into t_vip(id,name,email) values(1,'zhangsan','zhangsan@123.com');
insert into t_vip(id,name,email) values(1,'lisi','lisi@123.com');
//过错:不能重复
insert into t_vip(id,name,email) values(1,'lisi','lisi@123.com');
ERROR 1062 (23000): Duplicate entry '1-lisi' for key 'PRIMARY'
在实践开发中不主张运用:复合主键。主张运用单一主键!
由于主键值存在的意义便是这行记载的身份证号,只需意义达到即可,单一主键能够做到。
复合主键比较杂乱,不主张运用!!!
一个表中主键束缚能加两个吗?
drop table if exists t_vip;
create table t_vip(
id int primary key,
name varchar(255) primary key
);
ERROR 1068 (42000): Multiple primary key defined
定论:一张表,主键束缚只能增加1个。(主键只能有1个。)
主键值主张运用:
int
bigint
char
等类型。
不主张运用:varchar来做主键。主键值一般都是数字,一般都是定长的!
主键除了:单一主键和复合主键之外,还能够这样进行分类?
天然主键:主键值是一个天然数,和业务没联系。
业务主键:主键值和业务严密关联,例如拿银行卡账号做主键值。这便是业务主键!
在实践开发中运用业务主键多,仍是运用天然主键多一些?
天然主键运用比较多,由于主键只需做到不重复就行,不需求有意义。
业务主键不好,由于主键一旦和业务挂钩,那么当业务发生变动的时分,
或许会影响到主键值,所以业务主键不主张运用。尽量运用天然主键。
在mysql傍边,有一种机制,能够协助咱们主动保护一个主键值?
drop table if exists t_vip;
create table t_vip(
id int primary key auto_increment, //auto_increment表明自增,从1开端,以1递加!
name varchar(255)
);
insert into t_vip(name) values('zhangsan');
insert into t_vip(name) values('zhangsan');
insert into t_vip(name) values('zhangsan');
insert into t_vip(name) values('zhangsan');
insert into t_vip(name) values('zhangsan');
insert into t_vip(name) values('zhangsan');
insert into t_vip(name) values('zhangsan');
insert into t_vip(name) values('zhangsan');
select * from t_vip;
+----+----------+
| id | name |
+----+----------+
| 1 | zhangsan |
| 2 | zhangsan |
| 3 | zhangsan |
| 4 | zhangsan |
| 5 | zhangsan |
| 6 | zhangsan |
| 7 | zhangsan |
| 8 | zhangsan |
+----+----------+
- 外键束缚(foreign key,简称FK)
外键束缚涉及到的相关术语:
外键束缚:一种束缚(foreign key)
外键字段:该字段上增加了外键束缚
外键值:外键字段傍边的每一个值。
业务背景:
请规划数据库表,来描绘“班级和学生”的信息?
榜首种计划:班级和学生存储在一张表中???
t_student
no(pk) name classno classname
----------------------------------------------------------------------------------
1 jack 100 北京市大兴区亦庄镇第二中学高三1班
2 lucy 100 北京市大兴区亦庄镇第二中学高三1班
3 lilei 100 北京市大兴区亦庄镇第二中学高三1班
4 hanmeimei 100 北京市大兴区亦庄镇第二中学高三1班
5 zhangsan 101 北京市大兴区亦庄镇第二中学高三2班
6 lisi 101 北京市大兴区亦庄镇第二中学高三2班
7 wangwu 101 北京市大兴区亦庄镇第二中学高三2班
8 zhaoliu 101 北京市大兴区亦庄镇第二中学高三2班
剖析以上计划的缺陷:
数据冗余,空间糟蹋!!!!
这个规划是比较失利的!
第二种计划:班级一张表、学生一张表??
t_class 班级表
classno(pk) classname
------------------------------------------------------
100 北京市大兴区亦庄镇第二中学高三1班
101 北京市大兴区亦庄镇第二中学高三1班
t_student 学生表
no(pk) name cno(FK引证t_class这张表的classno)
----------------------------------------------------------------
1 jack 100
2 lucy 100
3 lilei 100
4 hanmeimei 100
5 zhangsan 101
6 lisi 101
7 wangwu 101
8 zhaoliu 101
当cno字段没有任何束缚的时分,或许会导致数据无效。或许呈现一个102,可是102班级不存在。
所以为了确保cno字段中的值都是100和101,需求给cno字段增加外键束缚。
那么:cno字段便是外键字段。cno字段中的每一个值都是外键值。
留意:
t_class是父表
t_student是子表
删去表的次序?
先删子,再删父。
创立表的次序?
先创立父,再创立子。
删去数据的次序?
先删子,再删父。
刺进数据的次序?
先刺进父,再刺进子。
考虑:子表中的外键引证的父表中的某个字段,被引证的这个字段有必要是主键吗?
不必定是主键,但至少具有unique束缚。
测试:外键能够为NULL吗?
外键值能够为NULL。
25.存储引擎(了解内容)
- 什么是存储引擎,有什么用呢?
- 存储引擎是MySQL中特有的一个术语,其它数据库中没有。(Oracle中有,可是不叫这个名字)
- 存储引擎这个名字高端大气上档次。
- 实践上存储引擎是一个表存储/安排数据的方法。
- 不同的存储引擎,表存储数据的方法不同。
- 怎样给表增加/指定“存储引擎”呢?
show create table t_student;
能够在建表的时分给表指定存储引擎。
CREATE TABLE `t_student` (
`no` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`cno` int(11) DEFAULT NULL,
PRIMARY KEY (`no`),
KEY `cno` (`cno`),
CONSTRAINT `t_student_ibfk_1` FOREIGN KEY (`cno`) REFERENCES `t_class` (`classno`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8
在建表的时分能够在终究小括号的")"的右边运用:
ENGINE来指定存储引擎。
CHARSET来指定这张表的字符编码方法。
定论:
mysql默许的存储引擎是:InnoDB
mysql默许的字符编码方法是:utf8
建表时指定存储引擎,以及字符编码方法。
create table t_product(
id int primary key,
name varchar(255)
)engine=InnoDB default charset=gbk;
- 怎样检查mysql支撑哪些存储引擎呢?
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.5.36 |
+-----------+
指令: show engines \G
*************************** 1. row ***************************
Engine: FEDERATED
Support: NO
Comment: Federated MySQL storage engine
Transactions: NULL
XA: NULL
Savepoints: NULL
*************************** 2. row ***************************
Engine: MRG_MYISAM
Support: YES
Comment: Collection of identical MyISAM tables
Transactions: NO
XA: NO
Savepoints: NO
*************************** 3. row ***************************
Engine: MyISAM
Support: YES
Comment: MyISAM storage engine
Transactions: NO
XA: NO
Savepoints: NO
*************************** 4. row ***************************
Engine: BLACKHOLE
Support: YES
Comment: /dev/null storage engine (anything you write to it disappears
Transactions: NO
XA: NO
Savepoints: NO
*************************** 5. row ***************************
Engine: CSV
Support: YES
Comment: CSV storage engine
Transactions: NO
XA: NO
Savepoints: NO
*************************** 6. row ***************************
Engine: MEMORY
Support: YES
Comment: Hash based, stored in memory, useful for temporary tables
Transactions: NO
XA: NO
Savepoints: NO
*************************** 7. row ***************************
Engine: ARCHIVE
Support: YES
Comment: Archive storage engine
Transactions: NO
XA: NO
Savepoints: NO
*************************** 8. row ***************************
Engine: InnoDB
Support: DEFAULT
Comment: Supports transactions, row-level locking, and foreign keys
Transactions: YES
XA: YES
Savepoints: YES
*************************** 9. row ***************************
Engine: PERFORMANCE_SCHEMA
Support: YES
Comment: Performance Schema
Transactions: NO
XA: NO
Savepoints: NO
mysql支撑九大存储引擎,当时5.5.36支撑8个。版别不同支撑状况不同。
- 关于mysql常用的存储引擎介绍一下
MyISAM存储引擎?
它办理的表具有以下特征:
运用三个文件表明每个表:
格局文件 — 存储表结构的界说(mytable.frm)
数据文件 — 存储表行的内容(mytable.MYD)
索引文件 — 存储表上索引(mytable.MYI):索引是一本书的目录,缩小扫描规模,提高查询功率的一种机制。
可被转换为压缩、只读表来节约空间
提示一下:
关于一张表来说,只需是主键,
或许加有unique束缚的字段上会主动创立索引。
MyISAM存储引擎特色:
可被转换为压缩、只读表来节约空间
这是这种存储引擎的优势!!!!
MyISAM不支撑业务机制,安全性低。
InnoDB存储引擎?
这是mysql默许的存储引擎,一起也是一个重量级的存储引擎。
InnoDB支撑业务,支撑数据库崩溃后主动康复机制。
InnoDB存储引擎最首要的特色是:十分安全。
它办理的表具有下列首要特征:
– 每个 InnoDB 表在数据库目录中以.frm 格局文件表明
– InnoDB 表空间 tablespace 被用于存储表的内容(表空间是一个逻辑称号。表空间存储数据+索引。)
– 供给一组用来记载业务性活动的日志文件
– 用 COMMIT(提交)、SAVEPOINT 及ROLLBACK(回滚)支撑业务处理
– 供给全 ACID 兼容
– 在 MySQL 服务器崩溃后供给主动康复
– 多版别(MVCC)和行级锁定
– 支撑外键及引证的完好性,包含级联删去和更新
InnoDB最大的特色便是支撑业务:
以确保数据的安全。功率不是很高,而且也不能压缩,不能转换为只读,
不能很好的节约存储空间。
MEMORY存储引擎?
运用 MEMORY 存储引擎的表,其数据存储在内存中,且行的长度固定,
这两个特色使得 MEMORY 存储引擎十分快。
MEMORY 存储引擎办理的表具有下列特征:
– 在数据库目录内,每个表均以.frm 格局的文件表明。
– 表数据及索引被存储在内存中。(意图便是快,查询快!)
– 表级锁机制。
– 不能包含 TEXT 或 BLOB 字段。
MEMORY 存储引擎以前被称为HEAP 引擎。
MEMORY引擎长处:查询功率是最高的。不需求和硬盘交互。
MEMORY引擎缺陷:不安全,关机之后数据消失。由于数据和索引都是在内存傍边。
26.业务
1. 什么是业务?
一个业务其实便是一个完好的业务逻辑。
是一个最小的作业单元。不行再分。
什么是一个完好的业务逻辑?
假定转账,从A账户向B账户中转账10000.
将A账户的钱减去10000(update句子)
将B账户的钱加上10000(update句子)
这便是一个完好的业务逻辑。
以上的操作是一个最小的作业单元,要么一起成功,要么一起失利,不行再分。
这两个update句子要求有必要一起成功或许一起失利,这样才干确保钱是正确的。
只要DML句子才会有业务这一说,其它句子和业务无关!!!
insert
delete
update
只要以上的三个句子和业务有联系,其它都没有联系。
由于 只要以上的三个句子是数据库表中数据进行增、删、改的。
只需你的操作一旦涉及到数据的增、删、改,那么就必定要考虑安全问题。
数据安全榜首位!!!
假定一切的业务,只需一条DML句子就能完结,还有必要存在业务机制吗?
正是由于做某件事的时分,需求多条DML句子一起联合起来才干完结,
所以需求业务的存在。假如任何一件杂乱的事儿都能一条DML句子搞定,
那么业务则没有存在的价值了。
究竟什么是业务呢?
说究竟,提到本质上,一个业务其实便是多条DML句子一起成功,或许一起失利!
业务:便是批量的DML句子一起成功,或许一起失利!
业务是怎样做到多条DML句子一起成功和一起失利的呢?
InnoDB存储引擎:供给一组用来记载业务性活动的日志文件
业务敞开了:
insert
insert
insert
delete
update
update
update
业务完毕了!
在业务的履行过程中,每一条DML的操作都会记载到“业务性活动的日志文件”中。
在业务的履行过程中,咱们能够提交业务,也能够回滚业务。
提交业务?
清空业务性活动的日志文件,将数据悉数彻底耐久化到数据库表中。
提交业务标志着,业务的完毕。而且是一种悉数成功的完毕。
回滚业务?
将之前一切的DML操作悉数吊销,而且清空业务性活动的日志文件
回滚业务标志着,业务的完毕。而且是一种悉数失利的完毕。
2.提交和回滚
怎样提交业务,怎样回滚业务?
提交业务:commit; 句子
回滚业务:rollback; 句子(回滚永久都是只能回滚到上一次的提交点!)
业务对应的英语单词是:transaction
测试一下,在mysql傍边默许的业务行为是怎样的?
mysql默许状况下是支撑主动提交业务的。(主动提交)
什么是主动提交?
每履行一条DML句子,则提交一次!
这种主动提交实践上是不契合咱们的开发习气,由于一个业务
一般是需求多条DML句子一起履行才干完结的,为了确保数据
的安全,有必要要求一起成功之后再提交,所以不能履行一条
就提交一条。
怎样将mysql的主动提交机制封闭掉呢?
先履行这个指令:start transaction;
演示业务:
---------------------------------回滚业务----------------------------------------
mysql> use bjpowernode;
Database changed
mysql> select * from dept_bak;
Empty set (0.00 sec)
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into dept_bak values(10,'abc', 'tj');
Query OK, 1 row affected (0.00 sec)
mysql> insert into dept_bak values(10,'abc', 'tj');
Query OK, 1 row affected (0.00 sec)
mysql> select * from dept_bak;
+--------+-------+------+
| DEPTNO | DNAME | LOC |
+--------+-------+------+
| 10 | abc | tj |
| 10 | abc | tj |
+--------+-------+------+
2 rows in set (0.00 sec)
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from dept_bak;
Empty set (0.00 sec)
---------------------------------提交业务----------------------------------------
mysql> use bjpowernode;
Database changed
mysql> select * from dept_bak;
+--------+-------+------+
| DEPTNO | DNAME | LOC |
+--------+-------+------+
| 10 | abc | bj |
+--------+-------+------+
1 row in set (0.00 sec)
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into dept_bak values(20,'abc
Query OK, 1 row affected (0.00 sec)
mysql> insert into dept_bak values(20,'abc
Query OK, 1 row affected (0.00 sec)
mysql> insert into dept_bak values(20,'abc
Query OK, 1 row affected (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from dept_bak;
+--------+-------+------+
| DEPTNO | DNAME | LOC |
+--------+-------+------+
| 10 | abc | bj |
| 20 | abc | tj |
| 20 | abc | tj |
| 20 | abc | tj |
+--------+-------+------+
4 rows in set (0.00 sec)
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from dept_bak;
+--------+-------+------+
| DEPTNO | DNAME | LOC |
+--------+-------+------+
| 10 | abc | bj |
| 20 | abc | tj |
| 20 | abc | tj |
| 20 | abc | tj |
+--------+-------+------+
4 rows in set (0.00 sec)
3.业务包含4个特性?
A:原子性
阐明业务是最小的作业单元。不行再分。
C:一起性
一切业务要求,在同一个业务傍边,一切操作有必要一起成功,或许一起失利,
以确保数据的一起性。
I:阻隔性
A业务和B业务之间具有必定的阻隔。
教室A和教室B之间有一道墙,这道墙便是阻隔性。
A业务在操作一张表的时分,另一个业务B也操作这张表会那样???
D:耐久性
业务终究完毕的一个保证。业务提交,就相当于将没有保存到硬盘上的数据
保存到硬盘上!
阻隔性
要点研究一下业务的阻隔性!!!
A教室和B教室中间有一道墙,这道墙能够很厚,也能够很薄。这便是业务的阻隔等级。
这道墙越厚,表明阻隔等级就越高。
业务和业务之间的阻隔等级有哪些呢?4个等级
读未提交:read uncommitted(最低的阻隔等级)《没有提交就读到了》
什么是读未提交?
业务A能够读取到业务B未提交的数据。
这种阻隔等级存在的问题便是:
脏读现象!(Dirty Read)
咱们称读到了脏数据。
这种阻隔等级一般都是理论上的,大多数的数据库阻隔等级都是二档起步!
读已提交:read committed《提交之后才干读到》
什么是读已提交?
业务A只能读取到业务B提交之后的数据。
这种阻隔等级处理了什么问题?
处理了脏读的现象。
这种阻隔等级存在什么问题?
不行重复读取数据。
什么是不行重复读取数据呢?
在业务敞开之后,榜首次读到的数据是3条,当时业务还没有
完毕,或许第二次再读取的时分,读到的数据是4条,3不等于4
称为不行重复读取。
这种阻隔等级是比较实在的数据,每一次读到的数据是肯定的实在。
oracle数据库默许的阻隔等级是:read committed
可重复读:repeatable read《提交之后也读不到,永久读取的都是刚敞开业务时的数据》
什么是可重复读取?
业务A敞开之后,不论是多久,每一次在业务A中读取到的数据
都是一起的。即便业务B将数据现已修正,而且提交了,业务A
读取到的数据仍是没有发生改变,这便是可重复读。
可重复读处理了什么问题?
处理了不行重复读取数据。
可重复读存在的问题是什么?
能够会呈现幻影读。
每一次读取到的数据都是幻象。不够实在!
早晨9点开端敞开了业务,只需业务不完毕,到晚上9点,读到的数据仍是那样!
读到的是假象。不够肯定的实在。
mysql中默许的业务阻隔等级便是这个!!!!!!!!!!!
序列化/串行化:serializable(最高的阻隔等级)
这是最高阻隔等级,功率最低。处理了一切的问题。
这种阻隔等级表明业务排队,不能并发!
synchronized,线程同步(业务同步)
每一次读取到的数据都是最实在的,而且功率是最低的。
验证各种阻隔等级
检查阻隔等级:SELECT @@tx_isolation
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
mysql默许的阻隔等级
被测试的表t_user
验证:read uncommited
mysql> set global transaction isolation level read uncommitted;
业务A 业务B
--------------------------------------------------------------------------------
use bjpowernode;
use bjpowernode;
start transaction;
select * from t_user;
start transaction;
insert into t_user values('zhangsan');
select * from t_user;
验证:read commited
mysql> set global transaction isolation level read committed;
业务A 业务B
--------------------------------------------------------------------------------
use bjpowernode;
use bjpowernode;
start transaction;
start transaction;
select * from t_user;
insert into t_user values('zhangsan');
select * from t_user;
commit;
select * from t_user;
验证:repeatable read
mysql> set global transaction isolation level repeatable read;
业务A 业务B
--------------------------------------------------------------------------------
use bjpowernode;
use bjpowernode;
start transaction;
start transaction;
select * from t_user;
insert into t_user values('lisi');
insert into t_user values('wangwu');
commit;
select * from t_user;
验证:serializable
mysql> set global transaction isolation level serializable;
业务A 业务B
--------------------------------------------------------------------------------
use bjpowernode;
use bjpowernode;
start transaction;
start transaction;
select * from t_user;
insert into t_user values('abc');
select * from t_user;
27.索引(index)
1.什么是索引?
索引是在数据库表的字段上增加的,是为了提高查询功率存在的一种机制。
一张表的一个字段能够增加一个索引,当然,多个字段联合起来也能够增加索引。
索引相当于一本书的目录,是为了缩小扫描规模而存在的一种机制。
关于一本字典来说,查找某个汉字有两种方法:
榜首种方法:一页一页挨着找,直到找到停止,这种查找方法归于全字典扫描。
功率比较低。
第二种方法:先经过目录(索引)去定位一个大约的方位,然后直接定位到这个
方位,做局域性扫描,缩小扫描的规模,快速的查找。这种查找方法归于经过
索引检索,功率较高。
t_user
id(idIndex) name(nameIndex) email(emailIndex) address (emailAddressIndex)
----------------------------------------------------------------------------------
1 zhangsan...
2 lisi
3 wangwu
4 zhaoliu
5 hanmeimei
6 jack
select * from t_user where name = 'jack';
以上的这条SQL句子会去name字段上扫描,为什么?
由于查询条件是:name='jack'
假如name字段上没有增加索引(目录),或许说没有给name字段创立索引,
MySQL会进行全扫描,会将name字段上的每一个值都比对一遍。功率比较低。
MySQL在查询方面首要便是两种方法:
榜首种方法:全表扫描
第二种方法:根据索引检索。
留意:
在实践中,汉语字典前面的目录是排序的,依照a b c d e f....排序,
为什么排序呢?由于只要排序了才会有区间查找这一说!(缩小扫描规模
其实便是扫描某个区间算了!)
在mysql数据库傍边索引也是需求排序的,而且这个索引的排序和TreeSet
数据结构相同。TreeSet(TreeMap)底层是一个自平衡的二叉树!在mysql
傍边索引是一个B-Tree数据结构。
遵从左小又大准则存放。选用中序遍历方法遍历取数据。
2.索引的完结原理?
假定有一张用户表:t_user
id(PK) name 每一行记载在硬盘上都有物理存储编号
----------------------------------------------------------------------------------
100 zhangsan 0x1111
120 lisi 0x2222
99 wangwu 0x8888
88 zhaoliu 0x9999
101 jack 0x6666
55 lucy 0x5555
130 tom 0x7777
提示1:在任何数据库傍边主键上都会主动增加索引目标,id字段上主动有索引,
由于id是PK。另外在mysql傍边,一个字段上假如有unique束缚的话,也会主动
创立索引目标。
提示2:在任何数据库傍边,任何一张表的任何一条记载在硬盘存储上都有
一个硬盘的物理存储编号。
提示3:在mysql傍边,索引是一个独自的目标,不同的存储引擎以不同的方法
存在,在MyISAM存储引擎中,索引存储在一个.MYI文件中。在InnoDB存储引擎中
索引存储在一个逻辑称号叫做tablespace的傍边。在MEMORY存储引擎傍边索引
被存储在内存傍边。不论索引存储在哪里,索引在mysql傍边都是一个树的方法
存在。(自平衡二叉树:B-Tree)
在mysql傍边,主键上,以及unique字段上都会主动增加索引的!!!!
什么条件下,咱们会考虑给字段增加索引呢?
条件1:数据量巨大(究竟有多么巨大算巨大,这个需求测试,由于每一个硬件环境不同)
条件2:该字段常常呈现在where的后边,以条件的方法存在,也便是说这个字段总是被扫描。
条件3:该字段很少的DML(insert delete update)操作。(由于DML之后,索引需求从头排序。)
主张不要随意增加索引,由于索引也是需求保护的,太多的话反而会下降系统的功能。
主张经过主键查询,主张经过unique束缚的字段进行查询,功率是比较高的。
3.索引怎样创立?怎样删去?语法是什么?
创立索引:
mysql> create index emp_ename_index on emp(ename);
给emp表的ename字段增加索引,起名:emp_ename_index
删去索引:
mysql> drop index emp_ename_index on emp;
将emp表上的emp_ename_index索引目标删去。
在mysql傍边,怎样检查一个SQL句子是否运用了索引进行检索?
mysql> explain select * from emp where ename = 'KING';
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | emp | ALL | NULL | NULL | NULL | NULL | 14 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
扫描14条记载:阐明没有运用索引。type=ALL
mysql> create index emp_ename_index on emp(ename);
mysql> explain select * from emp where ename = 'KING';
+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+
| 1 | SIMPLE | emp | ref | emp_ename_index | emp_ename_index | 33 | const | 1 | Using where |
+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+
4.索引有失效的时分,什么时分索引失效呢?
select * from emp where ename like '%T';
ename上即便增加了索引,也不会走索引,为什么?
原因是由于含糊匹配傍边以“%”开头了!
尽量防止含糊查询的时分以“%”开端。
这是一种优化的手法/战略。
mysql> explain select * from emp where ename like '%T';
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | emp | ALL | NULL | NULL | NULL | NULL | 14 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
失效的第2种状况:
运用or的时分会失效,假如运用or那么要求or两头的条件字段都要有
索引,才会走索引,假如其间一边有一个字段没有索引,那么另一个
字段上的索引也会完结。所以这便是为什么不主张运用or的原因。
mysql> explain select * from emp where ename = 'KING' or job = 'MANAGER';
+----+-------------+-------+------+-----------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+-----------------+------+---------+------+------+-------------+
| 1 | SIMPLE | emp | ALL | emp_ename_index | NULL | NULL | NULL | 14 | Using where |
+----+-------------+-------+------+-----------------+------+---------+------+------+-------------+
失效的第3种状况:
运用复合索引的时分,没有运用左侧的列查找,索引失效
什么是复合索引?
两个字段,或许更多的字段联合起来增加一个索引,叫做复合索引。
create index emp_job_sal_index on emp(job,sal);
mysql> explain select * from emp where job = 'MANAGER';
+----+-------------+-------+------+-------------------+-------------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+-------------------+-------------------+---------+-------+------+-------------+
| 1 | SIMPLE | emp | ref | emp_job_sal_index | emp_job_sal_index | 30 | const | 3 | Using where |
+----+-------------+-------+------+-------------------+-------------------+---------+-------+------+-------------+
mysql> explain select * from emp where sal = 800;
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | emp | ALL | NULL | NULL | NULL | NULL | 14 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
失效的第4种状况:
在where傍边索引列参与了运算,索引失效。
mysql> create index emp_sal_index on emp(sal);
explain select * from emp where sal = 800;
+----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+
| 1 | SIMPLE | emp | ref | emp_sal_index | emp_sal_index | 9 | const | 1 | Using where |
+----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+
mysql> explain select * from emp where sal+1 = 800;
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | emp | ALL | NULL | NULL | NULL | NULL | 14 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
失效的第5种状况:
在where傍边索引列运用了函数
explain select * from emp where lower(ename) = 'smith';
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | emp | ALL | NULL | NULL | NULL | NULL | 14 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
失效的第6...
失效的第7...
索引是各种数据库进行优化的重要手法。优化的时分优先考虑的因素便是索引。
索引在数据库傍边分了许多类?
单一索引:一个字段上增加索引。
复合索引:两个字段或许更多的字段上增加索引。
主键索引:主键上增加索引。
仅有性索引:具有unique束缚的字段上增加索引。
.....
留意:仅有性比较弱的字段上增加索引证处不大。
28.视图(view)
1.什么是视图?
view:站在不同的视点去看待同一份数据。
2.怎样创立视图目标?怎样删去视图目标?
表仿制:
mysql> create table dept2 as select * from dept;
dept2表中的数据:
mysql> select * from dept2;
+--------+------------+----------+
| DEPTNO | DNAME | LOC |
+--------+------------+----------+
| 10 | ACCOUNTING | NEW YORK |
| 20 | RESEARCH | DALLAS |
| 30 | SALES | CHICAGO |
| 40 | OPERATIONS | BOSTON |
+--------+------------+----------+
创立视图目标:
create view dept2_view as select * from dept2;
删去视图目标:
drop view dept2_view;
留意:只要DQL句子才干以view的方法创立。
create view view_name as 这儿的句子有必要是DQL句子;
3.用视图做什么?
咱们能够面向视图目标进行增修正查,对视图目标的增修正查,会导致
原表被操作!(视图的特色:经过对视图的操作,会影响到原表数据。)
//面向视图查询
select * from dept2_view;
// 面向视图刺进
insert into dept2_view(deptno,dname,loc) values(60,'SALES', 'BEIJING');
// 查询原表数据
mysql> select * from dept2;
+--------+------------+----------+
| DEPTNO | DNAME | LOC |
+--------+------------+----------+
| 10 | ACCOUNTING | NEW YORK |
| 20 | RESEARCH | DALLAS |
| 30 | SALES | CHICAGO |
| 40 | OPERATIONS | BOSTON |
| 60 | SALES | BEIJING |
+--------+------------+----------+
// 面向视图删去
mysql> delete from dept2_view;
// 查询原表数据
mysql> select * from dept2;
Empty set (0.00 sec)
// 创立视图目标
create view
emp_dept_view
as
select
e.ename,e.sal,d.dname
from
emp e
join
dept d
on
e.deptno = d.deptno;
// 查询视图目标
mysql> select * from emp_dept_view;
+--------+---------+------------+
| ename | sal | dname |
+--------+---------+------------+
| CLARK | 2450.00 | ACCOUNTING |
| KING | 5000.00 | ACCOUNTING |
| MILLER | 1300.00 | ACCOUNTING |
| SMITH | 800.00 | RESEARCH |
| JONES | 2975.00 | RESEARCH |
| SCOTT | 3000.00 | RESEARCH |
| ADAMS | 1100.00 | RESEARCH |
| FORD | 3000.00 | RESEARCH |
| ALLEN | 1600.00 | SALES |
| WARD | 1250.00 | SALES |
| MARTIN | 1250.00 | SALES |
| BLAKE | 2850.00 | SALES |
| TURNER | 1500.00 | SALES |
| JAMES | 950.00 | SALES |
+--------+---------+------------+
// 面向视图更新
update emp_dept_view set sal = 1000 where dname = 'ACCOUNTING';
// 原表数据被更新
mysql> select * from emp;
+-------+--------+-----------+------+------------+---------+---------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+--------+-----------+------+------------+---------+---------+--------+
| 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 |
| 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
| 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 |
| 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 |
| 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 1000.00 | NULL | 10 |
| 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL | 20 |
| 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 1000.00 | NULL | 10 |
| 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | 0.00 | 30 |
| 7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100.00 | NULL | 20 |
| 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | NULL | 30 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
| 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1000.00 | NULL | 10 |
+-------+--------+-----------+------+------------+---------+---------+--------+
4.视图目标在实践开发中究竟有什么用?《便利,简化开发,利于保护》
create view
emp_dept_view
as
select
e.ename,e.sal,d.dname
from
emp e
join
dept d
on
e.deptno = d.deptno;
假定有一条十分杂乱的SQL句子,而这条SQL句子需求在不同的方位上反复运用。
每一次运用这个sql句子的时分都需求从头编写,很长,很麻烦,怎样办?
能够把这条杂乱的SQL句子以视图目标的方法新建。
在需求编写这条SQL句子的方位直接运用视图目标,能够大大简化开发。
而且利于后期的保护,由于修正的时分也只需求修正一个方位就行,只需求
修正视图目标所映射的SQL句子。
咱们以后边向视图开发的时分,运用视图的时分能够像运用table一样。
能够对视图进行增修正查等操作。视图不是在内存傍边,视图目标也是
存储在硬盘上的,不会消失。
再提示一下:
视图对应的句子只能是DQL句子。
可是视图目标创立完结之后,能够对视图进行增修正查等操作。
小插曲:
增修正查,又叫做:CRUD。
CRUD是在公司中程序员之间沟通的术语。一般咱们很少说增修正查。
一般都说CRUD。
C:Create(增)
R:Retrive(查:检索)
U:Update(改)
D:Delete(删)
29.DBA常用指令?
要点把握:
数据的导入和导出(数据的备份)
其它指令了解一下即可。(这个训练日志文档留着,以后忘了,能够打开文档仿制粘贴。)
数据导出?
留意:在windows的dos指令窗口中:
mysqldump bjpowernode>D:\bjpowernode.sql -uroot -p123456
能够导出指定的表吗?
mysqldump bjpowernode emp>D:\bjpowernode.sql -uroot -p123456
数据导入?
留意:需求先登录到mysql数据库服务器上。
然后创立数据库:create database bjpowernode;
运用数据库:use bjpowernode
然后初始化数据库:source D:\bjpowernode.sql
数据库规划三范式
什么是数据库规划范式?
数据库表的规划根据。教你怎样进行数据库表的规划。
数据库规划范式共有?
3个。
榜首范式:要求任何一张表有必要有主键,每一个字段原子性不行再分。
第二范式:建立在榜首范式的根底之上,要求一切非主键字段彻底依靠主键,
不要发生部分依靠。
第三范式:建立在第二范式的根底之上,要求一切非主键字段直接依靠主键,
不要发生传递依靠。
声明:三范式是面试官常常问的,所以必定要熟记在心!
规划数据库表的时分,依照以上的范式进行,能够防止表中数据的冗余,空间的糟蹋。
1.榜首范式
最核心,最重要的范式,一切表的规划都需求满意。
有必要有主键,而且每一个字段都是原子性不行再分。
学生编号 学生名字 联系方法
------------------------------------------
1001 张三 zs@gmail.com,1359999999
1002 李四 ls@gmail.com,13699999999
1001 王五 ww@163.net,13488888888
以上是学生表,满意榜首范式吗?
不满意,榜首:没有主键。第二:联系方法能够分为邮箱地址和电话
学生编号(pk) 学生名字 邮箱地址 联系电话
----------------------------------------------------
1001 张三 zs@gmail.com 1359999999
1002 李四 ls@gmail.com 13699999999
1003 王五 ww@163.net 13488888888
2.第二范式:
建立在榜首范式的根底之上,
要求一切非主键字段有必要彻底依靠主键,不要发生部分依靠。
学生编号 学生名字 教师编号 教师名字
----------------------------------------------------
1001 张三 001 王教师
1002 李四 002 赵教师
1003 王五 001 王教师
1001 张三 002 赵教师
这张表描绘了学生和教师的联系:(1个学生或许有多个教师,1个教师有多个学生)
这是十分典型的:多对多联系!
剖析以上的表是否满意榜首范式?
不满意榜首范式。
怎样满意榜首范式呢?修正
学生编号+教师编号(pk) 学生名字 教师名字
----------------------------------------------------
1001 001 张三 王教师
1002 002 李四 赵教师
1003 001 王五 王教师
1001 002 张三 赵教师
学生编号 教师编号,两个字段联合做主键,复合主键(PK: 学生编号+教师编号)
经过修正之后,以上的表满意了榜首范式。可是满意第二范式吗?
不满意,“张三”依靠1001,“王教师”依靠001,显然发生了部分依靠。
发生部分依靠有什么缺陷?
数据冗余了。空间糟蹋了。“张三”重复了,“王教师”重复了。
为了让以上的表满意第二范式,你需求这样规划:
运用三张表来表明多对多的联系!!!!
学生表
学生编号(pk) 学生名字
------------------------------------
1001 张三
1002 李四
1003 王五
教师表
教师编号(pk) 教师名字
--------------------------------------
001 王教师
002 赵教师
学生教师联系表
id(pk) 学生编号(fk) 教师编号(fk)
------------------------------------------------------
1 1001 001
2 1002 002
3 1003 001
4 1001 002
背口诀:
多对多怎样规划?
多对多,三张表,联系表两个外键!!!!!!!!!!!!!!!
3.第三范式
第三范式建立在第二范式的根底之上
要求一切非主键字典有必要直接依靠主键,不要发生传递依靠。
学生编号(PK) 学生名字 班级编号 班级称号
---------------------------------------------------------
1001 张三 01 一年一班
1002 李四 02 一年二班
1003 王五 03 一年三班
1004 赵六 03 一年三班
以上表的规划是描绘:班级和学生的联系。很显然是1对多联系!
一个教室中有多个学生。
剖析以上表是否满意榜首范式?
满意榜首范式,有主键。
剖析以上表是否满意第二范式?
满意第二范式,由于主键不是复合主键,没有发生部分依靠。主键是单一主键。
剖析以上表是否满意第三范式?
第三范式要求:不要发生传递依靠!
一年一班依靠01,01依靠1001,发生了传递依靠。
不契合第三范式的要求。发生了数据的冗余。
那么应该怎样规划一对多呢?
班级表:一
班级编号(pk) 班级称号
----------------------------------------
01 一年一班
02 一年二班
03 一年三班
学生表:多
学生编号(PK) 学生名字 班级编号(fk)
-------------------------------------------
1001 张三 01
1002 李四 02
1003 王五 03
1004 赵六 03
背口诀:
一对多,两张表,多的表加外键!!!!!!!!!!!!
## 4.总结表的规划?
一对多:
一对多,两张表,多的表加外键!!!!!!!!!!!!
多对多:
多对多,三张表,联系表两个外键!!!!!!!!!!!!!!!
一对一:
一对一放到一张表中不就行了吗?为啥还要拆分表?
在实践的开发中,或许存在一张表字段太多,太巨大。这个时分要拆分表。
一对一怎样规划?
没有拆分表之前:一张表
t_user
id login_name login_pwd real_name email address........
---------------------------------------------------------------------------
1 zhangsan 123 张三 zhangsan@xxx
2 lisi 123 李四 lisi@xxx
...
这种巨大的表主张拆分为两张:
t_login 登录信息表
id(pk) login_name login_pwd
---------------------------------
1 zhangsan 123
2 lisi 123
t_user 用户详细信息表
id(pk) real_name email address........ login_id(fk+unique)
-----------------------------------------------------------------------------------------
100 张三 zhangsan@xxx 1
200 李四 lisi@xxx 2
口诀:一对一,外键仅有!!!!!!!!!!
嘱咐一句话:
数据库规划三范式是理论上的。
实践和理论有的时分有误差。
终究的意图都是为了满意客户的需求,有的时分会拿冗余换履行速度。
由于在sql傍边,表和表之间联接次数越多,功率越低。(笛卡尔积)
有的时分或许会存在冗余,可是为了削减表的联接次数,这样做也是合理的,
而且关于开发人员来说,sql句子的编写难度也会下降。
面试的时分把这句话说上:他就不会以为你是初级程序员了!