查看databases,tables,use
mysql:
select version();
show databases;
show tables;
use username
可以使用 desc t_user 来查看表结构、表中列的声明顺序
oracle:
select * from all_users;
select * from user_tables;
select table_name from user_tables; //当前用户的表
select table_name from all_tables; //所有用户的表
select table_name from dba_tables; //包括系统表
select table_name from dba_tables where owner=‘zfxfzb’
conn username;
对于null的处理:
mysql:
计算每个员工的年薪?
select ename,(sal+comm)*12 as yearsal from emp;
重点:所有数据库都是这样规定的,只要有NULL参与的运算结果一定是NULL。
使用ifnull函数:
select ename,(sal+ifnull(comm,0))*12 as yearsal from emp;ifnull() 空处理函数?
ifnull(可能为NULL的数据,被当做什么处理) : 属于单行处理函数。
oracle:
使用nvl函数可以将null进行替换
group by
记住一个规则:当一条语句中有group by的话,select后面只能跟分组函数和参与分组的字段。
distinct
1、关于查询结果集的去重?
mysql> select distinct job from emp; // distinct关键字去除重复记录。
mysql> select ename,distinct job from emp;
以上的sql语句是错误的。
记住:distinct只能出现在所有字段的最前面。
案例:统计岗位的数量?
select count(distinct job) from emp;
format
column name format a15;
只有Oracle中有用
笛卡儿积
笛卡尔积现象:当两张表进行连接查询的时候,没有任何条件进行限制,最终的查询结果条数是两张表记录条数的乘积。
多表连接查询
根据表的连接方式来划分,包括:
内连接:
等值连接
非等值连接
自连接
外连接:
左外连接(左连接)
右外连接(右连接)
全连接
内连接之非等值连接:最大的特点是:连接条件中的关系是非等量关系
select
e.ename,e.sal,s.grade
from
emp e
join
salgrade s
on
e.sal between s.losal and s.hisal;
外连接:
当副表中的数据没有和主表中的数据匹配上,副表自动模拟出NULL与之匹配。
外连接最重要的特点是:主表的数据无条件的全部查询出来。
全连接:
全外连接,即无论on中的条件满不满足,都保留所有表所有数据
由于mysql不支持全外连接,所以此条语句只能在其他数据库中执行
select s.name,t.name from student s full outer join teacher t on s.tId = t.id;
子查询
案例:找出高于平均薪资的员工信息。
select * from emp where sal > avg(sal); //错误的写法,where后面不能直接使用分组函数。正确写法:select * from emp where sal > (select avg(sal) from emp);
案例:找出每个部门平均薪水的等级
第一步:找出每个部门平均薪水(按照部门编号分组,求sal的平均值)
select deptno,avg(sal) as avgsal from emp group by deptno;第二步:将以上的查询结果当做临时表t,让t表和salgrade s表连接,条件是:t.avgsal between s.losal and s.hisal
操作结果集
Union,对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序;
Union All,对两个结果集进行并集操作,包括重复行,不进行排序;
Intersect,对两个结果集进行交集操作,不包括重复行,同时进行默认规则的排序;
Minus,对两个结果集进行差操作,不包括重复行,同时进行默认规则的排序。
可以在最后一个结果集中指定Order by子句改变排序方式。
分页查询(five stars)
mysql:
limit是mysql特有的,其他数据库中没有,不通用。(Oracle中有一个相同的机制,叫做rownum)
limit取结果集中的部分数据,这是它的作用。
语法机制:
limit startIndex, length
startIndex表示起始位置,默认从0开始,0表示第一条数据。
length表示取几个案例:取出工资前5名的员工(思路:降序取前5个) select ename,sal from emp order by sal desc; 取前5个: select ename,sal from emp order by sal desc limit 0, 5; select ename,sal from emp order by sal desc limit 5;
limit是sql语句最后执行的一个环节
案例:找出工资排名在第4到第9名的员工?
select ename,sal from emp order by sal desc limit 3,6;
通用的标准分页sql
公式:
假如要显示的页数是page,每页显示的条目数为size
select *
from emp
limit (page-1)*size,size;
oracle:
Oracle中,有一个特殊的关键字rownum,被称为:伪列。
rownum只有Oracle数据中才有。
rownum (伪列),就像表中的列一样,但是在表中并不存在。
伪列并不能像表中真实的列一样随便操作,伪列只能用于查询
select rownum,last_name from s_emp;
伪列,可以根据查询结果的条数,自动生成,并且一定是从1开始连续不断的数字
伪列rownum的本质就是给查询的一行行结果标上行号
3)如果伪列用在where条件中,那么它只能有以下操作:
rownum 如果是相同的条件,那么伪列只能等于1
如果等于其他值,那么就查询不出任何结果
rownum 如果是大于的条件,那么伪列只能大于0
rownum 可以小于任何数
伪列rownum实现分页查询
给rownum起一个别名rn,然后把这个sql语句作为第二条sql语句的子查询,并且把它当做一张虚拟的表,那么这时候,这个虚拟表中的rn是可以当做普通的字段进行操作了
select t.id,t.last_name,t.dept_id from ( select rownum rn,id,last_name,dept_id from s_emp where rownum<=10 ) t where t.rn>=6;
rownum结合关键字minus完成分页
select rownum,last_name from s_emp where rownum <=7 minus select rownum,last_name from s_emp where rownum < 3;
建表
create table 表名(
字段名1 数据类型,
字段名2 数据类型,
字段名3 数据类型,
…
);
命名
对应表和列的名字:
\1. 必须是字母开头
\2. 必须是1-30个字符之间的长度
\3. 表名中只能出现字母、数字、_、#
\4. 不能和数据库中己有对象的名字重复
\5. 不能是数据库中的关键字
数据类型
mysql:
1、整型
TINYINT SMALLINT INT BIGINT2、浮点型
FLOAT(m,n)
DOUBLE(m,n)
DECIMAL(m,n)
m和n可选3、字符型
CHAR(n):n可选
VARCHAR(n):n必选
TEXT
n表示最多字符个数4、日期型
DATE TIME DATETIME TIMESTAMP
5、二进制型
BLOB 存储图片数据
6、
CLOB 存储大文本
char和varchar怎么选择?
在实际的开发中,当某个字段中的数据长度不发生改变的时候,是定长的,例如:性别、生日等都是采用char。
当一个字段的数据长度不确定,例如:简介、姓名等都是采用varchar。
oracle:
\1. char varchar varchar2 都是存储字符串
char 存储数据的长度是固定的。varchar2 存储数据的长度是可变的。
char 效率比 varchar2效率高。 varchar是数据库标准类型,varchar2类型是oracle数据库中特有的
varchar2不能存空字符串,可以存null。varchar可以存空字符串
Oracle建议使用VARCHAR2
\2. number(p,s)
p 表示最大位数(整数位+小数位), s表示保留的小数位(四舍五入),也可以为负数。
例如,number(5,2)
存进去123.456,取出来为123.46
存进去12345.456,运行报错:值大于为此列指定的允许精度
注意1,其实这时候整数位最大只能有3位,因为要留俩位给小数位
注意2,可以直接使用number,不加参数,描述没有默认没限制
\3. date
日期类型
\4. blob
存二进制对象,例如视频,音频,图片等
\5. clob
存储大文本,例如很多很多文字
约束
说明:用于限制表中字段的数据的,从而进一步保证数据表的数据是一致的、准确的、可靠的!
NOT NULL 非空:用于限制该字段为必填项
DEFAULT 默认:用于限制该字段没有显式插入值,则直接显式默认值
PRIMARY KEY 主键:用于限制该字段值不能重复,设置为主键列的字段默认不能为空
一个表只能有一个主键,当然可以是组合主键 primary key(id)
主键的分类?
根据主键字段的字段数量来划分:
单一主键(推荐的,常用的。)
复合主键(多个字段联合起来添加一个主键约束)(复合主键不建议使用,因为复合主键违背三范式。)
根据主键性质来划分:
自然主键:主键值最好就是一个和业务没有任何关系的自然数。(这种方式是推荐的)
业务主键:主键值和系统的业务挂钩,例如:拿着银行卡的卡号做主键,拿着身份证号码作为主键。(不推荐用)
最好不要拿着和业务挂钩的字段作为主键。因为以后的业务一旦发生改变的时候,主键值可能也需要
随着发生变化,但有的时候没有办法变化,因为变化可能会导致主键值重复。
UNIQUE 唯一:用于限制该字段值不能重复 unique(email)
CHECK检查:用于限制该字段值必须满足指定条件
CHECK(age BETWEEN 1 AND 100)
注意Oracle数据库有check约束,但是mysql没有,目前mysql不支持该约束。
FOREIGN KEY 外键:用于限制两个表的关系,要求外键列的值必须来自于主表的关联列
要求:
①主表的关联列和从表的关联列的类型必须一致,意思一样,名称无要求
外键值可以为NULL?
外键可以为NULL。
外键字段引用其他表的某个字段的时候,被引用的字段必须是主键吗?
注意:被引用的字段不一定是主键,但至少具有unique约束。
列级约束:references t_customer(id)
表级约束:foreign key(customer_id) references t_customer(id)
表级约束和列级约束对比:
\1. 表级约束和列级约束所写的位置不一样
\2. not null约束不能用表级约束来声明
\3. 表级约束和列级约束声明语法稍有所不同
\4. 如果要声明的约束为联合主键、联合外键、联合唯一的时候,就一定要用表级约束
在创建约束的时候(行级、表级都可以),还可以给约束起一个名字,这时候就要使用关键字
constraint
constraint 关键字:
\1. constraint是约束的意思
\2. 建表的时候可以给约束起一个名字,这个名字起的规律一般会是:表名_列名_约束类型
\3. 如果没有给约束起名字,那么系统也会给这个约束起一个默认的名字
\4. 将来我们可以根据之前给约束起好的名字,而找到这个约束,然后进行修改获取其他操作
delete on
on delete xxx 语句是在声明外键约束的时候使用的
on delete no action
如果在建外键的时候,不加on delete语句,默认就是 on delete no action
on delete cascade
删除成功了,同时级联(cascade)删除了,t_order表中所关联的那条数据
on delete set null
删除成功了,同时把t_order表中所关联的那条数据的外键设置为了null
create table t_order(
id number, price number,
customer_id number,
constraint order_id_pk primary key(id),
constraint order_cid_fk foreign key(customer_id) references t_customer(id) on delete set null );
主键自增
mysql提供主键值自增:(非常重要。)
create table t_user(
id int primary key auto_increment, // id字段自动维护一个自增的数字,从1开始,以1递增。
username varchar(255)
);
oracle依靠序列sequence实现主键自增
序列(Sequence),它也是一种数据库对象。
它作用主要用来帮助表去创建自动增长的主键。
序列是oracle数据库所特有的对象,其他数据库中是没有的。
创建序列的默认语法:
create sequence 序列名;
查看序列的当前值,语法:
select 序列名.currval from dual;
查看序列下一个值,语法:
select 序列名.nextval from dual;
创建好一个序列之后,不能先使用currval,因为当前还没有值,需要先使用nextval,之后才
可以使用currval
查询当前用户的序列:
select sequence_name from user_sequences;
删除序列语法:
drop sequence 序列名
使用序列产生id值:
insert into t_user(id,name,salary) values(t_user_seq.nextval,'tom',2000);
视图
视图(view),它也是一种数据库对象
视图其实就是提取一张表或者多张表的数据生成一个映射。
操作视图从而达到操作原表的效果,方便数据管理和安全操作。
视图的主要作用是隐藏表中的重要数据、代替比较长的sql语句。
存储引擎
mysql默认使用的存储引擎是InnoDB方式。
默认采用的字符集是UTF8
什么是存储引擎呢?
存储引擎这个名字只有在mysql中存在。(Oracle中有对应的机制,但是不叫做存储引擎。Oracle中没有特殊的名字,就是“表的存储方式”)
常见的存储引擎
MyISAM这种存储引擎不支持事务。
MyISAM是mysql最常用的存储引擎,但是这种引擎不是默认的。
MyISAM采用三个文件组织一张表:
xxx.frm(存储格式的文件)
xxx.MYD(存储表中数据的文件)
xxx.MYI(存储表中索引的文件)
优点:可被压缩,节省存储空间。并且可以转换为只读表,提高检索效率。
缺点:不支持事务。
InnoDB
优点:支持事务、行级锁、外键等。这种存储引擎数据的安全得到保障。
表的结构存储在xxx.frm文件中
数据存储在tablespace这样的表空间中(逻辑概念),无法被压缩,无法转换成只读。
这种InnoDB存储引擎在MySQL数据库崩溃之后提供自动恢复机制。
InnoDB支持级联删除和级联更新。
MEMORY
缺点:不支持事务。数据容易丢失。因为所有数据和都是存储在内存当中的。
优点:查询速度最快。
以前叫做HEPA引擎。
事务
事务是逻辑上的⼀组操作,要么都执⾏,要么都不执⾏。
事务最经典也经常被拿出来说例⼦就是转账了。假如⼩明要给⼩红转账1000元,这个转账会涉及到两个
关键操作就是:将⼩明的余额减少1000元,将⼩红的余额增加1000元。万⼀在这两个操作之间突然出现
错误⽐如银⾏系统崩溃,导致⼩明余额减少⽽⼩红的余额没有增加,这样就不对了。事务就是保证这两
个关键操作要么都成功,要么都要失败。
和事务相关的语句只有:DML语句。(insert delete update)
为什么?因为它们这三个语句都是和数据库表当中的“数据”相关的。
事务的存在是为了保证数据的完整性,安全性。
事务包括四大特性:ACID
完成,要么完全不起作⽤;
相同的;
之间数据库是独⽴的;
库发⽣故障也不应该对其有任何影响。
索引
1、什么是索引?有什么用?
索引就相当于一本书的目录,通过目录可以快速的找到对应的资源。
在数据库方面,查询一张表的时候有两种检索方式:
第一种方式:全表扫描
第二种方式:根据索引检索(效率很高)
索引为什么可以提高检索效率呢?
其实最根本的原理是缩小了扫描的范围。
索引虽然可以提高检索效率,但是不能随意的添加索引,因为索引也是数据库当中
的对象,也需要数据库不断的维护。是有维护成本的。比如,表中的数据经常被修改
这样就不适合添加索引,因为数据一旦修改,索引需要重新排序,进行维护。
添加索引是给某一个字段,或者说某些字段添加索引。
select ename,sal from emp where ename = 'SMITH';
当ename字段上没有添加索引的时候,以上sql语句会进行全表扫描,扫描ename字段中所有的值。
当ename字段上添加索引的时候,以上sql语句会根据索引扫描,快速定位。
2、怎么创建索引对象?怎么删除索引对象?
创建索引对象:
create index 索引名称 on 表名(字段名);
删除索引对象:
drop index 索引名称 on 表名;
3、什么时候考虑给字段添加索引?(满足什么条件)
4、注意:主键和具有unique约束的字段自动会添加索引。
根据主键查询效率更高,尽量根据主键查询。
5、查看sql语句的执行计划:
mysql> explain select ename,sal from emp where sal = 5000;
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | emp | ALL | NULL | NULL | NULL | NULL | 14 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
给薪资sal字段添加索引:
create index emp_sal_index on emp(sal);
mysql> explain select ename,sal from emp where sal = 5000;
+----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+
| 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 |
+----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+
6、索引的实现原理:
7、 B + Tree
通过B Tree缩小扫描范围,底层索引进行了排序,分区,索引会携带数据在表中的“物理地址”,
最终通过索引检索到数据之后,获取到关联的物理地址,通过物理地址定位表中的数据,效率
是最高的。
select ename from emp where ename = ‘SMITH’;
通过索引转换为:
select ename from emp where 物理地址 = 0x3;
8、索引的分类
单一索引:给某个字段添加索引
复合索引:给多个字段联合起来添加一个索引
主键索引:主键上会自动添加索引
唯一索引:有unique 约束的字段会自动添加索引
…
9、索引什么时候失效
对于创建的多列索引(复合索引),不是使用的第一部分就不会使用索引
alter table student add index my_index(name, age) // name左边的列, age 右边的列
select * from student where name = 'aaa' // 会用到索引
select * from student where age = 18 // 不会使用索引
select ename from emp where ename like ‘%A%’;
模糊查询的时候,第一个通配符使用的是%,这个时候索引是失效的
如果条件中有 or, 有条件没有使用索引,即使其中有条件带索引也不会使用,换言之, 就是要求使用的所有字段,都必须单独使用时能使用索引。
如果列类型是字符串,那么一定要在条件中使用引号引用起来,否则不使用索引。
如果mysql认为全表扫面要比使用索引快,则不使用索引。
如:表里只有一条数据。
10、数据库设计三范式
什么是设计范式?
设计表的依据。按照这个三范式设计的表不会出现数据冗余。
第一范式:表中的每一个字段都是原子性不可再分的
第二范式:在第一范式的基础之上,所有的非主键字段完全依赖主键,不能产生部分依赖
第三范式:在第二范式的基础之水,所有的非主键字段直接依赖主键,不能产生传递依赖
提醒:在实际的开发中,以满足客户的需求为主,有的时候会拿冗余换执行速度。