数据库

SQL语言分为:

  • DQL(数据查询语言)   

  • DML(数据操作语言)   

  • DDL(数据定义语言)   

  • DCL(数据控制语言)

 

DQL数据查询语言

每个sql语句都应该有 “;”    一个sql语句是从from开始的,可以将from看成for循环  

大部分数据库都是不区分大小写的

-- 查询整个表

select * from 表名;(不建议这样写,效率低)

 

--查询属性1 属性2(整列)

select 属性1,属性2 from 表名;

 

--输出公司的职工工资(comm+sal),oracle内部方法nvl(字段,value):将任何字段为空的值 修改为value

select empno,sal+nvl(comm,0) from emp;

 

--nvl2(字段,val1,val2) 方法:如果字段是空 返回val2,如果字段不是空,返回val1

select ename,sal(comm,comm,0) from emp;  // 如果comm是空,返回0  如果comm不是空 返回comm本身

select empno,ename,job(job,job,'没有职位') from emp; 

 

-- decode  类似于 switch..case...

select ename,decode(job,'CLERK','职员',‘SALESMAN’,‘销售’,‘MANAGER’,'经理') from emp; //输出员工职位 职位是CLERK的输出职员...

 

--修改字段名(as),起别名

  • select empno,sal+nvl(comm,0) as month_sal from emp;
  • select empno,sal+nvl(comm,0) month_sal from emp;
  • select empno no,empname name from emp

 

-- 给表定 对象

select e.empno from emp e;(e相当于emp表的一个对象)

 

--排序(按照年薪排序)(order by 优先级最低,通常状况下写在语句末尾,并且最后执行)

  • select empno,ename,((sal)+nvl(comm,0))*15 as year_sal from emp order by year_sal asc;
  • (asc 升序  desc 降序)

 

-- 连接运算符 将各个字段的内容连接到一起

select empno||ename from emp;

 

-- 查询公司职位,并去除重复的职位,当同时修饰多个字段时,完全重复的才会消除(必须名字和职位都相同才去除)

  • select distinct job from emp;
  • select distinct job ename from emp;

 

条件查询语句

在数据库中用于判断值是否相等 用 = ;判断值是否不等, 用 !=  ;部分数据库不支持 !=     通用的不等于:<>

 

-- 查询出部门编号是10的员工编号 和 姓名

select empno,ename from emp where depno=10;

 

-- 查询姓名为Smith的员工编号和姓名,oracle下默认字符串是单引号,并且不能使用双引号;但是部分其他数据库可以

--oracle 关键字、字段 都不区分大小写;但是数据值区分大小写

select empno,ename from emp where ename='Smith';

 

--字符相关的函数:initcap(String):首字母大写

select empno,ename from emp where initcap(ename)='Smith';将ename字段的值转换为大写

--upper(string)  全大写

select empno,ename from emp where upper(ename)='SMITH';

--lower(string) 全小写

select empno,ename from emp where lower(ename)='smith'

 

--查询入职日期是1981/9/28的员工编号、姓名和入职日期

-- 修改日期格式,可以使用to_char() 函数将 日期转换为字符串,类似于

select empno,ename,hiredata from emp where to_char(hiredata,'yyyy-MM-dd')='1981-09-28'

 

其他运算符

 

-- 查询 出工资在 1000 到1500 之间的员工信息  and类似于Java的&&运算符,但是oracle不支持&&,部分其他数据库支持

select * from emp where sal >=1000 and sal<= 1500;

-- 类似于逻辑运算符的关键字: between...and  在...之间

select * from emp where sal between 1000 and 1500;

-- or 在oracle中想要表达满足其中一个条件的情况时,使用or,类似于Java的 ||

select * from emp where sal < 1000 or sal >1500;

-- not between..and...

select * from emp wher sal not between 1000 and 1500;

-- 可以通过in关键字 取一个区间内容,in效率极低,需要优化:工资为1200或者1500或者1600或者2500

select * from emp where sal in(1200,1500,1600,2500);

-- in也可以取in的反区间  not in:工资不为1200或者1500或者1600或者2500

select * from emp where sal not in(1200,1500,1600,2500);

 

--奖金为空的员工信息

select * from emp where comm is null;

null的特性:

  1. 任何与null做运算的表达式结果都是null
  2. 不可以使用 = 或者 != 做条件判断,只能用is或is not 做条件判断
  3. null排序时为最大,代表正无穷;在部分其他数据库中代表负无穷
  4. 被多行函数/组函数 忽略

 

