zoukankan      html  css  js  c++  java
  • Oracle笔记2-数据库设计

    数据库的设计

    软件开发的流程:
    立项->需求分析->概要设计->详细设计->实现->测试->交付->维护
    [含数据库设计]

    通过需求分析,就可以抽取出关键业务中的"实体类",这些实体类都是
    用来封装数据的,这些数据最终都是要存储到数据库中.


    数据库设计的基本流程:
    根据业务的需求找出相应的实体类,然后把这些实体类映射成数据库
    对象(表),再考虑实体的属性,也就是表格的列,最后考虑实体之间的
    关系,也就是表格之间的关系.


    数据库设计的常用工具:
    1.sybase公司,PowerDesigner,功能强大,收费
    2.ERWIN-Studio,功能比较强大,收费
    3.JUDE,日本开发的开源,免费

    E-R图(Entity-Relationship),实体关系映射图

    它的核心就是映射(mapping):
    1.实体名,映射成表名
    2.属性,映射成列名
    3.对象标示符,映射成主键约束
    4.实体关系,映射成表之间的关系(外键约束)

    映射举例:
    实体类 表
    名字 User 表名:tbl_user
    属性 id 主键:id
    属性 name 列名:name
    属性 password 列名:password


    实体类之间的关系:
    一对一 映射成外键
    一对多 映射成外键
    多对多 拆分成2个一对多,再映射成外键
    自关联 映射成外键

    注意:
    1.外键一般出现在表多的一方,映射具有方向性.
    2.实体类中没有外键的概念,数据库表中才有外键的概念.
    -----------------------------------------------------------

    数据库的三大范式,也就是数据库设计的原则:

    作用:是用来指导数据库设计人员的一种设计思想,保证数据库的设计
    是具备可拓展性,无数据的冗余,结构清晰简单明了.

    1NF:原子性,也就是说表中任何一个列都是唯一的,不可再拆分的
    如:
    R(id,name,age),此关系中name可以分为first_name和last_name,
    所以,此设计不符合1NF,应该重新设计为:
    R(id,first_name,last_name,age)


    2NF:在1NF的基础上,不存在非关键列部分依赖于关键列,也就是说
    所有的非关键列都必须完全依赖于关键列.
    如:
    R(sno,sname,cname,score)
    1 张三 数学 90
    由于以上不管是以哪一列作为关键列,都存在其他非关键列部分依赖
    于关键列,所以此设计不符合2NF,应该重新设计为:
    R1(sno,sname),存放学生信息的表
    R2(cno,cname),存放课程信息的表
    R3(sno,cno,score),存放学生与课程考试成绩的中间表


    3NF:在2NF的基础上,不存在非关键列传递函数依赖于关键列,也就是
    说,所有的非关键列都必须直接依赖于关键列
    如:
    如果A依赖于B,B依赖于C,我们就说A传递函数依赖于C

    学生考入某所大学的信息表:
    R(sno,sname,uno,uname,phone,address)
    如果以sno作为关键列,sanme,uno是直接依赖于sno,但是uname,phone,
    address这三列都是直接依赖于uno,间接依赖于sno,所以此设计不符合
    3NF,应该重新设计为:
    R1(sno,sname,uno),存放学生信息的表
    R2(uno,uname,phone,address),存放大学信息的表
    ------------------------------------------------------------

    DDL(create,drop,alter,rename to)

    创建表格分为2个步骤:
    1.定义列和数据类型
    2.添加约束


    约束(constraint)
    作用:相对于数据类型而言,用来进一步限定表中数据,使得添加到
    表中的数据都是合法有效,符合业务需求的数据,不会出现无效数据.

    Oracle中的5种约束类型:
    1.primary key PK P 含义:主键约束,非空唯一(表中最多只能含有一个主键约束)
    2.not null NN C 含义:非空
    3.unique UK U 含义:唯一
    4.check CK C 含义:自定义约束
    5.foreign key FK R 含义:外键约束(表示此列的值是引用自其它表的主键)

    注意:能够被外键所引用的列,其本身也必须是主键约束或者唯一性约束.


    创建表格的第一种方法:
    语法
    create table table_name(
    列名 数据类型 [default 默认值] [约束],
    列名 数据类型 [default 默认值] [约束],
    ...
    列名 数据类型 [default 默认值] [约束]
    );


    约束的名字:
    在创建表格时,如果不定义约束的名字,则数据库会给约束提供默认名,
    并且把这些内容存储到数据字典中

    --查询当前用户下所有的约束名
    select constraint_name from user_constraints;


    添加约束名字的语法:
    constraint 约束名 约束类型;

    约束名的命名规则:
    table_name_列名_约束类型缩写


    例如:
    --创建用户表
    create table tbl_user(
    id number(5) constraint tbl_user_id_pk primary key,
    username varchar2(25) constraint tbl_user_uname_uk unique not null,
    password varchar2(25) default '000000'
    );


    添加约束的2种方法:
    1.列级语法添加--边定义列,边添加约束

    --创建账户表
    create table tbl_account(
    id number(5) constraint tbl_acc_id_pk primary key,
    accountno varchar2(25) constraint tbl_acc_accno_uk unique not null,
    realname varchar2(25),
    password char(6) default '000000',
    balance number(10,2) constraint tbl_acc_bal_ck check(balance>=0)
    );

    2.表级语法添加--先定义列,然后再添加约束
    create table tbl_account(
    id number(5),
    accountNo varchar2(25) constraint tbl_acc_ano_nn not null,
    realName varchar2(25),
    password char(6) default '000000',
    balance number(10,2),
    constraint tbl_acc_id_pk primary key(id),
    constraint tbl_acc_ano_uk unique(accountNo),
    constraint tbl_acc_bal_ck check(balance>=0)
    );

    注意:not null约束不支持表级语法,只能采用列级语法添加!!!
    当然,也可以采用如下方法变通实现
    create table tbl_account(
    id number(5),
    accountNo varchar2(25),
    realName varchar2(25),
    password char(6) default '000000',
    balance number(10,2),
    constraint tbl_acc_id_pk primary key(id),
    constraint tbl_acc_ano_nn check(accountNo is not null),
    constraint tbl_acc_ano_uk unique(accountNo),
    constraint tbl_acc_bal_ck check(balance>=0)
    );


    --创建员工表(自关联)
    create table tbl_emp(
    id number(5),
    name varchar2(25) constraint tbl_emp_name_nn not null,
    title varchar2(25),
    salary number(10,2),
    manager_id number(5),
    constraint tbl_emp_id_pk primary key(id),
    constraint tbl_emp_title_ck check(title in('经理','办事','销售','财务')),
    constraint tbl_emp_sal_ck check(salary>1850),
    constraint tbl_emp_mgr_fk foreign key(manager_id)
    references tbl_emp(id)
    );


    补充:
    创建表格的第二种方法(根据已经存在的某张表创建一张新表格):

    --复制了某张表格的指定列,构建一张新表格(拷贝了数据)
    create table 新表格名 as select 列,列,... from 原表格;

    例如:创建一张s_emp表格中id,first_name,salary三列数据的新表
    create table new_emp as select id,first_name,salary from s_emp;


    --复制了某张表格的指定列,构建一张新表格(不拷贝数据,取表格结构)
    create table 新表格名 as select 列,列,... from 原表格
    where 恒假条件;

    例如:创建一张s_emp表格中id,first_name,salary三列的新表,不需要数据
    create table new_emp as select id,first_name,salary from s_emp
    where 1=2;

    注意:此处1=2表示恒false,则数据不会被拷贝,只能得到一张空表

    删除表格(注意约束控制):

    drop table table_name [cascade constraints];

    注意:cascade constraints表示连带约束一起删除,如果不添加,
    则如果有外键引用,则删除不成功.


    修改表格:

    --列相关
    1.添加列
    alter table 表名 add 列名 数据类型 默认值 约束;

    --给tbl_user表添加一列(age)
    alter table tbl_user add age number(3) default 18 not null;

    2.删除列
    alter table 表名 drop column 列名;

    --删除tbl_user表中的age列
    alter table tbl_user drop column age;

    3.修改列(修改列的数据类型和约束)
    alter table 表名 modify 原列名 新数据类型 新默认值 新约束;

    --修改tbl_user表中password列为char(6) 默认值'00000' 非空
    alter table tbl_user modify password char(6) default '000000' not null;

    4.修改列名
    alter table 表名 rename column 原列名 to 新列名;

    --修改tbl_user表中password列名为pwd
    alter table tbl_user rename column password to pwd;


    --约束相关
    1.添加约束
    alter table 表名 add constraint 约束名 约束类型(列名);

    注意:如果是添加非空约束,则:
    alter table 表名 add constraint 表名_列名_nn check(x is not null);

    **********************************************************************
    --删除表格
    drop table tbl_emp;

    --创建表格
    create table tbl_emp(
    id number(5),
    name varchar2(25) constraint tbl_emp_name_nn not null,
    title varchar2(25),
    salary number(10,2),
    manager_id number(5)
    );

    --添加约束
    alter table tbl_emp add constraint tbl_emp_id_pk primary key(id);
    alter table tbl_emp add constraint tbl_emp_title_ck check(title in('经理','办事','销售','财务'));
    alter table tbl_emp add constraint tbl_emp_sal_ck check(salary>1850);
    alter table tbl_emp add constraint tbl_emp_mgr_fk foreign key(manager_id)
    references tbl_emp(id);

    --初始化数据
    insert into tbl_emp values(...);
    insert into tbl_emp values(...);
    insert into tbl_emp values(...);

    --提交数据
    commit;

    **********************************************************************

    2.删除约束
    alter table 表名 drop constraint 约束名;

    3.使约束生效
    alter table 表名 enable constraint 约束名;

    4.使约束失效
    alter table 表名 disable constraint 约束名;

    ------------------------------------------------------------

    DML(insert,update,delete)

    1.插入数据
    insert into 表名(列,列,列,...) values(值,值,值...);

    //当插入的数据时与表格列一一对应的话,则列可以省略
    insert into 表名 values(值,值,值...);

    例如:
    --给tbl_user表添加一条记录
    insert into tbl_user (id,username,password) values(1,'jack','123456');
    insert into tbl_user values(2,'tom','456789');


    2.更新数据
    update 表名 set 列=新值 where 条件;

    例如:
    --修改tbl_user表中第二行记录中的用户名
    update tbl_user set username='ben' where id=2;

    --提高当前订单表中所有状态是未付款的订单价格10%
    update tbl_order set price=price*1.1 where status='unpayment';

    注意:修改操作千万要注意条件!!!


    3.删除数据
    delete 表名 where 条件;

    例如:
    --删除用户表第三行数据
    delete tbl_user where id=3;

    注意:此处不能违反约束

    ---------------------------------------------------------

    DML语句和DDL语句的不同:

    1.DML语句不会自动提交,也就是说当运行完DML语句后,数据库中
    真实的数据还没有发生变化,当前自己事务中看到的仅仅是内存
    中的情况,所以此时,另一个事务是无法看到修改结果的.

    如果要把修改后的结果同步到数据库中,则必须手动使用如下指令:

    --提交数据,把内存中的数据同步到数据库中
    commit;

    --回滚操作,撤销还没有提交的操作
    rollback [to 回滚点名字];

    --设置回滚点
    savepoint 回滚点名字;

    即:一个事务无法读取到另一个事务还没有提交的数据!!!

    注意:navicat中默认情况下DML语句也会自动提交


    2.DDL语句是自动提交的

    ---------------------------------------------------------

    数据字典

    定义:数据字典就是用来描述用户对象的对象.

    Oracle是一个用表(系统表)来维护表(用户表)的数据库系统,这里
    的系统表就是我们所说的数据字典.

    Oracle数据库定义的数据字典都遵循一定的命名规则,它内置了上
    千张表.

    命名规则:
    前缀_数据库对象+s/es

    常用的前缀:
    user
    all
    dba
    $

    常用的数据库对象:
    table,user,constraint,sequence,index,view...

    常用的数据字典:
    user_users 存放用户的信息
    user_tables 存放用户表的信息
    user_constraints 存放表中约束的信息
    user_sequences 存放序列的信息
    user_indexes 存放索引的信息
    user_views 存放视图的信息
    user_cons_columns 存放约束与列对应关系的信息


    --查看当前用户下有哪些约束
    select * from user_constraints;

    --查看当前用户下有哪些表格
    select table_name from user_tables;

    --查看TBL_EMP表中所有的约束名和约束类型
    select constraint_name,constraint_type from user_constraints
    where table_name='TBL_EMP';

    --查看当前用户(jsd1510)下所有状态为不可用的约束名字,以及该约束作用的表格名
    select constraint_name,table_name,status from user_constraints
    where status='DISABLED' and owner='JSD1510';


    注意:此处表名一定要大写!
    -------------------------------------------------------------

    DTL,数据事务语言

    事务的定义:
    就是指一组相关的SQL操作,我们所有的操作都是处在事务中的.

    注意:在数据库中,执行业务的基本单位是事务,不是以某一条SQL.
    数据库在默认情况下,事务都是打开的,也就是说它是一直
    处在事务中的,一个事务的结束,代表着下一个事务的开启.
    执行commit或者rollback指令时,会结束当前事务.

    作用:用来保证数据的平稳性和可预测性.

    例如:银行转账业务

    A帐号向B帐号转账10000
    SQL1:
    update tbl_account set balance=balance-10000 where accountNo=A帐号;

    SQL2:
    update tbl_account set balance=balance+10000 where accountNo=B帐号;

    SQL1和SQL2必须处在同一个事务中,从而保证同时成功或者同时失败.


    事务的四大特性(ACID):
    atomic,原子性,事务是不可再分割的,要么同时成功,要么同时失败
    consistency,一致性,事务一旦结束,内存中的数据和数据库中的数据是保持一致的
    isolation,隔离性,事务之间互不干扰,一个事务的结束意味着下一个事务的开启
    duration,持久性,事务一旦提交,则数据持久化到数据库中,永久保存

    在Oracle中,操作事务的命令:
    1.commit,提交事务
    把事务中所有的数据持久化到磁盘中

    2.rollback [TO 回滚点],回滚事务
    把事务中所做的操作全部取消,回到初始状态

    3.savepoint 回滚点,设置回滚点
    事务回滚时,回到的起点


    总结:
    1.目前主流的数据库都是支持事务的,而且其中Oracle支持的最好,
    2.一个事务不能读取到另一个事务还没有提交的数据.
    3.DDL语句都会自动提交事务
    4.DML语句不会自动提交事务,需要手动commit
    ---------------------------------------------------------

    多事务的并发处理机制:

    原因:多个事务同时操作一个表中的同一行数据,如果这些操作是
    修改操作的话,就会产生并发问题,如果不处理,则会造成数
    据不一致的情况.

    数据库可能产生的并发问题包括:
    1.脏读
    是指一个事务正在访问数据,并且对这个数据进行修改,而这种修改
    还没有提交到数据库中,而另一个事务也访问了这个数据,并且使用
    了这个数据.

    解决方法:一个事务在修改数据时,该数据不能被其他事务访问

    2.不可重复读
    是指一个事务多次读取同一条记录,如果此时另一个事务也访问并且
    修改了该数据,则就会出现多次读取出现数据不一致的情况,原来的
    数据变成了不可重复读取的数据

    解决方法:只有在修改事务完全提交过后才可以读取到数据

    3.幻读
    是指一个事务修改表中的多行记录,但是此时另一个事务对该表格进行
    了插入数据的操作,则第一个事务会发现表格中会出现没有被修改的行,
    就像发生了幻觉一样.

    解决方法:在一个事务提交数据之前,其他事务不能添加数据


    Oracle中采用'锁'来做并发处理:
    1.表级排它锁(X) exclusive mode
    2.表级共享锁(S) share mode
    3.表中行级排它锁(SRX) share row exclusive
    注:这三种锁是通过专门的命令来申请的

    语法:
    lock table table_name in mode;

    例如:
    --以共享锁锁表
    lock table tbl_emp in share mode;

    --以排它锁锁表
    lock table tbl_emp in exlusive mode;

    4.行级共享锁(RS) row share
    5.行级排它锁(RX) row exclusive
    注:这两种锁无需通过专门命令申请,而是通过DQL和DML来自动申请的

    注意:
    1.所有的DQL语句默认情况下都会自动申请RS锁
    2.所有的DML语句默认情况下都会自动申请RX锁,每一行记录都会唯一的RX锁
    3.在项目中,为了满足业务要求,一般select语句需要申请RX锁

    select语句通过for update来申请RX锁:
    select * from s_emp for update;
    select * from s_emp for update wait 5;//等待5秒钟
    select * from s_emp for update nowait;
    -----------------------------------------------------------

    其他数据库对象:
    序列(SEQUENCE)
    索引(INDEX)
    视图(VIEW)

    1.序列(SEQUENCE)
    对应的数据字典:user_sequences

    作用:用来产生唯一性值的数据库特殊对象

    创建序列的语法:
    create sequence 序列名
    [start with n] --表示从几开始,默认值是1
    [increment by n] --每计数一次增加多少,默认是1
    [MAXVALUE n] --序列最高峰值n
    [MINVALUE n] --序列最低峰值n
    [cache n] --提供n个预分配的序列,保存在内存中
    [cycle | nocycle] --是否循环
    [order | noorder] --有序还是无序序列

    例如:
    --给员工表创建一个序列
    create sequence tbl_emp_id start with 4;


    如何使用序列?
    nextval:取序列的下一个值(tbl_emp_id.nextval)
    currval:取序列的当前的值(tbl_emp_id.currval)

    在插入数据时使用:
    insert into tbl_emp values(tbl_emp_id.nextval,.........);

    删除序列:
    drop sequence 序列名;

    补充:MySQL
    create table tbl_user(
    id int auto increment,
    username varchar(25),
    password varchar(25)
    );
    ---------------------------------------------------------

    2.索引(INDEX)
    对应的数据字典:user_indexes

    它是一个比较重要的数据库对象,作用是可以有效的提高数据库的
    查询效率 (数据库性能优化).

    创建索引的2种方式:
    1.自动创建
    当表中的列添加了主键约束或者唯一性约束时,则系统会自动为此列
    创建唯一性的索引,索引名就是约束名.

    2.手动创建
    语法:
    create index 索引名 on 表名(列名...);

    注意:
    1.索引有自己独立的存储空间和命名空间
    2.创建索引也会相对牺牲一些数据库性能


    索引的原理:
    1.默认情况下,索引是采用BTree(二叉树)的数据结构
    2.伪列(rowid),存放的数据行记录的真正"物理地址".

    --根据物理地址查询某一行记录
    //先获取行记录的rowid
    select rowid from s_emp where id=1;//AAADXqAABAAAI16AAA

    //根据行记录rowid查找相应的记录
    select * from s_emp where rowid='AAADXqAABAAAI16AAA';


    ==>子查询
    select * from s_emp where rowid=
    (select rowid from s_emp where first_name='Carmen');


    3.索引建立的原理:
    把创建索引的列值与rowid合成一个键值对,这个键值对就是索引,
    然后把它们存放到指定的数据结构中(二叉树,位图)中,并且是独
    立的索引空间.

    4.索引查询的原理:
    当我们的查询语句中where条件的列建立了索引,则查询分为以下2步:
    a.先查索引,在句列中的值直接找到rowid
    b.根据第一步得到的rowid直接定位到相应的行记录结束查询

    5.建立索引的策略:
    a.主键列和唯一性列 适合
    b.不经常发生改变的列 适合
    c.满足以上2个条件,经常作为查询条件的列 适合
    d.重复值太多的列 不合适
    e.null值太多的列 不合适

    6.删除索引
    drop index 索引名;

    -----------------------------------------------------------

    视图(VIEW)
    对应的数据字典:user_views

    它是一个数据库对象,它的表格的一个"窗口",用来保存查询语句
    的对象,视图时依附于表的,并且他与表格共享存储空间.

    定义:本质就是一条合法的查询语句


    作用:
    1.配合权限,根据业务来做分级管理
    2.减少复杂性,增强数据的安全性


    创建视图的语法:
    create [or replace] view 视图名 as 字句;
    [with read only] -- 此视图只读
    [with check option [constraint 约束名]]

    例如:
    create view view_name as
    select id,salary from s_emp with read only;

    注意:
    操作视图必须拥有一定的权限!!!


    删除视图:
    drop view 视图名;


    视图的分类:
    关系视图,内嵌视图,对象视图,物化视图

    ----------------------------------------------------------

    补充:
    --查询当前用户可执行的主要操作
    select * from session_privs;

    --查询某个权限可执行的所有操作
    select * from DBA_SYS_PRIVS where grantee='DBA';(需要DBA)

    --查询当前用户被赋予的系统角色
    select * from SESSION_ROLES order by role;

    授予权限的两种方式:
    1.grant create any view to 用户名;
    2.grant connect,resource,dba to 用户名;


    练习:
    --创建41部门所有员工的简单视图(必须拥有操作视图的权限!)
    create view view_emp_41 as select * from s_emp where dept_id=41;

  • 相关阅读:
    P1410 子序列 (动态规划)
    P2085 最小函数值 (堆)
    [ZJOI2007]棋盘制作 (单调栈,动态规划)
    [ZJOI2005]午餐 (贪心,动态规划)
    黑匣子_NOI导刊2010提高 (对顶堆)
    [BZOJ1455] 罗马游戏 (左偏树||并查集)
    P1651 塔 (动态规划)
    两类斯特林数 (组合数学)
    从编程到工程
    失败的过程也是过程
  • 原文地址:https://www.cnblogs.com/tarek/p/5590533.html
Copyright © 2011-2022 走看看