Oracle学习笔记

Oracle中的逻辑结构和物理结构

物理结构

  1. 数据文件:记录所有的逻辑对象(表,视图,存储过程以及他们之间的关系) dba_data_files可以查询到
  2. 日志文件 记录所有数据库的变化,需要激活日志归档,可以根据日志文件做数据恢复
  3. 控制文件,数据文件和日志文件之间的桥梁。

逻辑结构

  • 实例(
    创建一个实例[数据库],就增加了2个进程,开销是很大的
    database configure assistance可以可视化的创建数据库
    作为客户端,可以通过配置tnsnames.ora来连接服务端。)
  • 表空间
  • 区间

oracle实例下的三种内存

  • 全局内存SGA
  • 进程内存PGA
  • 用户内存UGA
物理结构和逻辑结构的关系

一个逻辑机构可以对应多个物理结构,而一个物理结构只能对应一个逻辑结构

四种前缀
  • dba_ 只有dba权限的用户才可以查询
  • all- 在本用户范围内的所有
  • user_ 本用户私有的东西
  • v$ 在实例运行时不断变化的数据

用户管理

在oracle中创建用户需要指定密码
default tablespace 默认表空间 如果没有指定 用户都是users
temporary tablespace 临时表空间

刚创建的用户不能连接数据库,因此需要通过管理员给予用户连接和资源的权限。
grant connect,resource to xxx(user);

要想查看其它用户的表等信息,需要得到别人给自己的授权

给予权限
grant xx to user [with grant option 使用允许授权的用户再次将权限给予他人]

账号的锁定和解锁
alter user xxx account lock;
alter user xxx account unlock;

修改密码
alter user xxx identified xxx;
删除用户
drop user xxx
drop user xxx [cascade 删除用户和与用户有关的一切]

三种常用的角色
  • connect
    临时用户,特别是不需要建表的用户,赋予connect,(可以创建和访问自己的表,但无法操作和访问其他人的表。)该角色可以创建表,视图,索引,序列,簇,同义词,会话

  • resource
    与connect很类似,但不是临时用户

  • dba
    管理员
    拥有授权权限
    撤销授权

查看当前用户的所有角色
select * from user_role_privs;
查看角色的权限
select * from role_sys_privs
select * from role_sys_privs where role="connect"

查看从别人获得的 与 自己给别人的权限
select * from user_tab_privs;

表空间

意义:根据用户的情况,分配不同的表空间和空间大小,起到限制的作用;表空间支持分区散列(把重要且频繁访问的东西放在可快速访问的区域中),可以 执行计划 存放索引。

表空间,系统默认的6中表空间

  • system
  • sysaux
  • undotbsl
  • users
  • example
  • temp

create tablespace xxxx datafile [硬盘上的路径] size xxM;
如果表空间满了,可以增加容量
alter tablespace xxx add datafile size xxM.

drop tablespace xxx including contents
drop tablespace xxx including contents and datafiles

创建表

create table table_name(...)
如果用户创建表的时候,没有指定表空间,那么放在用户default tablespace 中,默认是user。
如果用户有修改过自己的默认表空间,就不会将自己创建的表放在user中

在建表时复制数据
create table table_name AS select column_1,column_2 FROM table_old
在添加时复制(要求列的名和类型要一致)
insert into table_name[column] select column_1,.. from table_old

dual表是一张只有一个字段1个记录的空表,可用于调试

oracle中的数据类型

  • 字符 varchar2 char nchar nvarchar2
  • 数值 number(p,s) [没有指定,默认38位] float 浮点型,*0.30103
    转为十进制
  • 日期 date datestamp
  • 其他 blob clob bfile

有char 和没nchar 的区别:有n表示使用字符计算,用unicode来存储
如果按照字节来计算的话 GBK汉字是2个字节,而utf-8是3~4个字节
char2和char的区别,带2表示是oracle优化器对于空格会做出优化,压缩空间存储。

结构层次

database–>tablespace,index .. –>segment(段) –> extent(区间)包含了许多的data block;

查询的一些优化建议
  • 尽量不要使用*
  • 多表查询尽量选择使用表别名
  • 条件查询多使用where;having虽然可以在结果集中过滤结果,但效率比较低。
  • 如果同一个条件or 有多个,使用in的效率会比较的高
对于索引的建议
  • 应该建立在DML较少,而查询多的表格上
  • 在unique上定义索引,效果更好
  • 尽量把表和它的索引放在不同磁盘上,这样可以调高查询速度。

约束