多行函数 组函数

--查询出公司当前员工数  count()

select count(empno) from emp;

-- 查询出公司当前的总工资和  sum()

select sum(sal) from emp;

-- 查询出公司当前的工资水平 avg()

select sum(sal)/count(empno) from emp;

select avg(sal) from emp;

-- 查询出公司最高工资 max()

select max(sal) from emp

-- 查询出最低工资 min()

select min(sal) from emp

-- 查询公司的平均奖金

select sum(comm)/count(empno) from emp;

select avg(nvl(comm,0)) from emp;

--求公司的职位种类

select count(distinct job) from emp;

 

group by 分组查询

-- 求公司各部门的平均工资

select avg(sal) from emp group by deptno;

--求公司各职位的最高工资、最低工资

select max(sal),min(sal) from emp group by job;

--求公司各职位的工资总和

select sum(sal) from emp group by job;

求公司各部门人数

select deptno,count(empno) from emp group by deptno;

 

分组条件查询

注意:

  • 1. group by 之后不允许进行where操作 
  • 2.where语句先执行,则在where语句中不可以使用之前的组函数生成的别名 
  • 3.where 语句后不可以使用分组函数
  • 4.having 语句后追加的组函数 不可以使用别名
  • 5.having 语句不可以使用之前的组函数生成的别名
  • 6.group by 后的条件查询语句 必须使用having进行判断,不能使用where 功能一致,但是原理不同

求平均工资大于2000的部门

select depno,avg(sal) avg_sal from emp group by depno having avg(sal) >2000;

求部门人数大于5的编号和人数

select depno,count(empno) as count from emp group by depno having count(empno)>5;

 

-- 模糊查询 like,需要匹配相应的通配符

-- 每一个_代表一个字符

-- 名字是Sx的员工信息

select * from emp where name like 'S_';

-- % 代表任意字符:

-- 名字中有s的员工信息

select * from emp where name like '%s%';

 

-- dual 虚表,在数据库中用于存储基本字符 运算符 基本函数的表 更多的时间用于联系使用

-- 字符函数 

-- initcap(char) 首字母大写

-- upper(char)  全部大写

-- lower(char)  全部小写 

-- 使用dual显示hello world

  1. -- select 'world' from dual;
  2. -- select initcap('world') from dual;
  3. -- select upper('world') from dual;
  4. -- select lower('world') from dual;

 

-- ltrim(char,set) 左裁剪  显示 world

select ltrim('hello world','hello') from dual;  

-- rtirm 右裁剪  显示hello 

select rtrim('hello world','world') from dual;

-- translate 转换 第一个参数是被修改的字符串  第二个是字符集合 第三个是对应字符集要转换的值

select translate('world','world',‘12345’)  输出12345

--replace 替换 第一个参数是被修改的字符串 第二个是被修改的字符集合 第三个是要修改成为的值

select replace('hello world','hello','你好')  输出你好world

-- instr 查找

select instr(‘hello world’,‘d’)from dual; //输出11

-- substr 子字符串

select substr('hello world',5,11)  from dual;  //输出 world

-- concat 连接字符串:输出 hello world

select concat('hello','world') from dual;

select 'hello' || 'world' from dual;

 

数值函数

-- abs(number) 绝对值

-- floor(number) 向下取整

--round(number) 四舍五入

-- ceil(number) 向上取整

-- sin(number) 正弦   cos(number) 余弦  tan(number) 正切

-- power(number,n) number的n次方

-- sqrt(number) 开方

-- mod(number,n) 求余数

-- sign(number) 求符号

-- trunc(number,n) 截断

select trunc(10.99999999,2) from dual;  显示10.99

 

日期函数  to_char()   to_date()

  • to_date 如果将一个字符串转换为date类型,则必须说明转换格式 否则语法错误
  • 如果是一个date类型,继续使用to_date 会将date默认转换为与sysdate同种类型的date

-- 返回当前日期

select sysdate from dual;

select to_char(sysdate,'yyyy-MM--dd hh:mi:ss') from dual;

select to_date('1992-02-18','yyyy-mm-dd') from dual;(将一个字符串转换为data类型)

-- 查询当前公司员工的编号和工作年限

