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;

  • 相关阅读:
    【NOIP 2003】 加分二叉树
    【POJ 1655】 Balancing Act
    【HDU 3613】Best Reward
    【POJ 3461】 Oulipo
    【POJ 2752】 Seek the Name, Seek the Fame
    【POJ 1961】 Period
    【POJ 2406】 Power Strings
    BZOJ3028 食物(生成函数)
    BZOJ5372 PKUSC2018神仙的游戏(NTT)
    BZOJ4836 二元运算(分治FFT)
  • 原文地址:https://www.cnblogs.com/tarek/p/5590533.html
Copyright © 2011-2022 走看看