not null:null 与 ” 都是不允许的
unique 唯一性约束,可以是单列或者是多列 允许多个null
primary key 主键约束 可以是单列或者多列
foreign key 外键约束 在参照关系中的值必须在被参照关系中对应字段的域范围内。
check 数据插入或者更新时触发的约束。

查询约束名字典表
select constraint_name from user_constraints [where constraint_name = '']

修改约束名
alter table userinfo rename constraint_old to constraint_new

创建表时设置外键

create table table_name (
    column_name datatype references table2(column_name)
)

从表的外键不一定要和主表的主键名称相同,只要数据类型完全一样即可。

oracle 5 大约束中只有not null 没有表级约束

避免使用复合主键因为复合主键常常带来信息的困惑,比如姓名,班级,手机号作为一个复合主键,

姓名 班级 电话
张文 A 1333
李四 B 1444
张文 A 1433

这个时候,当我们对表执行的查询中并没有带上班级,执行select * from student得到了一个班级的2个张三,他们除了电话号码不同外,其他相同。对于这个信息,可以有2种理解
1,张文是同一个人,具有2个电话
2,张文不是同一个人,只有1个电话。
因为复合主键只有所有的属性相同才会被认为是重复的,因此尽可能的不要使用复合主键。

oracle只能增加约束或删除,而无法修改约束

约束一定要在插入数据前就都制定好!!!而不要等存在数据时再去做修改

alter table table_name drop constraints c_name; 
alter table table_name add constraints c_name 
check约束

check ( ) 约束内容,有多个就用and链接 或者 or
check ( name > 5) 即便name是一个字符型,但在oracle中,check约束使得他变为了数字型,因而一直插入时会出现数字不符的情况。
check (length(name) >5 ) 表示name字符数要大于5 这是正确的表达。 length() 是oracle中的函数。

索引

create index index_name on table_name(字段)
普通索引,允许输入重复的值
create unique index index_name on table_name(字段)
唯一索引和unique很像,除了null允许多次外,不允许重复。

唯一约束和唯一索引区别
1.约束是来检查数据的准确性,索引是来实现数据查询的优化,目的不同
2.创建唯一约束会在oracle中创建一个约束也会创建一个唯一索引
3.创建唯一索引只会创建唯一索引,不会创建唯一约束

当索引失效时,需要重建索引
alter index index_name rebuild

在oracle中,可以在要执行语句上,按f5查看预定执行计划,观察索引是否失效。

组合索引
当两个或多个列经常一起出现在where条件中时,则在这些列上同时创建组合索引

位图索引
列中有非常多的重复的值时候。例如某列保存了 “性别”信息。
Where 条件中包含了很多OR操作符。
较少的update操作,因为要相应的跟新所有的bitmap
优点:位图以一种压缩格式存放,因此占用的磁盘空间比标准索引要小得多

视图

视图是一种逻辑结构,本身并不存储数据表中的信息。一般我们可以对于复杂且经常要访问的查询去建立视图,这样可以达到一个简便的目的。同时,一张数据表中的所有信息未必允许用户看的,例如职工表,职工的基本信息可能是不具有特殊性(姓名,性别,出生,职位),是可以随便谁看的,但如果涉及到私密的信息(薪水,电话等等),那么并不是所有人都有权利去看的。
使用视图就是可以建立一个逻辑关系,里面只看包了你想要别人看到的东西,简而言之,就是视图是可以完全或者部分包含单张或多张表的信息。

创建视图的一般语法如下:

/*视图不指定属性则默认是查询结果的所有字段*/
create view view_name(attr1,attr2...) as
select .. from table1,table2..;

一个创建好了的视图,同样的,也可以被用于去创建一个新的视图。
因为from后面跟随的,只能是table或view;

使用视图和使用普通的表是一样的。

视图对于查询而言,是一个很便捷的工具,但如果对于视图执行 更新 插入或删除,可能会带来严重的问题。
例如有2张表,学生表和老师表,学生表中的教师id作为外键,将学生表和老师表联系起来。我们创建了一个视图,显示了不同学生他们的教师名。现在我们想要去插入一条记录,包含一个不存在教师表的老师名,这个时候,插入操作就会出错,并作出如下提示

无法通过链接视图改变基表

因为绝大多数的数据不允许视图更新,只有在如下情况下视图是可更新的。

  • 视图是只来自于一个表
  • 创建视图select子句中只包含关系的属性,不包含任何表达式,聚集或者distinct
  • 任何没有出现在select子句中的属性可以空值
  • 创建视图不含有group by 和having语句

这样创建出来的是图是可更新的视图

事务

事务其实就是由查询或更新语句的序列(下一节的序列不一样)组成。例如

