亮书房程序员Java

Oracle 数据库 知识总结

2016-10-12  本文已影响129人  七弦桐语

Oracle 基础

一、概述

Oracle的安装

下载地址:oracle官网
卸载: 安装目录/dbhome_1/deinstall/deinstall.bat(点击运行)

二、用户与表空间

1. Sql Plus 登录

系统用户

使用系统用户登录

[username/password][@server][as sysdba|sysoper]

查看用户登录

启用scott用户

2. 表空间

表空间的概述

查看用户的表空间

alter user user_name default|temporary tablespace tablespace_name

创建修改删除表空间

  1. 创建表空间
create tablespace tablespace_name datafile 'filename.dbf' size 10m; --永久表空间
create temporary tablespace tablespace_name tempfile 'filename.dbf' size 10m;   --临时表空间
  1. 差看创建的表空间路径
desc dba_data_files;
select file_name from dba_data_files where tablespace_name = 'tablespace_nameXXX' --注意tablespace_name大写
  1. 修改表空间

修改表空间的状态

alter tablespace tablespace_name online|offline;
select status from dba_tablespaces where tablespace_name='NAME_TABLESPACE'; --查看状态
alter tablespace tablespace_name read only|read write;

修改表空间的数据文件

alter tablespace tablespace_name add datafile 'xx.dbf' size xx;
alter tablespace tablespace_name drop datafile 'filename.dbf';  --注意 不能删除创建表空间时的第一个数据文件
drop tablespace tablespace_name;    --只删除表空间
drop tablespace tablespace_name including contents;  --删除表空间和数据文件

三、表与约束

管理表

1. 数据类型

2. 基本语法

create table table_name(
    column_name datatype,...
)

添加字段

alter table table_name add column_name datatype;

更改字段数据类型

alter table table_name modify column_name datatype;

删除字段

alter table table_name drop column column_name;

修改字段名字

alter table table_name rename column column_name to new_column_name;

修改表名

alter table_name to new_table_name;

-删除表
delete语句

delete from table_name;
truncate table_name;

truncate和delete的区别?
(1)都是清空表中的数据,即删除表中的记录。
(2)truncate 的速度要比delete快。
(3)delete可以指定删除符合条件的记录
delete from test where name='35';

操作表中的数据

添加数据

insert into table_name(column1,comlumn2,...)values(value1,value2,...)

复制表数据

create table table_new as select * from table_old;

修改数据

update table_name set column1=value1,...[where conditions];

约束

非空约束

在修改表时添加非空约束

alter table table_name modity column_name datatype not null;

主键约束(也是非空约束)

查找约束

select constraint_names from user_constraints where table_name=' ';

在修改表时添加主键约束

add constraint constraint_names primary key (column_name1,...);

更改约束的名字

rename constraint old_name to new_name;

删除主键约束

disable | enable constraint constraint_names;   --禁用约束
drop constraint constraint_names;   --删除约束
drop primary key[cascade];  --cascade用于级联删除约束

外键约束

在创建表时设置外键约束(两种方式)

create table typeinfo (typeid varchar2(10) primary key , typename varchar2(30));    --主表(类型信息表)
create table userinfo (
    userid varchar2(10) primary key ,
    username varchar2(20),
    typeid_new varchar2(10) references typeinfo(typeid);
);    --从表

-------
create table userinfo_f1 (
    id varchar2(10) primary key,
    name varchar2(30),
    typeid_new varchar2(10),
    constraint fk_typeid_new foreign key(typeid_new) references typeinfo(typeid)
    on delete cascade;
)

在修改表时添加约束

create table userinfo(
    id varchar2(10) primary key,
    name varchar2(30),
    typeid_new varchar2(10);
)
alter table userinfo add constraint fk_typeid foreign key (typeid_new) 
references typeinfo(typeid);

注:

  1. 主从表中响应字段必须是同一个数据类型。
  2. 从表中外键字段的值必须来自于主表中相应字段的值,或为null值。
  3. on delete caseade是级联删除。
    删除约束
alter table table_names disable | enable constraint constraint_names;
alter table table_names drop constraint constraint_names;
select constraint_name,constraint_type,status from user_constraints where table name = "";
-- 查询约束

唯一约束

唯一约束和主键约束的不同

  1. 主键字段值必须是非空的;唯一约束允许有一个空值。
  2. 主键在一张表中只能有一个,但是唯一约束可以有多个。

在创建表时设置唯一约束

create table table_names (column_name datatype unique,...); --列级
create table table_names (
    column_name datatype,...
    constraint constraint_name unique(column_name); --表级
)

在修改表时添加唯一约束

alter table table_name add constraint constraint_names unique(column_name);

删除唯一约束

alter table table_names disable | enable constraint constraint_names;
alter table table_names drop constraint constraint_names;

检查约束

作用:表中的值更具有实际意义。

在创建时设置检查约束

create table table_names (column_name datetype check(expressions),...) --列级
eg:
    create table userinfo_c(
        id varchar2(10) primary key,
        username varchar2(20),
        salary number(5,0) check(salary>0)
    )
constraint constraint_names check(expressions) --表级

