javaWeb阶段需要掌握的知识
- 1.概述:
- 2.mysql数据库的常用命令
- 3.简单查询:
- 4.条件查询 where
- 5.模糊查询(重点):
- 6.order by
- 7.分组函数 和 group by
- 8.where子查询
- 9.limit 分页查询(重点掌握)
- 10添加和删除和更新
- 11.约束(Constraint):
- 12.存储引擎
- 13.事务(Transaction)
- 14.索引
- 15.视图(view)
- 16.数据库设计三范式(重点内容,面试经常问)
- 17.补充内容
1.概述:
舍去那些纷繁庸绕,只为来到这片天,
静下心来去做自己想做的事情,何尝不是一种快乐呢?
如果学完javaSE的朋友想进阶javaWeb阶段,建议先学完mysql基础再次往上进行学习,因为用了一个下午的时间进行整理的,眼睛都看花了,估计中途难免会出错,希望理解,希望这篇文章的某个知识点对你有所帮助,就是我最大的快乐。
视频学习地址:mysql
什么是数据库?
就是一个软件,能帮我们把数据进行存储和提取,就好比java里存变量数组等东西的时候是存在内存中的,内存速度快,但是不能长时间存储,而硬盘的好处就是存储时间长,但是速度特别慢
优势:能快速找到我们想要的数据,能进行存储的优化
想要长时间保存数据只能是把数据存储到硬盘上,当我们下次启动的时候,在把数据读取上来。
数据库就是用于存放数据的,软件的开发就是通过界面和数据库的交互达到一个动态交互的过程,特别是学后端的人,不管是php,还是java等等,都得和数据库打交道,就是我们常说的CRUD(增,删,改,查),基础部分我们主要是了解mysql数据库,并且掌握增删改查,好的概念性的东西我就不多说了。
说明一下:因为本人是走的javaWeb开发方向,所有的细节描述的可能不是很好,主要是的描述一个基本的增删改查,以及多表查询,因为我在java代码开发操作数据库的时候,大多数的时候都是在写sql,至于mysql数据库的一些命令是不太关注的。增,删,改,都是比较简单的,难的部分在查询。
作为一名后端程序员来说,大多数时候都是在操作的是数据,所以数据库知识是非常重要的,当然这这是基础部分,后面有空的话,还会写一篇关于数据库的高级部分,先学会用,然后再去窥探其原理,我就是这样去学习的,不要一上来就去关注什么sql调优,以及索引优化,你连sql都写不出来,你还去调什么优呢?是吧?
可能我的大部分文章都是代码加文字,排版也不是特别好,但是我都尽量排版的好一点,让大家看到明白,看文字是一个比较枯燥的事情,但是学习本身就是一个枯燥的事情。
mysql安装:官网下载地址:mysql官网下载地址
进入官网后自行进行下载就行,选择对应的数据库版本,按照自己的需求选择对应的版本即可,如果不会的,百度搜索mysql的安装方式,极其简单,按照步骤一 一 操作就行,这里就不在进行一 一 的概述了。
mysql配置环境变量:
安装好了之后:接下来我们就是要配置mysql的环境变量了,学过java的朋友都知道环境变量,如果不配置环境变量,我们windows系统是找不到mysql的命令的。
找到mysql的安装目录,然后把mysql的地址配置的环境变量path中,有两个环境变量一个是系统变量,一个是用户变量,推荐配置到系统变量中。如图所示:
然后找到windows的cmd命令窗口,用管理员的方式进行运行cmd
然后启动mysql服务。
启动mysql服务:
在关闭mysql服务:
然后登陆进数据库:localhost代表的是本机地址 也就是:127.0.0.1
mysql -h 数据库IP地址 -P 端口号 -u 用户名 -p 密码
好,接下来我们就可以通过cmd命令来进行使用数据库了
接下来我们全程用cmd命令进行操作。
建议: 当然也有很多可视化工具去管理我们的数据库,但是新手来说,我是不太建议这样去做的,一上手就依赖工具,这样是不好的,当我们写sql,这些命令写的滚瓜烂熟的时候,这个时候你就可以去使用工具了,不然一开始就使用工具对于学习是不太好的,多用手敲,可以帮助我们牢牢的记住这些常用的命令。
2.mysql数据库的常用命令
1.sql ,DB,DBMS 分别是什么?他们之间的关系是什么?
DB:database : (数据库,数据库实际上是以文件的形式存在电脑的硬盘上)
DBMS:DataBase Management System : (数据库管理系统:常见的有:mysql oracle,sqlserver,DB2,sybase…)
sql:结构化操作语言,是一门通用的语言,标准的sql适合于所有的数据库产品.
sql: 属于高级语言,只有能看懂英语单词的,写出的sql,大致都能读懂是什么意思.
sql:在执行的时候,实际上也会进行编译,然后在执行sql,(sql由dbms完成)
DBMS负责执行sql语句,通过执行sql语句来操作DB当中的数据
DBMS->(执行)->sql(操作)->DB
一种是mysql特有的指令,一种是通用的sql语句,这个我们一定要区分清楚,后面我会给大家描述的,大家先有个印象。
2.什么是表?
表:table是数据库的最基本组成单元,所有的数据都以表格的形式存在,目的是可读性强.
行:被称为记录(data)
列:称为字段(colum)
3.学习mysql主要还是学通用的sql语句,那么sql语句包括增删改查,sql语句如何分类呢?
DQL (数据定义语言): 查询语句,凡是select都是DQL语句
DML (数据查询语言): insert,delete,update,对表中的数据进行修改
DDL (数据操作语言)create,drop,alter,对表结构的增删改查
TCL (事务控制语言):commit提交事务,rollback 回滚事务 (TCL中的T是什么?是Transaction:事务)
DCL (数据控制语言):grant授权,revoke撤销权限等
我们主要关注的是:DML,DDL ,TCL
4.如何通过dos命令窗口导入数据
4.1:查看有哪些数据库? show database(这个不是ql语句,是mysql特有的命令)
use databaseName;打开某个数据库
4.2:创建属于自己的数据库; create database bjpowernode; (这个不是ql语句,是mysql特有的命令)
4.3use bgpowernode; 打开数据库 (这个不是ql语句,是mysql特有的命令)
4.5:show tables; 查看当前数据库有哪些数据表;mysql命令
4.6: dos 命令窗口打开 : source sql脚本的完整路径名;
如果这个文件以sql结尾的,这样的文件为sql脚本; sql文件数据量太大的时候,无法打开,请使用source命令完成初始化;如果这个sql文件里面有上千万的数据,以这样的方式是比较合理的。
5.删除一个数据库: drop database databaseName;
将以下的sql导入到数据中,接下来的操作都是基于这三张表进行操作;
DROP TABLE IF EXISTS EMP;
DROP TABLE IF EXISTS DEPT;
DROP TABLE IF EXISTS SALGRADE;
CREATE TABLE DEPT
(DEPTNO int(2) not null ,
DNAME VARCHAR(14) ,
LOC VARCHAR(13),
primary key (DEPTNO)
);
CREATE TABLE EMP
(EMPNO int(4) not null ,
ENAME VARCHAR(10),
JOB VARCHAR(9),
MGR INT(4),
HIREDATE DATE DEFAULT NULL,
SAL DOUBLE(7,2),
COMM DOUBLE(7,2),
primary key (EMPNO),
DEPTNO INT(2)
)
;
CREATE TABLE SALGRADE
( GRADE INT,
LOSAL INT,
HISAL INT );
INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES (
10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES (
20, 'RESEARCH', 'DALLAS');
INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES (
30, 'SALES', 'CHICAGO');
INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES (
40, 'OPERATIONS', 'BOSTON');
commit;
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7369, 'SMITH', 'CLERK', 7902, '1980-12-17'
, 800, NULL, 20);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20'
, 1600, 300, 30);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7521, 'WARD', 'SALESMAN', 7698, '1981-02-22'
, 1250, 500, 30);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7566, 'JONES', 'MANAGER', 7839, '1981-04-02'
, 2975, NULL, 20);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28'
, 1250, 1400, 30);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01'
, 2850, NULL, 30);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7782, 'CLARK', 'MANAGER', 7839, '1981-06-09'
, 2450, NULL, 10);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7788, 'SCOTT', 'ANALYST', 7566, '1987-04-19'
, 3000, NULL, 20);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7839, 'KING', 'PRESIDENT', NULL, '1981-11-17'
, 5000, NULL, 10);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7844, 'TURNER', 'SALESMAN', 7698, '1981-09-08'
, 1500, 0, 30);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7876, 'ADAMS', 'CLERK', 7788, '1987-05-23'
, 1100, NULL, 20);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7900, 'JAMES', 'CLERK', 7698, '1981-12-03'
, 950, NULL, 30);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7902, 'FORD', 'ANALYST', 7566, '1981-12-03'
, 3000, NULL, 20);
INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,
DEPTNO ) VALUES (
7934, 'MILLER', 'CLERK', 7782, '1982-01-23'
, 1300, NULL, 10);
commit;
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES (
1, 700, 1200);
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES (
2, 1201, 1400);
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES (
3, 1401, 2000);
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES (
4, 2001, 3000);
INSERT INTO SALGRADE ( GRADE, LOSAL, HISAL ) VALUES (
5, 3001, 9999);
commit;
7.查看数据库表的结构 :desc tableName;
也就是这三张表:
emp(员工表):
dept(部门表):
salgrade(工资等级表):
8.查询某张表中的全部数据:
select * from tableName;
9.9.mysql的常用命令:
9.1查看当前正在使用的数据库 : select database();
9.2:终止一条语句: \c;sql语句没有见到分号(;)是不会结束的;
9.3查看当前数据库的版本: select version();
9.4:退出数据库管理系统: \q | exit | quit
9.5:查看其它数据库中的数据表: show tables from databaseName;
9.6:查看指定表的创建语句: show create table tableName;
3.简单查询:
提示 : 任何一条sql语句都以 ";"号结尾; sql语句 不区分大小写,sql语句里面的关键字不能随便更改sql 语句字符串 用单引号括起来, mysql双引号也行, 但是尽量使用单引号,因为别的数据库可能不支持
查询员工的姓名: select ename from emp;
查询所有员工的年薪:select ename,sal*12 from emp; 字段名可以参与数学运算(其实这样是不太正确的,后面我们在讲)
给查询后的结果列重命名:select eanem as name,sal as salary from emp; 也可以不需要as 用空格分开
查询表中所有的字段:select * from emp; 但是实际开发中不建议使用,这样的查询效率比较低,而且扩展性不强。
4.条件查询 where
条件查询: 执行顺序 先from 然后where 最后select
查询emp表中工资等于5000的记录: select ename,sal from emp where sal=5000;
查询SMITH的工资:select sal from emp where ename=‘SMITH’;
查询工资大于3000(不包括3000)的员工:select ename sal from emp where sal>3000;
查询工资大于3000(包括3000)的员工:select ename sal from emp where sal>=3000;
查询工资不等于3000的员工:select ename sal from emp where sal<>300;
第二种写法:select ename,sal from emp where sal !=3000;
查询工资在1100和3000之间的员工,包括1100和3000?
第一种:select ename,sal from emp where sal>=1100 and sal<=3000;
第二种:select ename,sal from emp where sal between 1100 and 3000;
前小后大,如果前面的数据比后面大的就查询不到任何数据查询1982-01-23日之后入职的员工
select ename ,hiredate from emp where hiredate<‘1982-01-23’;
查询首字母A~C的员工姓名
select ename from emp where ename between ‘A’ and ‘D’;
用在字符方面,前面的包括,后面的不包括
is null is not null 查询
数据库中 null 表示没有值,表示什么值都没有 ,不能用= 号进行比较 必须使用 is null 或者 is not null
查询津贴为null的员工:
select ename,comm from emp where comm is null;
查询没有津贴的员工:
select ename,comm from emp where comm is null or comm=0;
查询津贴不为null的员工:
select ename,comm from epm where comm is not null;
查询岗位是MANAGER和SALESMAN的员工:
select ename,job from emp where job=‘MANAGER’ or job=‘SALESMAN’;
and 和or 联合使用:
注意: and 的优先级比or高,在不知道优先级的情况下,直接在想要先执行的sql语句中套上括号。
找出薪资大于1000的 并且部门编号是20或30的员工?
select ename,sal,deptno from emp where sal>1000 and (deptno=20 or deptno=30);
in 和 not in的用法 in的用法等同于 or in(条件满足的值都查出来)
找出工作岗位是MANAGER和SALESMAN的员工:
select ename, job from emp where job in(‘MANAGER’,‘SALESMAN’);
找出工资为 1000的和5000的; in 后面的值不是区间,而是具体的值:in(条件值)
select ename,job,sal from emp where sal in(800,1300);
等同于:select ename,sal,job from emp where sal=800 or sal=1300;
找出工资不是1000的和5000的员工:
select ename,job,sal from emp where not in(1000,5000);
5.模糊查询(重点):
*like 模糊查询 %:任意多个字符 _ :任意一个字符 转义用 *
找出员工姓名中有O的员工:select ename from emp where like “%O%”;
找出ename中A开头的员工:select ename from emp where ename like ‘A%’;
找出ename中有 _ 的员工:select ename from emp where ename like ‘%_%’; (转义)
找出ename中最后一位为T的员工:select ename from emp where ename like ‘%T’;
6.order by
order by :排序(升序,降序) 默认是升序 从小到大 asc:升序 desc:降序
注意:越靠前的字段,起的主导作用越大,只有前面的字段相等的时候,后面的第二个排序条件才会被用上
按照工资升序排:
select ename,sal from emp order by sal asc;
工资按照降序排,当工资相同按照名字的升序排:
select ename,sal from emp order by sal desc ,ename asc;
找出岗位是 SALESMAN的员工,并且按照工资的降序排列:
select ename,job,sal from emp where job=‘SALESMAN’ order by sal desc;
7.分组函数 和 group by
分组函数: 一共5个 还可以叫多行处理函数,输入多行,输出一行.
count:计数
sum:求和 sum:函数自动忽略null
avg:平均值
max:最大值
min:最小值
所有的分组函数都是对某一组数据进行操作
找出员工的工资总和:
select sum(sal) from emp;
找出最高工资:
select max(sal) from emp;
找出最低工资:
select min(sal) from emp;
找出平均工资:
select avg(sal) from emp;
找出所有的员工总数:
select count(ename) from emp;
分组函数自动忽略null值,但是:0不会被忽略:
select count(comm) from emp; 结果是:4
单行处理函数: 输入一行,输出一行
计算出员工的年薪:select ename ,(sal+comm)*12 as yearssal from emp;
错误的查询结果:
因为在select sql 语句中 会有一个默认的分组,还没有分组就使用分组函数就有问题,因为分组函数都是在group by 之后执行
select ename,sal from emp where sal>(select avg(sal) from emp);
注意:所有的数据库数学运算表达式中 如果有一个值为null最终的结果就是null
正确的查询结果: 这个是 where 字查询 后面会介绍到
ifnull(可能为null的数据,被当做什么处理)计算出员工的年薪,并按照工资降序排序:
select ename,sal+ifnull(comm,0) from emp order by sal desc;
正确查询结果:
错误的查询结果:
sql语句中有一个语法规则,分组函数不可以直接使用在where子句的后面
count(*) 和count(某个字段具体值)的区别:
count(*):统计的是这个表的所有记录总数
count(某个字段具体值)统计的是某个字段中不为null的记录总数
分组函数也可以组合起来使用:
统计员工表中的记录总数,工资总和,平均工资,最高工资,最低工资
select count(*) as count,sum(sal) as sum,avg(sal) as avg,max(sal) as max,min(sal) as min from emp;
group by 和having
- group by:按照某个字段或者某些字段进行分组
- having:对分组之后的数据进行再次过滤
找出每个岗位的最高薪资
select job,max(sal) from emp group by job;
max(sal):在group by job 分组完成之后再执行的按照工作岗位分组,计算出每个工作岗位的平均薪资:
select job, avg(sal) from emp group by job;
多个字段进行分组
找出每个部门不同工作岗位的最高薪资:
select deptno,job,max(sal) from emp group by deptno,job order by deptno;
找出每个部门的最高薪资,找出大于2900的部门:
select deptno,max(sal) from emp group by deptno having max(sal)>2900;
//执行效率比较低
建议能使用where过滤的尽量使用where过滤:
select deptno,max(sal) from emp where sal>2900 group by deptno;
找出每个部门的平均薪资,要求显示大于2000的数据:
select deptno ,avg(sal) from emp group by deptno having avg(sal)>2000;
where 后面不能使用分组函数 先使用wher过滤 where过滤不掉的数据再用having过滤 having是对分完组之后的数据不满意再次进行过滤
select job,max(sal) ,ename from emp group by job; // 错误
该语句在mysql中执行没有问题,但是结果不是我们想要的,在oracle数据库中会直接报错
规则:当一条sql语句中有 group by 的话,select 后只能跟分组函数和参与分组的字段
分组函数通常和group by 进行使用 ,并且分组函数都是在 group by 语句执行结束之后才会执行,当一条sql语句没有group by的话,整张表的数据会自成一组
关于查询结果集去重复:
在select语句后加上 distinct 关键字 只能查询单列,去重单个字段的重复,只能出现在所有字段的最前面
查询有哪些工作岗位: select distinct job from emp;
sql: select distinct job deptno,from emp; 将job和deptno两个字段联合起来去重复
统计岗位的数量: select count(distinct job) from emp;
总结DQL语句: 顺序千万不能颠倒
select
…
where 1 (可选)
…
group by 2 (可选)
…
having 3(可选)
…
order by 4 (可选)
…
8.连接查询(重点)
在实际开发中,大部分都是不单表查询,而是多表查询,一般都是多张表联合查询,取出最终结果
在实际开发中,一般一个业务都会对应多张表
- 连接查询的分类:
- 根据语法出现的年代来划分
- sql92(一些老的DAB 数据库管理系统)
- sql99(比较新的语法)
根据表的连接类型来划分:
- 内连接
- 等值连接
- 非等值连接
- 自连接
- 外连接
- 左外连接(左外连接)
- 右外连接(右)连接)
- 全连接
在表的连接查询方面有一种现象,称为:笛卡尔积现象(笛卡尔乘积现象)
找出每个员工的部门名称,要求显示员工的部门和姓名
:select ename,dname from emp,dept;
因为查出来的结果太长了,这里就不截取全部了,感兴趣的朋友可以自己执行以下这条sql,观察一下查询出来的结果。
笛卡尔积现象:当两张表进行连接查询的时候,没有任何条件进行限制的时候,最终的查询结果条数就是两张表记录数的乘积;
关于表的别名:
select e.ename,d.dname from emp e,dept d;
给表起别名的好处:
1.执行效率更高
2可读性好
如何避免笛卡尔积现象,加where条件进行判断,避免了笛卡尔积现象,不会减少匹配的次数,只不过显示出来的都是有效记录而已
找出每个员工的部门名称,要求显示员工的部门和姓名:
select e.ename,d.dname from emp e,dept d where d.deptno=e.deptno; sql 92(不经常用)
内连接查询:
内连接之等值连接:最大的特点是,条件是等量关系 on 后面是连接条件 inner可以省略掉不写
查询查询每个员工的部门名称,要求显示员工名个部门名:
sql: select e.ename,d.dname from emp e inner join dept d on d.deptno=e.deptno;
sql99的写法更加清晰,连接条件和where条件分的更加清晰了
查询SMITH名字和部门名称:
sql: select e.ename,d.dname from emp e inner join dept d on d.deptno=e.deptno where ename =‘SMITH’;
内连接之非等值连接 最大的特点是 :连接条件中的关系是非等量关系找出每个员工的工资等级要求显示员工姓名,工资,等级:
sql: select e.ename,e.sal,s.grade from emp e join salgrade s on e.sal between s.losal and s.hisal;
内连接之自然连接
最大的特点就是一张表看成两张表,自己连接自己 其实就是把当前这张表分成两张表,然后自己连接自己进行查询
找出每个员工的上级领导,要求显示员工名和对应的领导名称
sql: select a.ename as ‘员工名’,b.ename as ‘领导名’ from emp a join emp b on a.mgr=b.empno;
找出SMITH的上级领导,要求显示员工名和领导名称
sql: select a.ename as “员工姓名” ,b.ename as “领导姓名” from emp a join emp b on a.mgr=b.empno where a.ename=“SMITH”;
外连接和内连接的区别?
内连接:假设A表和B表进行连接,使用内连接的话,凡是A表和B表能够匹配上的记录查询出来,这就是内连接,AB两张表没有主副之分,两张表的关系是平等的.
外连接:假设AB两张表进行连接,使用的是外连接的话,AB两张表中其中有一张是主表,一张是副表,主要的查询主表中的数据,捎带着查询副表,
当副表中的数据和主表中的数据没有匹配上的时候,副表自动模拟出null与之匹配 .
外连接分类 outer 是可以省略不写的 (外连接使用的比较多)
左外连接(左连接):表示左边的这张表是主表 如果主表和副表对应不上的话,副表会以null的形式进行补上
右外连接(右连接):表示右边的这张表是主表
左连接有右连接的写法,右连接也会有对应左连接的写法
找出每个员工的上级领导(所有员工必须查询出来):
左连接:
sql : select a.ename as ‘员工名’,b.ename as ‘领导名’ from emp a left outer join emp b on a.mgr=b.empno;
右连接 把关键位置换个位置就行了
sql :select a.ename as ‘员工名’,b.ename as ‘领导名’ from emp b right join emp b on a.mgr=b.empno;
外连接最重要的特点就是:
主表的数据无条件的全部查询出来,内连接 如果匹配不上,就会丢失数据
找出那个部门没有员工:
select d.* from emp e right join dept d on d.deptno = e.deptno where e.deptno is null;
三张表联合查询(重点)
找出每一个员工的部门名称以及工资等级:
sql:
select d.dname,e.ename,s.grade from
dept d join emp e join salgrade s
on d.deptno=e.deptno and e.sal between s.losal and hisal;
找出每一个员工的部门名称以及工资等级以及上级领导:
sql:
select e.ename as '员工',d.dname as '部门名称',s.grade as '工资等级',e1.ename as '领导' from
emp e join dept d on e.deptno = d.deptno join salgrade s
on e.sal between s.losal and s.hisal
left join emp e1 on e.mgr = e1.empno;
8.where子查询
子查询:什么是子查询?子查询可以出现在哪里?
select语句中嵌套select查询语句,被嵌套的select查询就是子查询
子查询可以出现在哪儿?
select …(select)
from …(select)
where …(select)
where :后面跟子查询
找出高于平均薪资的员工信息:
select * from emp where sal> (select avg(sal) from emp);
from:后面跟子查询
找出每个部门平均薪资的薪水等级: from 后面跟子查询 相当于把查询的结果作为一张临时表 然后起个别名,然后再去连接其他的表进行查询
select t.*,s.grade from (select deptno,avg(sal) as avgsal from emp group by deptno) t join salgrade s on t.avgsal between s.losal and s.hisal;
找出每个部门的薪资等级的平均值:先得到每个员工的薪水等级,然后再按照部门分组,然后求薪资等级的平均值
sql: select e.deptno,avg(s.grade) from emp e join salgrade s on e.sal between s.losal and s.hisal group by e.deptno;
select:后面跟子查询:
找出每个员工所在的部门名称:
select e.ename as empName,(select d.dname from dept d where d.deptno=e.deptno) as ‘部门’ from emp e;
union (可以将查询的结果集相加)
1.UNION操作符用于合并两个或多个 SELECT 语句的结果集。
2. UNION结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名。
3. 默认UNION 操作符选取不同的值。如果允许重复的值,则使用 UNION ALL。
4. 注意: 需要注意的是前面一条sql语句的查询字段必须和后面一条sql语句的查询字段相同
5.特点是可以将两张毫无关联的表查询的结果集显示在一起
案例:找出工作岗位是SALLESMAN和MANAGER的员工?
sql1: select job,ename from emp where job='SALESMAN’or job=‘MANAGER’;
sql2: select job,ename from emp where job in(‘SALESMAN’,‘MANAGER’);
union: sql3:
select job,ename from emp where job=‘SALESMAN’ union select job,ename from emp where job=‘MANAGER’;
9.limit 分页查询(重点掌握)
limit (分页查询,重点掌握) 取结果集中的部分数据 mysql行的下班是从 0开始
1.limit是mysql数据库特有的,其他数据库中没有,不通用,(Oracle 中有一个相同的机制,叫做rownum)取出工资前五名的员工:
select ename,sal from emp order by sal desc limit 0,5;
还可以这样:
select ename,sal from emp order by sal desc limit 5;
只写一位的时候,默认就是0
每页显示3条记录:
第1页:0, 3
第2页:3, 3
第3页:6, 3
第4页:9, 3
第5页:12, 3
每页显示pageSize条记录: (当前页-1)*每页需要显示的记录条数
第pageNo页:(pageNo - 1) * pageSize, pageSize
10添加和删除和更新
表的创建:
create tablee tableName{
字段名1,数据类型,
字段名2,数据类型,
字段名3,数据类型,
......
};
关于mysql的数据类型:
int (整数)
bigint (长整形)
float (浮点型)
varchar(可变长字符串) 不确定字符串的长度用 varchar 例如:姓名
char(定长字符串) 固定的字符串长度char 例如:性别
date (日期类型)
BLOB(二进制大对象,村图片,视频等)
CLOB(字符串大对象,可以存储比较大的文本类型字符串)
创建学生表: 信息包括 姓名(varchar),性别(char) ,班级编号(int),生日(char)
create table t_student(
no bigint,
name varchar(255),
sex char(1) default '男',
classno varchar(255),
birthd char(10)
);
删除表:当这个表存在就删除: drop table if exists tableName;
添加数据: insert into 要求字段的数量和值的数量相等,并且数据类型要一致
需要注意的地方:
当一条insert语句执行成功之后,表格当中必然会多一行记录。
即使多的这一行记录当中某些字段是NULL,后期也没有办法在执行
insert语句插入数据了,只能使用update进行更新。
方式1: 插入全部数据,前面的字段值和后面的值的顺序需要相对应.
insert into t_student(no, name, sex, classno, birthd) values(1, 'zhangsan', '男', 'gaosan1ban', '2020-11-25');
方式2: 不写字段名,插入
insert into t_student values(1, 'zhangsan', '男', 'gaosan1ban', '2020-11-25');
方式3:插入部分数据,如果,没有插入的字段就为 该字段的默认值,如果没有默认值,就是null
insert into t_student(no, name, sex, classno) values(1, 'zhangsan', '男', 'gaosan1ban');
批量插入:
insert into t_student(no, name, sex, classno, birthd) values(1, 'zhangsan', '男', 'gaosan1ban', '2020-11-25'), (2, 'lisi', '女', 'gaosan2ban', '2020-11-26');
表的复制: create table NewTableName as select * from emp;
将查询出来的结果集复制条另外一张新表之中;
将查询的结果插入到另外一张已经存在的表当中: 查询的结果和被插入的表的结果和字段要相同才可以
insert into dept1 select *from dept;
修改数据: update 注意:没有条件整张表全部更新
语法: update 表名 set 字段名1=值1,字段名2=值2… where 条件;
修改no=1的记录:
update t_student set name='lisi' ,sex='男' ,classno='gaosan5ban',birthd='1999-10-13' where no=1;
删除数据: delete from tableName where 条件; 没有条件则删除所有的记录
删除 no =1 的记录: delete from t_student where no=1;
删除所有的数据: delete from t_student;
怎么删除数据量比较大的表: 全部删除值剩下表结构和表头的字段名 谨慎使用 表被截断,不可回滚.永久删除
truncate table tableName;
11.约束(Constraint):
什么是约束?常见的约束有哪些呢?
在创建表的时候,可以给表的字段添加相应的约束,添加约束的目的是为了保证表中数据的
合法性、有效性、完整性。
常见的约束有哪些呢?
非空约束:(not null) 被约束的字段不能为null
唯一约束(unique):约束的字段不能重复
主键约束(primary key):约束的字段既不能为NULL,也不能重复(简称PK)
外键约束(foreign key):…(简称FK)
检查约束(check):注意Oracle数据库有check约束,但是mysql没有,目前mysql不支持该约束。
非空约束:
案例:
drop table if exists t_user;
create table t_user(
id int,
username varchar(255) not null,
password varchar(255)
);
insert into t_user(id,password) values('admin','123');
报错信息: ERROR 1364 (HY000): Field 'username' doesn't have a default value
* 注意:not null约束只有列级约束。没有表级约束。
唯一性约束:修饰的字段具有唯一性,但是可以为null
案例:给某一列添加unique
drop table if exists t_user;
create table t_user(
id int,
username varchar(255) unique
);
insert into t_user values(1,'zhangsan');
insert into t_user values(2,'zhangsan');
报错信息:ERROR 1062 (23000): Duplicate entry 'zhangsan' for key 'username'
案例:
给两个列或者多个列添加unique 【表级约束】 : 多个字段联合起来添加1个约束unique
drop table if exists t_user;
create table t_user(
id int,
usercode varchar(255),
username varchar(255),
unique(usercode,username)
);
测试:
insert into t_user values(1,'111','zs');
insert into t_user values(2,'111','ls');
insert into t_user values(3,'222','zs');
select * from t_user;
insert into t_user values(4,'111','zs');
ERROR 1062 (23000): Duplicate entry '111-zs' for key 'usercode'
主键约束 不能为空并且不能重复
怎么给一张表添加主键约束呢?
列级约束:
drop table if exists t_user;
create table t_user(
id int primary key,
username varchar(255),
email varchar(255)
);
insert into t_user(id,username,email) values(1,'zs','zs@123.com');
insert into t_user(id,username,email) values(2,'ls','ls@123.com');
insert into t_user(id,username,email) values(3,'ww','ww@123.com');
select * from t_user;
测试:
insert into t_user(id,username,email) values(1,'jack','jack@123.com');
ERROR 1062 (23000): Duplicate entry ‘1’ for key ‘PRIMARY’
insert into t_user(username,email) values('jack','jack@123.com');
ERROR 1364 (HY000): Field ‘id’ doesn’t have a default value
根据以上的测试得出:id是主键,因为添加了主键约束,主键字段中的数据不能为NULL,也不能重复。
主键的特点:不能为NULL,也不能重复。
主键相关的术语?
主键约束 : primary key
主键字段 : id字段添加primary key之后,id叫做主键字段
主键值 : id字段中的每一个值都是主键值。
主键有什么作用?
表的设计三范式中有要求,第一范式就要求任何一张表都应该有主键。
主键的作用:主键值是这行记录在这张表当中的唯一标识。(就像一个人的身份证号码一样。)
主键的分类?
根据主键字段的字段数量来划分:
1.单一主键(推荐的,常用的。)
2.复合主键(多个字段联合起来添加一个主键约束)(复合主键不建议使用,因为复合主键违背三范式。)
3.根据主键性质来划分:
4.自然主键:主键值最好就是一个和业务没有任何关系的自然数。(这种方式是推荐的)
5.业务主键:主键值和系统的业务挂钩,例如:拿着银行卡的卡号做主键,拿着身份证号码作为主键。(不推荐用)
注意: 最好不要拿着和业务挂钩的字段作为主键。因为以后的业务一旦发生改变的时候,主键值可能也需要随着发生变化,但有的时候没有办法变化,因为变化可能会导致主键值重复。
一张表的主键约束只能有1个。(必须记住)
mysql提供主键值自增:(非常重要。)// id字段自动维护一个自增的数字,从1开始,以1递增。
drop table if exists t_user;
create table t_user(
id int primary key auto_increment,
username varchar(255)
);
insert into t_user(username) values('a');
insert into t_user(username) values('b');
insert into t_user(username) values('c');
insert into t_user(username) values('d');
insert into t_user(username) values('e');
insert into t_user(username) values('f');
select * from t_user;
提示:Oracle当中也提供了一个自增机制,叫做:序列(sequence)对象。
外键约束:
业务背景:
请设计数据库表,用来维护学生和班级的信息?
两张表(班级表和学生表)
t_class 班级表
cno(pk) cname
---------------------------------------------------------------------------------------
101 xxx二中高三1班
102 xxx二中高三2班
t_student 学生表
sno(pk) sname classno(该字段添加外键约束fk)
---------------------------------------------------------------------------------------
1 zs1 101
2 zs2 101
3 zs3 102
4 zs4 102
5 zs5 102
练习:将以上表的建表语句写出来:
t_student中的classno字段引用t_class表中的cno字段,此时t_student表叫做子表。t_class表叫做父表。
顺序要求:
删除数据的时候,先删除子表,再删除父表。
添加数据的时候,先添加父表,在添加子表。
创建表的时候,先创建父表,再创建子表。
删除表的时候,先删除子表,在删除父表。
drop table if exists t_student2;
drop table if exists t_class;
父表
create table t_class(
cno int,
cname varchar(255),
primary key(cno)
);
子表
create table t_studen2t(
sno int,
sname varchar(255),
classno int,
primary key(sno),
foreign key(classno) references t_class(cno)
);
插入测试数据
insert into t_class values(101,'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
insert into t_class values(102,'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy');
insert into t_student values(1,'zs1',101);
insert into t_student values(2,'zs2',101);
insert into t_student values(3,'zs3',102);
insert into t_student values(4,'zs4',102);
insert into t_student values(5,'zs5',102);
insert into t_student values(6,'zs6',102);
select * from t_class;
select * from t_student;
insert into t_student values(7,‘lisi’,103);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`bjpowernode`.INT `t_student_ibfk_1` FOREIGN KEY (`classno`) REFERENCES `t_class` (`cno`))
外键值可以为NULL?
外键可以为NULL。
外键字段引用其他表的某个字段的时候,被引用的字段必须是主键吗?
注意:被引用的字段不一定是主键,但至少具有unique约束,且数据类型相同。
12.存储引擎
完整的建表语句
CREATE TABLE `t_x` (
`id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
注意:在MySQL当中,凡是标识符是可以使用飘号括起来的。最好别用,不通用。
建表的时候可以指定存储引擎,也可以指定字符集。
mysql默认使用的存储引擎是InnoDB方式。
默认采用的字符集是UTF8
常见的存储引擎?
Engine: MyISAM
Support: YES
Comment: MyISAM storage engine
Transactions: NO
XA: NO
Savepoints: NO
MyISAM这种存储引擎不支持事务。
MyISAM是mysql最常用的存储引擎,但是这种引擎不是默认的。
MyISAM采用三个文件组织一张表:
xxx.frm(存储格式的文件)
xxx.MYD(存储表中数据的文件)
xxx.MYI(存储表中索引的文件)
优点:可被压缩,节省存储空间。并且可以转换为只读表,提高检索效率。
缺点:不支持事务。
-----------------------------------------------------------------------------
Engine: InnoDB
Support: DEFAULT
Comment: Supports transactions, row-level locking, and foreign keys
Transactions: YES
XA: YES
Savepoints: YES
优点:支持事务、行级锁、外键等。这种存储引擎数据的安全得到保障。
表的结构存储在xxx.frm文件中
数据存储在tablespace这样的表空间中(逻辑概念),无法被压缩,无法转换成只读。
这种InnoDB存储引擎在MySQL数据库崩溃之后提供自动恢复机制。
InnoDB支持级联删除和级联更新。
-------------------------------------------------------------------------------------
Engine: MEMORY
Support: YES
Comment: Hash based, stored in memory, useful for temporary tables
Transactions: NO
XA: NO
Savepoints: NO
缺点:不支持事务。数据容易丢失。因为所有数据和索引都是存储在内存当中的。
优点:查询速度最快。
以前叫做HEPA引擎。
13.事务(Transaction)
什么是事务?
一个事务是一个完整的业务逻辑单元,不可再分。
比如:银行账户转账,从A账户向B账户转账10000.需要执行两条update语句:
update t_act set balance = balance - 10000 where actno = ‘act-001’;
update t_act set balance = balance + 10000 where actno = ‘act-002’;
以上两条DML语句必须同时成功,或者同时失败,不允许出现一条成功,一条失败。
要想保证以上的两条DML语句同时成功或者同时失败,那么就需要使用数据库的“事务机制”。
和事务相关的语句只有:DML语句。(insert delete update)
为什么?因为它们这三个语句都是和数据库表当中的“数据”相关的。
事务的存在是为了保证数据的完整性,安全性。
假设所有的业务都能使用1条DML语句搞定,还需要事务机制吗?
不需要事务。
但实际情况不是这样的,通常一个“事儿(事务【业务】)”需要多条DML语句共同联合完成。
事务的原理(重点)
假设需要执行三条sql语句,分别是insert,update,delete,完成一个业务
1.开启事务
2.执行insert语句 (这个执行成功之后,把这个执行的记录存到数据库的操作历史当中,但是并不会向数据库添加一条数据)
3.执行update语句 (这个执行成功之后,把这个执行的记录存到数据库的操作历史当中,但是并不会修改数据库中的数据)
4.执行delete语句(这个执行成功之后,把这个执行的记录存到数据库的操作历史当中,但是并不会删除数据库中的数据)
5.1提交事务(执行数据库中的历史操作记录,并且清空历史记录)
5.1事务的回滚(清空数据库中的历史操作记录,但是不会执行数据库历史操作记录,不会对数据进行修改)
事务的特性?
事务包括四大特性:ACID(重点,记不住的话,先背下来,后面再理解)
A: 原子性:事务中包含的操作被看做一个逻辑单元,这个逻辑单元中的操作要么全部成 功,要么全部失败。
C: 一致性:事务完成时,数据必须处于一致状态,数据的完整性约束没有被破坏,事务在执行过程中
发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没 有执行过一样。
I:事务允许多个用户对同一个数据进行并发访问,而不破坏数据的正确性 和完整性。同时,并行事务的修改必须与其他并行事务的修改相互独立。
D:持久性:持久性说的是最终数据必须持久化到硬盘文件中,事务才算成功的结束。
关于事务之间的隔离性
事务隔离性存在隔离级别,理论上隔离级别包括4个:
第一级别:读未提交(read uncommitted)
对方事务还没有提交,我们当前事务可以读取到对方未提交的数据。
读未提交存在脏读(Dirty Read)现象:表示读到了脏的数据。
第二级别:读已提交(read committed)
对方事务提交之后的数据我方可以读取到。
这种隔离级别解决了: 脏读现象没有了。
读已提交存在的问题是:不可重复读。
第三级别:可重复读(repeatable read)
这种隔离级别解决了:不可重复读问题。
这种隔离级别存在的问题是:读取到的数据是幻象。
第四级别:序列化读/串行化读(serializable)
解决了所有问题。
效率低。需要事务排队。
oracle数据库默认的隔离级别是:读已提交。
mysql数据库默认的隔离级别是:可重复读。
演示事务
mysql事务默认情况下是自动提交的。关闭事务:Set autocommit = 0; 开启事务: start transaction;
(什么是自动提交?只要执行任意一条DML语句则提交一次。)怎么关闭自动提交?
回滚事务:rollback;
提交事务:commit;
需要注意的是不管是回滚事务还是提交事务,事务都会结束,需要重新开启;
查看当前数据库的事务隔离级别: select @@global.transaction_isolation;
事务演示: 注意设置全局事务隔离级别后需要退出mysql管理系统,然后查询登录
第一级别:读未提交(read uncommitted)
1.设计全局的事务隔离级别: set global transaction isolation level read uncommitted;
2.开启事务 start transaction; (两个窗口都需要开启事务)
3.打开两个dos命令窗口:一个窗口A中执行添加语句,但是不要提交事务,在另外一个窗口中B进行查询
4.结果:另外一个窗口A没有提交事务的时候,另外一个窗口B也能读取到,这样就造成了数据的脏读.窗口A把事务回滚了,窗口B再去读的时候,数据就读不到了.
第二级别:读已提交
1.设置事务全局事务隔离级别 : set global transaction isolation level read committed;
2.开启事务 start transaction; (两个窗口都需要开启事务)
3.打开两个dos命令窗口:一个窗口A中执行添加语句,但是不要提交事务,在另外一个窗口中B进行查询
4.结果:另外一个窗口A没有提交事务的时候,另外一个窗口B就不能读取到刚刚添加的数据,着就是读已提交,只有窗口A提交了事务之后,窗口B才能读取到刚刚添加的数据
第三级别: 可重复读
1.设置全局事务的隔离级别:set global transaction isolation level repeatable read;
2: start transaction; (两个窗口都需要开启事务)
3.打开两个dos命令窗口:一个窗口A中添加一条记录,但是不要提交事务,在另外一个窗口中B进行查询
4.结果: 当窗口A添加成功之后, 窗口B是查询不到的,查询到的数据都是开启事务之前的数据,直到窗口A提交事务之后,窗口B才能查询到.窗口A读到的是备份数据,这是幻读
第四级别:串行化,序列化:
1.设置全局事务隔离级别: set global transaction isolation level serializable;
2: start transaction; (两个窗口都需要开启事务)
3.打开两个dos命令窗口:一个窗口A中添加一条记录,但是不要提交事务,在另外一个窗口中B进行查询
4.结果: 当AB连个窗口都开启事务之后,窗口A去执行添加语句的时候是会直接卡住的,只能等窗口B提交事务之后,窗口A才能插入数据,所有的事务否需要排队,不能两个事务同时操作一张表;
14.索引
查看sql语句的执行计划: explain select * from emp where sal=5000;
什么是索引?有什么用?
索引就相当于一本书的目录,通过目录可以快速的找到对应的资源。
在数据库方面,查询一张表的时候有两种检索方式:
第一种方式:全表扫描
第二种方式:根据索引检索(效率很高)
索引为什么可以提高检索效率呢?
其实最根本的原理是缩小了扫描的范围。
索引虽然可以提高检索效率,但是不能随意的添加索引,因为索引也是数据库当中
的对象,也需要数据库不断的维护。是有维护成本的。比如,表中的数据经常被修改
这样就不适合添加索引,因为数据一旦修改,索引需要重新排序,进行维护。
添加索引是给某一个字段,或者说某些字段添加索引。
select ename,sal from emp where ename = ‘SMITH’;
当ename字段上没有添加索引的时候,以上sql语句会进行全表扫描,扫描ename字段中所有的值。
当ename字段上添加索引的时候,以上sql语句会根据索引扫描,快速定位。
怎么创建索引对象?怎么删除索引对象?
创建索引对象:
create index 索引名称 on 表名(字段名);
删除索引对象:
drop index 索引名称 on 表名;
什么时候考虑给字段添加索引?(满足什么条件)
数据量庞大。(根据客户的需求,根据线上的环境)
该字段很少的DML操作。(因为字段进行修改操作,索引也需要维护)
该字段经常出现在where子句中。(经常根据哪个字段查询)
注意:主键和具有unique约束的字段自动会添加索引。
根据主键查询效率较高。尽量根据主键检索。
索引底层采用的数据结构是:B + Tree
索引的实现原理?
通过B Tree缩小扫描范围,底层索引进行了排序,分区,索引会携带数据在表中的“物理地址”,最终通过索引检索到数据之后,获取到关联的物理地址,通过物理地址定位表中的数据,效率是最高的。
select ename from emp where ename = ‘SMITH’;
通过索引转换为:
select ename from emp where 物理地址 = 0x3;
索引的分类?
单一索引:给单个字段添加索引
复合索引: 给多个字段联合起来添加1个索引
主键索引:主键上会自动添加索引
唯一索引:有unique约束的字段上会自动添加索引
索引什么时候失效?
select ename from emp where ename like ‘%A%’;
模糊查询的时候,第一个通配符使用的是%,这个时候索引是失效的。
15.视图(view)
可以查询某个表的某些字段(也可以是全部字段)然后创建一个新的视图表
什么是视图?
站在不同的角度去看到数据。(同一张表的数据,通过不同的角度去看待)。
怎么创建视图?怎么删除视图?
create view myview as select empno,ename from emp;
将查询出来的结果又生成一张表,对这个视图表进行操作,对视图表的操作也会影响到原表的数据
删除视图:drop view myview;
注意:只有DQL语句才能以视图对象的方式创建出来。
对视图进行增删改查,会影响到原表数据。(通过视图影响原表数据的,不是直接操作的原表)
可以对视图进行CRUD操作。
视图的作用?
视图可以隐藏表的实现细节。保密级别较高的系统,数据库只对外提供相关的视图,java程序员只对视图对象进行CRUD。
DBA命令 数据库的导入导出
将数据库当中的数据导出
在windows的dos命令窗口中执行:(导出整个库)
mysqldump bjpowernode>D:\bjpowernode.sql -uroot -p333
在windows的dos命令窗口中执行:(导出指定数据库当中的指定表)
mysqldump bjpowernode emp>D:\bjpowernode.sql -uroot –p123
导入数据
create database bjpowernode;
use bjpowernode;
source D:\bjpowernode.sql
16.数据库设计三范式(重点内容,面试经常问)
什么是设计范式?
设计表的依据。按照这个三范式设计的表不会出现数据冗余。
三范式都是哪些?
第一范式:
任何一张表都应该有主键,并且每一个字段原子性不可再分。 不能有一个字段是联系方式:里面放邮箱和电话号码
第二范式:
建立在第一范式的基础之上,所有非主键字段完全依赖主键,不能产生部分依赖。
多对多?三张表,关系表两个外键。
t_student学生表
sno(pk) sname
-------------------
1 张三
2 李四
3 王五
t_teacher 讲师表
tno(pk) tname
---------------------
1 王老师
2 张老师
3 李老师
t_student_teacher_relation 学生讲师关系表
id(pk) sno(fk) tno(fk)
----------------------------------
1 1 3
2 1 1
3 2 2
4 2 3
5 3 1
6 3 3
第三范式:
建立在第二范式的基础之上,所有非主键字段直接依赖主键,不能产生传递依赖。
一对多?两张表,多的表加外键。
班级t_class
cno(pk) cname
--------------------------
1 班级1
2 班级2
学生t_student
sno(pk) sname classno(fk)
---------------------------------------------
101 张1 1
102 张2 1
103 张3 2
104 张4 2
105 张5 2
提醒:在实际的开发中,以满足客户的需求为主,有的时候会拿冗余换执行速度。
39.3、一对一怎么设计?
一对一设计有两种方案:主键共享
t_user_login 用户登录表
id(pk) username password
--------------------------------------
1 zs 123
2 ls 456
t_user_detail 用户详细信息表
id(pk+fk) realname tel ....
------------------------------------------------
1 张三 1111111111
2 李四 1111415621
一对一设计有两种方案:外键唯一。
t_user_login 用户登录表
id(pk) username password
--------------------------------------
1 zs 123
2 ls 456
t_user_detail 用户详细信息表
id(pk) realname tel userid(fk+unique)....
-----------------------------------------------------------
1 张三 1111111111 2
2 李四 1111415621 1
17.补充内容
数据库表之间的关系
一对一(单张表,一个主键)
一对多:(两张表,两个主键,一个外键)
一的一方:主表(一个主键)
多的一方:从表(一个主键,新建一个字段组作为外键,取值来源于主表的主键)
多对多(三张表,两个主键,两个外键)
中间表:中间表两个外键,两个外键分别关联另外的两张表