select * from table1;
update table1 set attr=xxx,attr2=value2 where id=xx;
insert into table1(attr1=xx) values(xx) where id=xy;

在一些可视化工具(如PL/SQL)的sql窗口,全选这3个,点击执行,那么就构成了一个事务。事务的重大意义就是当其中出现错误时(违反约束或者系统故障)时,会回滚到最初的状态,这样也就是保持状态。

事务使用的一个注意点
在事务中,如果事务结束前,执行过DDL(create table.. drop table.. 等等)语句,那么事务将无法回滚

序列

在其他的一些数据库中,有auto increment来达到自增的目的,但是这个语法在oracle中不支持,解决的办法是创建一个序列对象。
创建序列对象的一般语法如下

create sequence sequence_name
start with xx
minvalue xx
maxvalue xx
increment by xx
cache xx (default 20)
cycle[nocycle]

如果没有修改cache,maxvalue-minvalue<20就会出错
使用方法,
seq_name.nextval 只要有使用过,不论是否更新或者插入成功失败,都会改变序列对象的值。
curval 当前值,如果没有执行过next,那么curval会出错
nextval 执行一个值,如果已经达到了最大值并且不循环的话,会出错

同义词

1.创建同义词语句:
create [public] synonym table_name for user.table_name;
其中第一个user_table和第二个user_table可以不一样。
  此外如果要创建一个远程的数据库上的某张表的同义词,需要先创建一个Database Link(数据库连接)来扩展访问,然后在使用如下语句创建数据库同义词:create synonym table_name for table_name@DB_Link;当然,你可能需要在user用户中给当前用户(user2)授权: grant select/delete/update on user2
2.删除同义词:drop public synonym table_name;
3.查看所有同义词:
select * from dba_synonyms

 同义词拥有如下好处:

  • 节省大量的数据库空间
  • 对不同用户的操作同一张表没有多少差别;
  • 扩展的数据库的使用范围,能够在不同的数据库用户之间实现无缝交互;
  • 同义词可以创建在不同一个数据库服务器上,通过网络实现连接。
  • Oracle同义词是数据库方案对象的一个别名,经常用于简化对象访问和提高对象访问的安全性。

零散的知识点

rownum

伪列 本身并不存在,但是可以进行使用的列,如sysdate,rowNum rowID
rowNum 行号 根据搜索的结果从1开始排列,不与关系中的元组号绑定。即rownum永远是从1开始排列,跟所查询的表格中的顺序无关。
rowNum一般用户获取第一条记录或者前N条记录,(可用于分页)
分页例如
–分页查询 找到51~59之间的sessionid记录(显示的就是51~59)

select r, SESSIONID from 
(select rownum r,sys.AUD$.* from sys.AUD$ where rownum<60)
where r>50;

/*
当有这种情况事,外层的rownum不认识里层的rownum,依然是要从1开始,而此时指定的条件是从3开始,于是就得不到想要的结果
*/
select * from (select rownum, test_tbl.* from test_tbl where rownum<10) where rownum>3
delete和truncate的区别

delete不是完全的删除,在没有保存退出之前,他的索引,视图等还是保存着,占据硬盘空间。
truncate 截断表,清空表中所有的记录,连通索引 视图等都清除。

oracle中的回收站

purge recycle 清空回收站
drop table table_name purge 删除表并清空回收站。

闪回技术

如果误删了,想找回,可以使用oracle的闪回技术
FLASHBACK TABLE table_name TO BEFORE DROP.

谓词

IN
在where中 如果有多个OR,且判断条件很相似 如 A=1 A=3 A=4 A=9 那么where将执行4次,判断,在性能效率上就比较低,此时就推荐使用IN
A in (1,3,4,9)
注意点,也可以是会用 NOT IN 表示不再范围内,但千万不要使用 NOT IN (null)!!
not in 查找的范围中如果有null,那么将不会有任何结果返回,in 无此限制。

having

HAVING 必须要和GROUP BY 结合用,WHERE 不能使用统计函数。
下面是3中子查询的建议
HAVING 子查询需要返回单行单列,而且需要用统计函数进行过滤
WHERE 子查询可以是单行单列 单行多列 多行单列
多行单列相当于得到的是一种范围 可以结合 IN, ANY, ALL来进行范围筛选。

exists

如果子查询有行返回,则返回true,没有就是false,exists关心的行数据,而in是列的数据,因此exists性能比in更好一些。

exists 和 in 比较
exists 是先执行主查询 然后 执行子查询,子查询存在一条记录,那么便返回主查询的结果。
in 先是将主查询挂起,先执行子查询,然后执行主查询,判断主查询结果是否在子查询的范围内。

GROUP BY