select empno,ename,ceil(sysdate - to_date(hiredate))/365) work_year from emp;

select empno,ename,ceil((sysdate-hiredate)/365) work_year from emp;

-- 返回两个日期相隔的月数

select months_between(sysdate,hiredate) workyear from emp;

-- 返回 把月份数 添加到指定日期上

select add_months(sysdate,1) from emp;  //系统当前日期加上一个月

-- next_day 返回指定日期对应后的新的日期

select next_day(sysdate,'星期一') from dual;  //显示当前日期的之后的第一个星期一的日期

-- last_day 返回指定日期所在月的最后一天的日期

select last_day(sysdate) from dual;

-- round 指定日期,按照某种方式进行四舍五入

select round(sysdate,'year') from dual;

-- trunc 按照某种方式 进行截断日期

select trunc(to_date('2017-05-25  11:59:59' , 'yyyy-mm-dd hh24:mi:si') , 'day') from dual;  只显示 2017/05/21

 

 

--查询出各职位的最高工资  列出2000以上的并按照从多到少的顺序排序 并排除没有职位的情况

select  job,max(sal) as max_sal from emp where job is not null group by job having max(sal) >2000 order by max_sal desc;

SQL语句的执行顺序:

  • 1.执行from语句
  • 2.执行where 语句
  • 3.执行group by 语句
  • 4.执行having语句
  • 5.执行select 
  • 6 执行order by

 

 

DML(数据操作语言)   

数据库的本质是文件管理系统   ——增、删、改、查的实现

 

-- insert into语句

常见的插入方式有两种:

