零: 关系范式(设计数据库中 表的基本原则)
基本思想:
消除关系中的数据冗余
消除数据依赖中的不合适部分
以解决数据插入、更新、删除操作中的异常问题
1、第一范式 1NF(First Normal Form)
表中的每个属性不可再分
(不允许属性以数组、集合等方式存储)
Stu表
name age course
- - - - - - - - - - - -
Tom 23 JavaSE、Oracle 不满足1NF
结论:满足1NF的数据库设计,才是关系型数据库(最基本的范式)
2、第二范式 1NF(Seconde Normal Form)
在1NF的基础上,添加一个主键(主属性)
Stu表
id(PK) name age cid cname
1 Tom 23 101 JavaSE
改为CoreJava的话,所有的101课程都要改
2 Tom 21 102 Oracle
3 James 23 101 JavaSE
结论:可能出现数据的冗余(不够独立)(多个JavaSE)、不一致(一处改,到处都要改,容易造成不一致)
3、第三范式 3NF
在2NF的基础上,解除非主属性之间的依赖关系
Stu表(学生表)
id(PK) name age
1 Tom 23
2 Tom 21
3 James 23
Course表(课程表)
id(PK) name
101 JavaSE 解除了数据冗余,数据独立,仅存一份
102 Oracle
103 Web
sc表(学生课程关系表)(没有独立主键,只有联合主键,sid和cid的组合是唯一的)
sid cid grade
1 101 99
1 102 98
1 103 99
2 101 87
2 102 97
2 103 82
3 101 78
3 102 87
3 103 67
总结:使用第三范式 避免了数据的冗余、不一致问题
常见的数据库的设计都使用3NF
一: DBMS(数据库管理系统)
SqlServer2008 Oracle10g DB2 MySql
0:基本概念
基本思路:通过DBMS来管理DB,从而管理DB中的表(table)以及其它数据资源
DB:DataBase(数据库) 受DBMS的管理
物理结构:
*.mdf:主数据文件(MSSqlServer中)
*.ldf: 日志文件(MSSqlServer中)
逻辑结构:
管理器(DBMS)中可见的部分,可以通过sql来操作
关系型数据库
核心概念:实体关系模型 E-R Model
(数据模型、域模型)
属于数据库设计范畴,表示不同实体(表)之间的关系
借助于E-R图来表示
工具:纸和笔 E-R Win
Sybase PowerDesigner
table:表 二维表 表示关系
表名:实体名(Entity)、关系名、在数据库中区分不同的表
行: row 记录(元组)
列: column 字段(属性、域、Field)
字段名、字段数据类型、宽度、约束
1:如何操作SqlServer?
使用其管理器 - > 需要权限验证登录:默认采用Windows身份登录
- > 登录到DBMS - > 创建数据库 - > 创建表
database table
数据库的组成:
文件类型:
MDF(main data file)主数据文件,属于主文件组(只有1个)
LDF(log data file) 日志文件(可以借助日志文件,进行数据还原),不属于任何文件组
NDF 辅助数据文件(后来添加的文件)
文件组:(管理、分配数据文件)
主文件组:只有一个,Primary
次文件组
初始大小:文件一开始创建时候的大小
自动增长:
路径:实际工作中出于安全考虑,不要将MDF和LDF将在同一路径下,
数据库至少需要以下2个物理文件:
student.mdf 主数据文件 保存业务数据
student_log.ldf 日志文件 数据恢复等管理
数据库的操作:
1)分离数据库:
将某个数据库脱离管理器(DBMS)管理
注意:不能是当前正在使用的数据库
选中数据库-》右键-》任务-》分离
2)附加数据库:
将某个数据库加入到管理器(DBMS)管理
选中数据库-》右键-》附加-》添加-》选择.mdf文件
数据的完整性:数据准确性、一致性
1)实体完整性 (行完整性)行的唯一
2)域完整性 (列完整性)列的要求
3)引用完整性 (参照完整性)比如员工表的部门id要参照部门表id
实现方式:约束 constraint(保证数据库的完整性[准确性,一致性])
完整性:实体完整性 PK UK 行的唯一性
域完整性 NN UK CK default 字段的约束,列的约束
参照完整性 FK
约束也是数据库中的一种对象,一定是针对某张表的 某个字段 进行约束
约束受数据库管理,要求约束名是唯一的,表如果被删除,那约束自动解除
约束的分类: 同的数据库产品统一
PK primary key
FK foreign key references
UK unique
NN not null
CK check
default
1)主键约束 PK primary key
PK = UK + NN 唯一 且 非空
保证实体(每一行)的完整性
一张表是无法同时定义多个PK
联合主键:联合起来,唯一且非空(只能使用表级约束实现)
列级约束:约束直接定义在字段之后
create table emp(
id int constraint emp_id_pk primary key,
name varchar(30) not null,
salary float
);
表级约束:所有的字段之后,追加约束(可以实现联全主键)
create table emp1(
id int,
name varchar(30) not null,
salary float,
constraint emp1_id_pk primary key(id)
);
联合主键应用:
create table stu1(
id1 int,
id2 int,
name varchar(30),
constraint stu1_id1_id2_pk primary key(id1,id2)
);
2)唯一约束 UK unique
唯一
constraint 约束名 unique(字段)
alter table stu add constraint stu_name_uk unique(name);
3)外键约束 FK foreign key
引用完整性/参照完整性(参照的表中的字段,一定是唯一的(PK或者UK),用表级约束)
结论:通过主外键关系 实现了实体间的 1对多的关系(1(父表)———*(子表))
父表 dept部门表
子表 emp员工表
规则 父先于子存在,子先于父消失
先删子表(子表依赖于父表),再删父表
先加父表(子表依赖于父表),再加子表
只能用表级约束/创建完表在用alter add constraint添加外键约束,不能用列级约束,切记
constraint 约束名 foreign key(子表/本表 中的字段a) references 父表(字段b) 约束名:当前表_父表名_当前表中被添加FK约束的字段名_fk
———————————————————————————
dept表(父表) 1——-* emp表(子表)
id(PK) name(UK NN) id(PK) name dept_id(FK)
1 销售 101 Tom 1
2 行政 102 James 1
3 研发 103 Mary 2
———————————————————————————
use worker;
drop table emp;
drop table dept;
create table dept(
id int constraint dept_id_pk primary key,
name varchar(30) not null unique
);
create table emp(
id int primary key,
name varchar(30) not null,
salary float,
dept_id int,
constraint emp_dept_deptid_fk foreign key(dept_id) references dept(id)
);
4)非空约束 NN not null
非空
5)检查约束 CK check
6)默认值约束 default
alter table 表名 add constraint 约束名 default 默认值 for 字段;
alter table test1 add constraint test1_age_dk default 20 for age;
数据库中包含的对象:
表 table
索引 index(主要用于提高查询效率)
视图 view
共同点: create 创建 drop 删除
表 table
索引 index(主要用于提高查询效率)
聚集(聚簇)索引(只能有1个)
记录的索引顺序与数据表中数据行的物理顺序相同
create clustered index 索引名 on 表名(字段名);
drop index 表名.索引名;
非聚集(非聚簇)索引(可以有多个,实际工作中常用)
记录的索引顺序与数据表中数据行的物理顺序不相同
建立非聚集索引 没有clustered,可以针对多个字段建立非聚集索引,
常用,因为id默认是聚集索引(是不能创建多个聚集索引的,只能有1个)
create index 索引名 on 表名(字段名);
drop index 表名.索引名;
索引的底层原理:
使用数据结构:B-Tree 平衡二叉查找树
特点:查询效率很高
索引的特点和使用场合:
适合:从海量数据中查询少量结果(大海捞针),很少修改数据的情况,提高查询效率,
比如:性能 瓶颈 sql效率
数据库优化:针对字段建立索引
注意:无法删除PK默认的索引
建立索引会带来开销
1.占据表空间 空间开销
2.降低增、删、改的效率 时间开销(因为需要重新调整索引结构)
视图 view()
用途:简化sql语句,访问权限设定,本质就是保存一条sql语句,
通过视图名来代替一条sql语句,
不会占据表空间、不会提高查询效率
一般将比较复杂的sql创建视图
创建视图:
create view my_view0 as select * from myemp where salary>5000.0;
更改视图:
alter view my_view0 as select * from myemp where salary>6000.0;
通过视图,插入数据:本质基础表中插入数据
insert into my_view0 values(4, 'Tony', 9000.0);
删除视图:
drop view my_view0;
数据库中的函数:数据库提供的函数可以简化sql
1)单行函数: 一条记录 -》 一个结果
LEN(‘ABC’) 返回3,表示3个字符长度
2)多行函数:(组函数、聚集函数) 多条记录 -》 一个结果
SUM() 求总和
AVG() 求平均值
COUNT() 统计记录条数
MAX() 最大值
MIN() 最小值
组函数经常和group by子句配合使用
语法:where之后,
如果需要在分组后进一步过滤,可以使用having子句
如果不写group by,默认将所有 记录作为一组
注意:使用了组函数,就要求select之后的内容
要么也使用组函数
要么使用group by 字段
(总之必须和组相关)
2:SQL(Structured Query Language)结构化查询语言
(1)DDL 数据定义语言 定义(数据库、表)结构
create 创建
create database 数据库名 on primary(…) log on(…); 创建数据库
create table 表名(…); 创建表
create table 表名 add constraint …; 创建表中字段对应的约束
create index/view 创建索引/视图
drop 删除
drop database 数据库名;
drop table 表名;
drop index/view 删除索引/视图
alter 改变
alter index/view 改变索引/视图
alter table 表名 add constraint 约束名 primary key(字段); 添加约束(PK)
alter table 表名 add constraint 约束名 default 默认值 for 字段; 添加约束(DK)
alter table 表名 drop constraint 约束名 primary key(字段); 删除约束()
(2)DML 数据操纵语言 操纵表中的数据(一行数据,一行的无组)
DML:select DQL Query查询
增删改查CURD(Create Update Read Delete)
insert
delete
update
select DQL(数据查询语言)
[] 表示里面的内容可省略
* 表示所有列/通配符
- - 单行注释
/**/ 多行注释
insert 插入数据
insert [into] 表名 values(列值1,列值2,…所有字段值); 插入所有的列
insert [into] 表名(字段名1,字段名2,…) values(列值1,列值2,…); 插入指定的列
(不插入的列,默认是空值,null)
delete 删除数据,能删除:0、 1、 n行记录
delete from 表名; 删除所有行数据
delete from 表名 where 记录匹配条件; 删除表中的数据(记录、行)
update 修改表中的数据
update 表名 set 字段1=新值,字段2=新值,…; 修改所有行
update 表名 set 字段1=新值,字段2=新值,… 修改指定行
where 记录的匹配条件;
select 查询数据
语法结构:(可以不写from,仅限MSSQL中,Oracle必须要写)
select *,字段名,表达式,常量,函数调用
from 表1,表2,…(可多表查询)
where 查询条件(分组前的过滤条件) 可以组合(and or not)
= > >= < <= != <> between a and b in
is null is not null like % _ [] [^]
group by 字段名 根据该字段来分组
having 分组后的过滤条件
order by 字段名 排序规则
select * from 表名; 查询所有行
select后面跟的内容:
as 给查询的字段取别名(as可省略)
字段名 [as] 别名
+ 查询结果的拼接,将多个列合并成1个列显示
select之后可加常量(查询结果新增加1列,第行都显示’试用‘,新增加显示的列没有字段名)
select name,salary,'试用' from worker;
select 1+2; (仅限MSSQL中,可以这样写)
select getdate() 当前系统时间; (仅限MSSQL中,可以这样写)
select ‘试用’ as 类型; (仅限MSSQL中,可以这样写)
distinct 去除查询结果中的重复值(只能位于,selece和字段之间)
去重(排重)、排序(某些数据库版本中同时还自动排好序)
from 表1,表2...
多表查询
为什么需要多表查询?
为了满足3NF(拆表),避免了数据的冗余,不一致性,
为了形成良好的设计,进行拆表,数据分布在多张表中(合久必分),
实际开发中,需要使用一条sql,同时查找多表的数据(分久必合)
- - - 表连接(多表查询)emp(员工表) 8条记录 dept(部门表) 4条记录
select * from emp,dept; 8*4=32条记录——笛卡尔积
笛卡尔积:所有记录都会匹配一次,不合理,只有8条是合理的
去除笛卡尔积,用where过滤
-- 查询员工信息以及所在部门名称
select *
from emp e, dept d
where e.dept_id=d.id;
-- 查询员工id,name,salary以及部门名称,要求薪水大于7000.0
select e.id, e.name, e.salary, d.name
from emp e, dept d
where e.dept_id=d.id and e.salary>7000.0
给表象起别名的好处:
1.简化表名
2.区分不同表 相同字段 e.id d.id
3.提高sql效率
where:选择、过滤出需要 行(记录)
比较运算符:
= > >= < <= !> !<
!= <>(也表示不等于) ==
字段名 between a and b———[a,b]之间的值,则返回真
字段名 in(m,n,k,…) 只要出现在括号中,则返回真
字段名 like ‘匹配字符串’ 模糊查询
匹配字符串:
% 0个或多个字符(任意个字符)
_ 任意1个字符
[] 在范围内的1个字符
[^] 不在范围内的1个字符
null 空值null带来的影响
空值和任何值包括空值和空值自己比较,都返回假
is null 判断是否为空
is not null 判断是否不为空
逻辑表达式:
and 并且 逻辑与
or 或者 逻辑或
not 非 逻辑非
group by 字段名 根据该字段来分组(写在where之后)
如果不写group by,默认将所有 记录作为一组
组函数经常和group by子句配合使用
语法:where之后,
如果需要在分组后进一步过滤,可以使用having子句
如果不写group by,默认将所有 记录作为一组
-- 查询出所有员工的总薪水和平均薪水
select sum(salary) 总薪水, avg(salary) 平均薪水 from emp;
-- 查询出每个部门的总薪水和平均薪水,以及每个部门的员工人数
select dept_id, sum(salary) 总薪水, count(id) 该部门员工数, avg(salary) 平均薪水 from emp group by dept_id;
-- 求出每个部门中最高薪水和最低薪水
select dept_id, max(salary) 最高薪水, min(salary) 最低薪水 from emp
group by dept_id;
having 分组后的过滤条件
-- 求出12 部门的平均工资(分组前过滤),巧妙
select max(dept_id), avg(salary) 平均工资
from emp
where dept_id=12;
-- 求出12 部门的平均工资(分组前过滤)
select dept_id, avg(salary) 平均工资
from emp
where dept_id=12
group by dept_id;
-- 求出12 部门的平均工资(分组后过滤)
select dept_id, avg(salary) 平均工资
from emp
group by dept_id having dept_id=12;
order by 字段名 可以根据不同的字段对查询结果排序
位置: select语句的最后
本质: 在返回的查询结果后,改变结果的返回顺序
order by 字段 排序规则,…;
排序规则:
[asc] 升序,默认可不写
desc 降序
select * from myemp order by name, salary desc;——先对name按升序,相同则按salary按降序排序
sp_helpdb 查询当前DBMS中所有的数据库
select * from sys.databases; 查询当前DBMS中所有的数据库
= show databases;(MySQL中的写法)
select * from sys.tables; 查询当前数据库中所有的表
= show tables;(MySQL中的写法)
sp_help 表名; 查询表的结构
select * into 新表名 from 源表名; 复制表(整张表全部复制,内容会复制)
会根据源表的结构创建新表
同时将查询回的结果插入到新表中
select * into 新表名 from 源表名 where 条件; 复制表(表的局部复制,内容会复制)
select * into 新表名 from 源表名 where 1<>1; 复制表(表的结构的复制,内容不复制,无记录)
(3)TCL 事务控制语言 Transcation事务
事务:要么一起成功,要么一起失败的 一组原子操作
银行转账操作就是一个事务,不可分割的操作—原子操作
A账户:-5000
B账户:+5000
事务和日志有关,根据日志恢复数据
begin transaction; 开始事务(sqlserver中这么写)
… 各种sql操作
commit 提交事务,全部成功
rollback 回滚事务,全部失败
- - 单行注释
/**/ 多行注释
3:SQLServer常用的数据类型
数值类型
int 整数
float 浮点数
字符类型
char(10) 定长,固定分配10个字符空间
‘abc’ 分配10个字符空间,其余使用空白补充
== ‘abc ’
varchar(10) 可变长,最多分配10个字符空间,
‘abc’ 只分配3个字符空间,节约数据库空间
日期类型
datatime
注意:添加时,要加’’,2个单引号
4:SQL脚本
4.1创建数据库
利用SQL语句,创建一个数据库,数据库名字Lib
磁盘中的位置:D:\SQLServer\Lib
mdf文件:
初始化的大小是5W,
每次增长1,
大小没有限制
名字lib_dat
log文件:
初始化的大小是3W,
每次增长10%,
最大的容量是8W
名字lib_log
创建数据库的基本的格式:
create database 数据库名字
on primary( 数据库中主要存储文件)
log on( 数据库中日志文件)
create database Lib
on primary
(
name = lib_dat,
filename = 'C:\SQLServer\lib\libdat.mdf',
size = 5,
maxsize = unlimited,
filegrowth = 1
)
log on
(
name = lib_log,
filename = 'C:\SQLServer\lib\liblog.ldf',
size = 3,
maxsize = 10,
filegrowth = 10%
)
4.2创建表
3种方式:
1)使用SQL语句来创建表(最常用的)
SQL语句来创建表的基本格式
use 数据库名字
CREATE TABLE 表的名字
(
字段名1(属性名/列名) 数据类型 (各种约束),
字段名2 数据类型 (各种约束),
字段名3 数据类型 (各种约束),
...
)
[GO] the
主键约束:primary key(固定的格式)
非空约束:添加数据的时候,被非空约束,所修饰的列,必须有内容 ,
not null除了主键约束以后,其他的约束,是根据需要才添加
2) 利用工具在数据库中来创建表
a)特点:方便,简单,使用极少
(大型数据库,一般要么是用专业建表工具来生成表,要么通过Sql来建表,
只有SQLServer系列数据库等才支持用工具建表)
b)通过工具来往表中添加数据
c)select * from 表名:显示当前表中所有的数据
3) 利用模板来创建表(开发中基本不用)
网友评论