分组聚集,类似去重显示,同时可以对分组的属性使用聚集。
例如
select deptno,job,max(sal) from emp group by deptno,job
找出每个部门不同职业的最高薪水。

GROUP BY 分组聚集一个很重要的条件
保证出现在select语句中 但没有被聚集的属性 只能出现在group by 中。换句话说,出现在select中的属性,要么在聚集函数中,要么在group by中。
例如下面的查询是错误的


select dept_name, id, avg(salary)  //id 没有出现在聚集函数或者group by语句中
from instructor
group by dept_name 

Join 中 Using的用法
select * from empl join deptm using(deptno);
等价于
select * from empl e, join j where e.deptno=j.deptno;

集合运算

  • union 并集
  • interect 交集
  • except(Oracle中是minus) 差集

select 中的属性要一样,不一致会出现列数不一致的信息
union 默认是不包含重复的,union保留所有的
(select deptno from emp) union all (select deptno from dept)

Oracle PL/SQL :SQL结构化查询语言

在ORACLE写代码,
PL/SQL procedural Language /SQL :是在ORACLE 标准的SQL之上扩展的语言,执行SQL语句,定义变量,给变量赋值,条件,循环,异常处理,游标

procedure 过程化语言

SQL> set serveroutput on
SQL> begin
  2  dbms_output.put_line('hello world');
  3  end;
  4  /

定义变量

declare
---定义变量,  变量名   数据类型 
v_name varchar(10);
begin
--赋值  :=
v_name:='20';
dbms_output.put_line('hello world ' || v_name);
end;
SQL> declare
  2  v_name varchar(20);
  3  begin
  4  v_name:=&;
  5  dbms_output.put_line('hello '||v_name);
  6  end;
SQL> declare
  2  v_name staff.staf_name%type;
  3  begin
  4  v_name:=&s; ‘&’表示输入赋值,字符串需要''
  5  dbms_output.put_line('hello'||v_name);
  6  end;
declare
v_emp staff%rowtype;  这将存入一行的所有字段的类型,放入多个信息
begin
    select * into v_emp
    from staff
    where staf_id=2;
    dbms_output.put_line(v_emp.staf_name);
end;

if elsif else结构


declare
sal number(3,0);
begin
sal:=#

  if (sal<100) then
      dbms_output.put_line('小于100');
  elsif (sal<200) then
      dbms_output.put_line('大于100 小于200');
  else
      dbms_output.put_line('大于200');
  end if;

end;

loop循环

SQL> declare
  2  i number:=1;
  3  begin
  4      loop
  5          dbms_output.put_line(i);
  6          i:=i+1;
  7          exit when(i>5);
  8      end loop;
  9  end;
 10  /

FOR循环

for arg in start..endnum loop
    //execute body;
end loop;

异常的捕获

SQL> declare
  2  v number:=0;
  3  begin
  4  v:=1/0;
  5  exception
  6      when others then
  7      dbms_output.put_line('错误发生了');
  8  end;

存储过程

存储过程一般语法

create or replace prc_name(arg1 in type, arg2 out type)
is[as]
begin
    // execute body;
end; 

可以是无参,或仅带有输入 或输出 或多个的输入输出

create or replace procedure prc_test(p_balance in number)
is
begin
    update bank set user_balance=p_balance where user_id=1;
    commit;
end;

调用这个过程

declare
v number(12,0);
begin
    v:=&n;
    prc_test(v);
end;
create or replace procedure prc_test2(p_id in number, p_balance out number)
is
begin
    select user_balance into p_balance from bank where user_id=p_id;
end;

调用这个过程

declare
b number(12,0);
v number(2,0);
begin
    v:=&id;
    prc_test2(v,b);
    dbms_output.put_line(b);
end;

在JAVA中调用过程

需要用到
CallableStatement

 Connection con =  JDBCTools.getConnection();
try {
  //调用存储过程,使用prepareCall
  CallableStatement cstmt = con.prepareCall("{call prc_test2(?,?) }");
  cstmt.setInt(1, 1);
  //第二个参数为out,需要使用registerOutParameter
  cstmt.registerOutParameter(2, oracleTypes.INTEGER);
  cstmt.execute();
  //执行完毕,获取out的值
  int i = cstmt.getInt(2);
  System.out.println(i);
  cstmt.close();
  con.close();
} catch (SQLException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
}

函数

声明
create or replace function fn(num1 number) return nvarchar2
is
v_name nvarchar2(10);
begin
    select user_name into v_name from bank where user_id=num1;
    return v_name;
end;

调用函数
select fn(1) as name from dual;

你可能感兴趣的:(Oracle)