1.普通插入:insert into emp(1002,'Mike','经理',1001,to_date('2008-09-29','yyyy-mmm-dd',20000,4000,null);

2.对应插入:insert into emp(empno,ename) values(1003,'Sonia');

 

--复制表内容并再插入到原表

insert into emp select * from emp;

-- 复制A表内容再插入到B表中  注:复制表的数据时 不可以添加as关键字

insert into B select * from A;

--复制一个表的所有内容 到一个新表中  注:复制表时 必须添加as关键字 此处不可略

create table emp_test as select * from emp;

 

-- 删除  delete from

--删除整个表

delete from emp;

--清空表 有更快的方式,而且没有回滚撤销

truncate table emp;

 

--条件删除语句

delete from emp where empno=0;

-- 删除所有工资是空的员工

delete from emp where sal is null;

--删除名字中带有L的员工

delete from emp where ename like '&L%';

 

-- 修改 update

--所有人修改名为 a

update emp set ename='a';

 

--修改表内多列数据

update emp set ename = 'a' , job = 'xicesuo',sal = 1000;

 

--条件修改语句

update emp set ename = 'zz'  where comm = 0;

--修改所有工资小于2000的员工 将当前工资提高500 奖金设置为 2000

update emp set sal = sal+500,comm=2000 where sal<2000;

 

子查询语句

-- 查询谁比琼斯的工资高

select ename,sal from emp where sal > (select sal from emp where ename = 'JONES')

-- 查询职务和SCOTT相同,比SCOTT雇佣时间早的员工信息

select * from emp where job = (select job from emp where ename = 'SCOTT') and hiredate < (select hirdate from emp where ename = 'SCOTT')

-- 查询工资比SCOTT 高 或者雇佣比他早的雇员编号和名字

select empno,ename from emp where sal > (select sal from emp where ename = 'SCOTT')  or hiredate < (select hirdate from emp where ename = 'SCOTT')

-- 如果存在多个SCOTT ???

-- 多行子查询  any  all 

select * from emp where sal > all (select  sal from emp where ename = 'SCOTT') ;  比所有SCOTT 工资都高

select * from emp where sal > any(select sal from emp where ename = 'SCOTT')

-- 查询职务和其中一个SCOTT 相同 比所有SCOTT 雇佣时间早的员工信息

select * from emp where job = any(select job from emp where ename = 'SCOTT')  and hiredata < all(select hiredata from emp where ename = 'SCOTT')

 

关联子查询  当子查询的值依赖于主查询的值 必须使用关联子查询

-- 查询出比自身部门的平均工资高的姓名、编号和工资

select ename,empno,sal from emp e1 where sal > (select avg(sal) from emp e2 where e1.deptno = e2.deptno)

-- 查询出 各职业最高工资的员工编号 姓名

select empno,ename from emp e1 where sal = (select max(sal) from emp e2 where e1.job = e2.job);

 

--exists 关键字

  1. -- exists 使用在where语句之后,不添加任何列名,直接追加子查询
  2. -- exists 关键字不在乎某一列的数据,只在乎该数据是否存在于子查询中,存在返回真,不存在返回假;所以where与exists之间不需要列名,又由于主查询没有选择列名 那么子查询也不需要返回一个列的数据,通常情况下 exists的子查询就写成select 1 
  3. -- select 1 查询一个常量,节省内存,减少内存占用量

-- 查询部门 20 中职务同部门10的雇员 一样的员工信息

select * from emp where deptno = 20 and job in (select job from emp where deptno = 10);

select * from emp e1 where deptno = 20 and exists (select 1 from emp e2 where deptno=10 and e1.job = e2.job )

 

多表关联查询

92版(只支持Oracle)  99版(通用)

-- 92版多表查询

--等值连接

-- 查询员工的姓名、编号、工作地点

select empno,ename,loc from emp,dept where emp.deptno = dept.deptno;

--查询员工的编号、姓名、工作地点和部门编号

select e.empno , e.ename , d.deptno , d.loc  from emp e , dept d where e.deptno = d.deptno;

 

-- 非等值连接

-- 查询员工的工资等级

select empno,ename,sal,grade from emp,salgrade where sal >= losal and sal <=hisal;

select empno,ename,sal,grade from emp,salgrade where sal between losal and hisal ;

 

-- 外连接

  • 1.左外连接
  • 2.右外连接
  • 3.全外连接(92版没有全外连接)

-- 查询所有员工的编号、姓名和工作地点 把没有部门的员工也显示出来

-- 等值连接无法显示 值为空的数据

select empno,ename,loc from emp,dept where emp.deptno = dept.deptno; // 显示不出来 没有部门的员工

1.左外连接 以等号为分隔符,左外连接写在 右侧参数的后面

select empno,ename,loc from emp e,dept d where e.deptno = d.deptno(+);

2.右外连接  以等号为分隔符,右外连接写在 左侧参数的后面

select empno,ename,loc from emp e , dept d where e.deptno(+) = d.depno;

 

-- 查询所有员工的编号、姓名和工作地点 把没有员工的部门也显示出来

1.左外连接

select empno,ename,loc from emp,dept where dept.deptno = emp.deptno(+);

2.右外连接  

select empno,ename,loc from emp e , dept d where e.deptno(+) = d.depno;

 

 

-- 99版多表关联查询

-- 交叉连接 结果是笛卡儿积

select * from emp cross join dept;

-- 自然连接 natural join 类似于等值连接

select * from emp natural join dept;

-- using 语句  表示使用deptno作为等值连接的判断依据

select * from emp join dept using(deptno);

-- on语句  可是是等值的 也可以是不等值的

select * from emp join dept on emp.deptno = dept.deptno;

-- 查询出公司的所有员工编号、姓名、工资、工作地点、工资等级

select empno,ename,sal,loc,salgrade from emp e join dept d on e.deptno = d.deptno join salgrade s on e.sal between s.losal and s.hisal ;

 

-- 外连接

1.左外连接

2.右外连接

3.全外连接

-- 查询出所有员工的信息,没有部门的员工信息也显示出来

1.左外连接 以join为分割线,可以在join前添加关键字 left/right   left表示join左侧的表的数据全部显示  right表示右侧表的所有数据都显示

select * from emp left join dept on emp.deptno = dept.deptno;

2.右外连接  显示的是没有员工的部门

select * from emp right join dept on emp.deptno = dept.deptno;

3.全外连接 full join表示  获取两个表内的所有数据

select * from emp full join dept on emp.deptno = dept.deptno;

 

--自连接

-- 查询出 员工编号和姓名 与 其上司的员工编号、姓名

select e1.empno , e1.ename , e2.empno , e2.ename from emp e1 join emp e2 on e1.mgr = e2.empno;

 

--- 视图

select * from (select empno.ename from emp) e;

 

-- 给scott用户授权,可以创建视图

grant create view to scott;

 

-- 创建一个视图

create or replace view emp_view as (select empno,ename from emp) with read only;

 

-- 查看视图

select * from emp_view;

 

--如果一个视图设置为了只读,则不可以进行DML操作,通常情况下视图都是只读的

-- 如果一定要删除,则可以删除整个视图

drop view emp_view;

--同理于table 也可以删除

drop table emp;

 

-- 视图更多使用在 SQL 语句中,实现复杂的功能

-- 将员工工资改为所在部门平均工资+1000

update emp e1 set e1.sal  = (select avg(sal) from emp e2 where e1.deptno = e2.deptno) + 1000;

-- 删除重复部门,只留下一项

-- 思路:1.按照部门名称分组,求数量大于1的 表示该部门存在重复

              2.获取重复部门名称

              3.查找所有与该名称重复的数据

              4.删除 除去最小编号的其他 与重复部门名称相同的 数据

视图不可以做DML操作

delete from dept where deptno != (select min(deptno) min_no from dept where dname in (select dname from (select dname,count(*) count_name from dept group by dname) d where count_name>1) group by dname) and dname =(select dname from (select dname,count(*) count_name from dept group by dname) where count_name > 1)

 

-- 更新员工工资为他的主管的工资、奖金

--思路:1.查询出每个员工对应主管的工资

             2.更新所有员工的工资

            3.查询出每个员工对应主管的奖金

            4.更新所有员工的奖金

update emp e set sal = (select sal from (select distinct e1.empno,e1.ename,e1.sal,e1.comm from emp e1 join emp e2 on e1.empno = e2.mgr) where e.mgr = empno), comm = (select comm from (select distinct e1.empno,e1.ename,e1.sal,e1.comm from emp e1 join emp e2 on e1.empno = e2.mgr) where e.mgr = empno) where e.mgr is not null;

 

oracle基本数据类型

字符串类 

  • 1)char 定长字符串 默认长度是1
  • 2)varchar2 变长字符串 必须提供最大长度