在修改表时添加检查约束

alter table table_names add constraint constraint_name check(expressions);

四、查询语句

基本查询语句

select [distinct] column_names1,... |* from table_name [where conditions];

在SQL*Plus中的设置格式

column column_names HEADING new_name;  --修改字段名称(column可以简写成COL)
column column_names format dataformat;  --设置结果显示格式
column column_names clear;  --清除之前设置的格式

给字段设置别名

select column_names AS new_name from table_names;   --AS可以省略

运算符和表达式

select id,username,salary+200 from users;  --只是查询的结果视图+200
select username from users where salary > 800 and salary <> 1200;
select * from users where not(user_name = 'aaa');

模糊查询

select * from users where user_name LIKE '_张%'; --查询第2个字是张的人的信息
select * from users where user_name LIKE '%张%'; --查询名字中含有张的人的信息

范围查询

select * from users where salary not between 800 and 1000;
select * from users where user_name not in ('a','b'); --用户名不等于a且不等于b

排序

select * from users order by id desc , dalary asc; --在id相同的情况下salary才按升序排列

case...when

select username , 
    case username when 'a' then '语文' when 'b' then '数学' else '其他' end as 科目 
from users; 
select username,case when username='aaa' then '计算机部门'
    when username='bbb' then '市场部门' else '其他部门' end as 部门
    from users;

decode

select username , decode(username,'aaa','计算机部门','bbb','市场部门','其他') as 部门
from users; 

Oracle 函数

函数的作用

函数的分类

数值函数

1. 四舍五入

ROUND(n[,m])

select round(23.4),round(23.42,1),round(23.42,-1) from dual;
-- 结果分别为23/23.4/20

2. 取整函数

CEIL(n):取整时取最大值
FLOOR(n):取整时取最小值

3. 其他函数

字符函数

大小写转换函数

获取子字符串函数

获取子字符串长度函数

字符串连接函数

select concat('a','bc') from dual;
select 'a' || 'bc' from dual;

去除子串函数

替换函数

日期函数

select next_day(sysdate,'星期一') from dual;
select extract(hour from timestamp '2016=9-1 14:34:22') from dual;

转换函数

日期转换成字符的函数

select to_char(sysdate,'YYYY-MM-DD HH24:MI:SS') from dual;

字符转换成日期的函数

数字转换成字符的函数

select to_char(12345.678,'$99,999.99') from dual;    --结果为:$12,345.678

字符转换成数字的函数

select to_number('$1,000','$9999') from dual;

Oracle 查询

分组查询

概念

分组函数作用于一组数据,并对一组函数返回一个值。

常用的分组函数

select avg(sal), sum(sal) , max(sal) ,min(sal) from emp;
select count(*) from emp;
select count(distinct empno) from emp; --去重部门数统计
select depno 部门号, wm_concat(ename) 部门中员工的姓名 from emp group by deptno;
部门号   |   部门中员工的姓名
10  |   张三,李四
20 | 王五,赵六 

注意:NVL函数 使分组函数无法忽略空值。

select count(nvl(comm,0)) from emp; --comm若为空,置为0

分组数据

select deptno, job, sum(sal) from emp group by deptno, job order by deptno;

当多个列分组时,用逗号分开。
select 列表中所有未包含在组函数中的列都应包含在group by 子句中。
**eg:select depno count(ename) from emp 就会执行错误 **

过滤分组

select depno, avg(sal) group by deptno having avg(sal) > 2000;  --平均工资大于两千的部门

where和having的区别

不能在where语句中使用组函数;
where不能放在group by 之后;
可以在having语句中使用组函数;
从SQL优化的角度,尽量使用where(where先过滤,后分组;having先分组后过滤)

分组查询中排序

可以按照:列、别名、表达式、序号 进行排序

select depno avg(sal) from emp group by deptno order by avg(sql);
select depno avg(sal) 平均工资 from emp group by deptno order by 平均工资;
select depno avg(sal) from emp group by deptno order by 2 desc;

分组函数嵌套

select max(avg(sal)) from emp group by deptno; --求平均工资的最大值

GROUP BY 语句增强

select deptno, job, sum(sal) from emp group by rollup(deptno,job);

用于报表

多表连接查询

笛卡儿积

等值连接

select  e.empno, e.empname, d.dname
    from emp e, dept d 
    where e.deptno = d.deptno;

不等值连接

select e.empno, e.ename, e.sal, s.grade 
    from emp e, salgrade s 
    where e.sal between s.losal and s.hisal; 
-- 显示薪水级别
-- between and 中小值在前

外连接

核心

select d.deptno 部门号, d.dname 部门名称, count(e.empno) 人数
    from emp e, dept t
    where e.deptno(+)=d.deptno
    group by d.deptno, d.dname; 
-- 按照部门统计员工人数,要求显示:部门号,部门名称,人数
-- 右外连接,防止部门人数为0时不显示
部门号|部门名称|人数
10|accounting|3
40|operations|0
20|research|5

自连接

核心:通过别名,将同一张表视为多张表