数值类  Number

  • 1)number 可以是整数,也可以是浮点数

日期类型 

  • 1)date 日期格式,可以显示yyyy-mm-dd hh:mis:ss 格式的日期类型
  • 2)timestamp 格式同上,但是可以包含小数点位的秒 最多包含9位小数

 

创建数据库表

create table 表名(列名 类型,列名1 类型1......)

--建立一张用来存储学生信息的表

create table student(

sno number,

sname varchar2(20),

sex char,

age number,

enterdate date,

classno number,

email varchar2(50)

math number(4,1),  一共四位,一位是小数

english number(3,1)

);

 

--删除一张表 包括表本身都被删除

drop table student;

 

-- 修改表

-- alter table 表名 action 

--添加列

alter table student add sex char(1);

--修改列

alter table student modify (sex varchar(20));

--删除列

alter table student drop column sex;

-- 修改列名

alter table student rename column sname to name;

 

--约束

--常用约束:

  • 1.主键 primary key 表示非空且唯一,并追加一个索引,提高查询效率,降低插入效率
  • 2.非空 not null
  • 3.唯一 unique
  • 4.检查 check
  • 5.外键 foreign key 表示关联一个父列 如果该列没有值 则不允许插入 如果本身存有父列的值 则父列不允许删除

-- 存有约束的student表

create table student(

sno number unique not null,

sname varchar2(20) not null,

pwd varchar2(100) not null,

score number(4,1) check(score <= 100 and score >=0)

);

-- 删除约束

alter table 表名 drop constraints 约束名;

 

--学生表 编号、姓名、分数、班级编号

--班级表 编号、教室、辅导员名、教师名

 create table student(

sno number primary key,

sname varchar2(20),

score number,

clazzno number ,

foreign key(clazzno) references clazz(clazzno)

);

 

create table clazz(

clazzno number primary key,

clazzroom number,

assistant varchar2(20),

tname varchar2(20)

)

 

-- constraints 的特点::

  1. 提高数据库的安全性,降低数据的错误率
  2. 降低添加、删除、修改效率  如果是一个添加删除修改频率比较频繁的数据库,尽量不要添加过多的约束
  3. 通常情况下,只添加主键和外键约束

 约束的添加方式有三种:

  • 1.在建表语句时,直接在列名之后
  • 2.在建表语句的末尾,添加constraints关键字, 约束名 列名 约束关键字
  • 3.创建完毕表后,使用alter table 表名 constraints 关键字 约束名 约束关键字(列名)
  • 通常情况下使用2,3两种方式 添加约束,方便删除和修改

第二种方式:

create table t_student(

sno number,

sname varchar2(20) not null,

score number(4,1),

constraints PK_SNO primary key(sno),

constraints NOTNULL_SNAME not null(sname),

constraints CHECK_SCORE check(score<=100 and score >= 0)

);

 

第三种方式:

-- 添加主键约束

alter table t_student add constraints PK_SNO primary key(sno);

--添加检查约束

alter table t_student add constraints CHECK_SCORE check(score<=100 and scor >= 0);

-- 删除主键约束

alter table t_student drop contraints PK_SNO;

--删除检查约束

alter table t_student drop constraints CHECK_SCORE;

 

-- DML操作数据库用户

--创建一个用户

create user bjsxt identified by bjsxt;

-- 给一个用户授权

-- 常见用户权限:

  1. connect 临时用户
  2. resource 普通用户
  3. dba管理员用户

grant connect,resource to bjsxt;

--取消一个用户的权限

revoke resource from bjsxt;

--删除一个用户

drop user bjsxt;

 

 

序列

-- 需要插入学生数据,但是需要学生编号是自动生成的

-- 创建一个序列

create sequence stu_seq;

-- 删除一个序列

drop sequence stu_seq;

-- 插入数据时 使用stu_seq进行插入 stu_seq.nextval

insert into student values (stu_seq.nextval,'a',10,10);

-- 可以在创建序列时,提供参数

create sequence stu_seq1 start with 10000 increment by 1 nocache; (nocache表示没有缓存区)

--使用stu_seq1插入数据

insert into student values (stu_seq1.nextval,'b',10,10);

 

--事务 TCL语句

在不同的使用环境下会存在自动保存数据 或者 自动撤销数据 的情况

实际上是事务的保存或撤销

  1. pl/sql 按照自动保存机制
  2. sqlplus 按照自动撤销机制
  3. java 按照自动保存机制
  4. 也可以手动保存或撤销

-- 保存

commit;

--撤销

rollback;

-- 自动保存

set autocommit on;

 

-- index索引

  1. 为了提供查询效率而存在于数据表中的 类似目录的内容 叫做索引
  2. 最常见的索引叫做主键索引 主键约束即是约束 也是索引
  3. 索引可以提高 > >= = < <= <> in between ..and 关键字的查询效率
  4. 当数据量提高时,会降低插入、删除、修改的效率

 

-- 创建一个索引

create index stu_name_index on student(sname desc);

create index stu_score_index on student(score desc);

 

-- 索引不需要手动使用 在使用查询语句时 自动触发

select score from student;

 

-- 删除索引

drop index stu_name_index;

drop index stu_score_index;

 

 

-- 分页ROWID ROWNUM

-- 使用rowid rownum 时,不推荐使用* ,在部分数据库中报错

-- rowid 指的是在硬盘空间地址 在存储数据后自动生成,可以作为条件查询数据

 

-- rownum代表每一行数据对应的行号  rownum不可以使用> 也不可以使用between..and 也不可以使用= 只能使用<比较数据

-- 显示公司工资前五名的员工心思

select * from (select emp.* from emp order by sal desc)  where rownum < 6;

-- 显示公司工资第7名到第10名的员工心思

select * from (select rownum r,e.* from (select emp.* from emp order by sal desc) e) where r between 7 and 10;

 

 

三大范式

第一范式:数据库中每一列都具有原子性,不可分割

第二范式:属性完全依赖于主键 ( 多对多 )

第三范式:数据库中每一列都和主键之间相关 不能间接相关 (一对多 多对一)