select e.ename 员工姓名, b,ename 老板姓名
    from emp e, emp b
    where e.mgr = b.empno
-- 查询员工的姓名和员工老板的姓名
-- mgr:老板号(老板也在员工中)

自连接存在的问题

层次查询

select level, empno, ename, sal mgr
    from emp
    connect by prior empno = mgr
    start with mgr is null
    order by 1;

子查询

eg:谁的工资比SCOTT高?

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

子查询中的十个问题

select empno,ename, (select job from emp where empno = 7839) 第四列 from emp;
-- select中使用子查询(必须为单行子查询)
select deptno,avg(sql) frpm emp
group by deptno 
having avg(sal) > (select max(sal)
                            from emp
                            where deptno=30);
-- having中使用子查询。不能用where代替,因为where中不能使用分组函数
select * from(select empno, ename, sal from emp);
-- 在from语句中使用子查询
-- 查询部门名称是sales的员工信息
select * from emp 
    where deptno=(select deptno from dept 
                        where dname='sales')
-- 用表连接的方法
select * from emp e,deptno d 
    where e.deptno=d.deptno and d.dname='sales'

注意:原则上使用表连接的方法性能高。因为只用一个from,只对数据库访问一次。
但是多表查询会产生多卡尔集,从而影响性能。

  1. 行号永远按照默认的顺序生成(不随位置变化而变化)
  2. 行号只能用<,<=,不能用>,>=

因为行号在Oracle数据库中永远从1开始,所以不能用>,>=

-- 找出员工表种工资最高的前三名
-- 此方法错误,因为行号不随位置变化而变化
select rownum,eno,ename,sal 
from emp where rownum>3
order by sal desc;
--以下方法为正确
select rownum,eno,ename,sal
from (select * from emp order by sal desc where rownum>3) 
-- 找到员工表种薪水大于本部门平均薪水的员工
select empno,ename,sal,(select avg(sal) from emp where deptno = e.deptno)
from emp e
where sal>(select avg(sal) from emp where deptno = e.deptno);
-- 查询员工信息,要求:职位与7566一样;薪水大于7782员工薪水
select * from emp where job=(select job from emp where empno='7566')
and  sal > (select sal from emp where empno='7782')
-- 查询最低工资大于20号部门最低工资的部门号和部门最低工资
select deptno,min(sal) from emp group by deptno 
having min(sal)>(select min(sal) from emp where deptno='20'

单行子查询之能用单行操作符
在一个主查询种可以有多个子查询

多行子查询的相关例子

--查询部门名称是sales和accounting的员工信息
select * from emp 
where deptno in (select deptno from dept where dname='sales' or dname='accounting')
--等价于
select e.* from emp e,dept d
where e.deptno = d.deptno and (d.dname='sales' or d.dname='accounting');
查询工资比30号部门任意一个员工高的员工信息
select * from emp where sal > any (select sal from emp where deptno='30')
查询工资比30号部门所有员工高的员工信息
select * from emp where sal > all (select sal from emp where deptno='30')
--等价于
select * from emp where sal >  (select max(mal) from emp where deptno='30')
--查询不是老板的员工
slect * from emp where empno not in (select mgr from emp where mgr is not null);
-- not in 后面的集合不能有空值,否则查询不出结果

案例

分页显示员工信息:显示员工号,姓名,月薪

每页显示四条记录

显示第二页的员工
按照月薪降序排列

-- Oracle 通过子查询的方式实现分页
select r,empno,ename,sql 
from (select  rownum r,empno,ename,sal 
          from (  select rownum ,empno,ename,sal from emp order by sal desc ) e1
         where r < 8) e2
where r >= 5

找到员工表中薪水大于本部门平均薪水的员工

-- 使用相关子查询方法
select empno,ename,sal ,(select avg(sal) from emp where deptno = e.deptno) avgsal from emp e
where sal > (select avg(sal) from emp where deptno = e.deptno)
-- 使用嵌套子查询方法
select e.empno,e.ename,e.sal,d.avgsal
from emp e , ( select deptno, avg(sal) avgsal from emp group by deptno ) d 
where e.deptno = d.deptno and e.sal>d.avgsal
-- 第一种(相关子查询)的性能好,执行块

按照部门统计员工人数,按照如下格式输出

select count(*) Total,
    sum(decode(to_char(hiredate,'YYYY'),'1980',1,0)) "1980",
    sum(decode(to_char(hiredate,'YYYY'),'1981',1,0)) "1981",
    sum(decode(to_char(hiredate,'YYYY'),'1982',1,0)) "1982",
    sum(decode(to_char(hiredate,'YYYY'),'1987',1,0)) "1987"
from emp;
-- or
select 
    (select count(*) from emp) Total,
    (select count(*) from emp where to_char(hiredate,'YYYY')='1980') "1980",  
    (select count(*) from emp where to_char(hiredate,'YYYY')='1981') "1981", 
    (select count(*) from emp where to_char(hiredate,'YYYY')='1982') "1982", 
    (select count(*) from emp where to_char(hiredate,'YYYY')='1987') "1987",  
from dual; 
上一篇 下一篇

猜你喜欢

热点阅读