◆ 第一范式(1NF):强调的是列的原子性,即列不能够再分成其他几列。 
考虑这样一个表:【联系人】(姓名,性别,电话) 
如果在实际场景中,一个联系人有家庭电话和公司电话,那么这种表结构设计就没有达到 1NF。要符合 1NF 我们只需把列(电话)拆分,即:【联系人】(姓名,性别,家庭电话,公司电话)。1NF 很好辨别,但是 2NF 和 3NF 就容易搞混淆。
◆ 第二范式(2NF):首先是 1NF,另外包含两部分内容,一是表必须有一个主键;二是没有包含在主键中的列必须完全依赖于主键,而不能只依赖于主键的一部分。 
考虑一个订单明细表:【OrderDetail】(OrderID,ProductID,UnitPrice,Discount,Quantity,ProductName)。
因为我们知道在一个订单中可以订购多种产品,所以单单一个 OrderID 是不足以成为主键的,主键应该是(OrderID,ProductID)。显而易见 Discount(折扣),Quantity(数量)完全依赖(取决)于主键(OderID,ProductID),而 UnitPrice,ProductName 只依赖于 ProductID。所以 OrderDetail 表不符合 2NF。不符合 2NF 的设计容易产生冗余数据。
可以把【OrderDetail】表拆分为【OrderDetail】(OrderID,ProductID,Discount,Quantity)和【Product】(ProductID,UnitPrice,ProductName)来消除原订单表中UnitPrice,ProductName多次重复的情况。
◆ 第三范式(3NF):首先是 2NF,另外非主键列必须直接依赖于主键,不能存在传递依赖。即不能存在:非主键列 A 依赖于非主键列 B,非主键列 B 依赖于主键的情况。
考虑一个订单表【Order】(OrderID,OrderDate,CustomerID,CustomerName,CustomerAddr,CustomerCity)主键是(OrderID)。
其中 OrderDate,CustomerID,CustomerName,CustomerAddr,CustomerCity 等非主键列都完全依赖于主键(OrderID),所以符合 2NF。不过问题是 CustomerName,CustomerAddr,CustomerCity 直接依赖的是 CustomerID(非主键列),而不是直接依赖于主键,它是通过传递才依赖于主键,所以不符合 3NF。
通过拆分【Order】为【Order】(OrderID,OrderDate,CustomerID)和【Customer】(CustomerID,CustomerName,CustomerAddr,CustomerCity)从而达到 3NF。

第二范式(2NF)和第三范式(3NF)的概念很容易混淆,区分它们的关键点在于,2NF:非主键列是否完全依赖于主键,还是依赖于主键的一部分;3NF:非主键列是直接依赖于主键,还是直接依赖于非主键列。

 

 

 

 

 

---------------------------------------------------mysql-------------------------------------

mysql 与Oracle 不同:

没有默认自带的orcl数据库

必须需要手动创建数据库 或使用 官方推荐的test数据库

选择数据库或者创建数据库

 

--登陆数据库

mysql -u root -p

 

--选择数据库

use 数据库名;

 

--创建数据库

create database sxt201;

 

--显示数据库

show database;

 

--删除数据库

drop database 数据库名

 

-- MySQL 与 Oracle 中dql 基本一致

select * from 表名;

 

-- dml基本一致

insert into 表名 values(值);

delete from 表名 where 列= 值;

update 表名 set 列名= 列值 where 列 = 值;

 

-- mysql中基本数据类型 与 oracle 不同

没有number类型,只有int double float 

没有varchar2类型 使用 char和varchar

时间类型 使用date(yyyy-mm-dd)datetime(yyyy-mm-dd hh:mm:ss) timestamp(yyyymmddhhmmss)

 

-- mysql中可以将from dual省略

所以最简单的hello world 

select 'hello world'

 

-- 事务与oracle不同

每一次事务的开始 都需要begin

之后再执行commit和rollback

 

-- mysql常用引擎 ?

 

-- mysql不支持全外连接 多表关联查询时 无法全外连接

如果一定要实现,则需要union关键字

oracle中:select * from emp e full join dept d on e.deptno = d.deptno;

mysql中:select * from emp e left join dept d on e.deptno = d.deptno union select * from emp e right join dept d on e.deptno = d.deptno;

 

-- mysql 不支持序列 如果要自增长 则需要使用一个约束 并且必须是主键约束的条件下auto_increment

alter table student add constraints stu_pk primary key(no) auto_increment;

--建表时添加

create table user (no int primary key auto_increment,name varchar(20));

 

-- mysql 不支持rowid 和rownum 无法像oracle实现分页

-- 需要使用limit关键字,添加两个参数:1.起始行的坐标 从0 开始  2.显示几条

-- 显示前五条数据

select * from student limit 0,5;

-- 显示5到10条数据

select * from student limit 5,5;

 

--日期函数有较大区别

select now();  -- 代表当前时间 yyyy-mm-dd hh:mm:ss

select curdate(); -- 代表当前日期 yyyy-mm-dd

select curtime(); -- 代表当前时间 hh:mm:ss

 

-- mysql可以使用help contents 查询帮助文档内容 所有说明和例子都在其中

 

 

 

 

 

 

 

 

 

 

-- 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值