Oracle数据库笔记 Jack Chaing
作者QQ595696297 交流群 127591054 祝大家学习进步。
如果大家想看Word版本的可以去下载:Word排版比较清晰一些。
http://download.csdn.net/detail/jack__chiang/9810532
此笔记是作者本人去年开始从一个DBA新人的学习笔记,积累至今,希望拿出来给那些对DBA有兴趣的童孩学习,大家一起努力嘛。
此笔记记录了作者工作学习中从零基础的学习的记录,和从中遇见的问题与问题的解决!很高兴大家来疯狂源代码大家庭交流学习!
感谢支持,鞠躬!!转载请注明作者哦!!谢谢。
此文章不断更新!!谢谢大家支持!!
一、Oracle的使用
1)、启动
1、登录
Win+R—cmd—>sqlplus “/as sysdba” //以sysdba用户登录,这样可以管理权限,添加用户等
Win+R—cmd—>sqlplus username/password //以指定用户名密码登录
win+R —> cmd —–> sqlplus //按照提示,输入用户名密码
2、创建用户
create user username identified by password;
3、给与权限
grant resource,connect to username;
resource:
create trigger
create sequence
create type
create procedure
create cluster
create operator
create indextype
create table
connect:
create session
4、切换用户显示当前用户
conn username/password 切换用户
show user 显示当前用户名
5、使用$后面跟window命令符可以使用window命令
exit退出
7、查询当前系统时间
select sysdate from dual;
8、导入数据文件(sql语句表数据之类的)
因为数据文件默认语言环境为英语,当前系统是中文,中英文时间显示不一致,导致倒入失败,所以 需要先修改语言环境
alter session set nls_date_language=english;
alter session set nls_language=english;
然后开始导入文件使用:@ 文件全路径名 或者 start 文件全路径名
9、查看当前用户的所有表
select table_name from user_tables;
10、查看当前表结构
desc 表名字;
11、Oracle服务意思
1.OracleDBConsoleorcl oem控制台的服务进程
2.OracleJobSchedulerXE 定时器的服务进程
3.OracleOraDb10g_home1iSQL*Plus isql*plus的服务进程
4.OracleXETNSListener 监听器的服务进程
5.OracleServiceORCL 数据库服务进程
2)、Select 基本操作
1、distinct关键字
distinct跟在select后面,代表去除重复的,这个重复是整体重复的。
select 子句后面指定要查询的列
from 后面跟要查询的表
2、select语句可以对指定的列的所有值进行算术运算。
语法:
select 要计算列的名字 运算符 数字from 表名;
3、取别名
select 列名 要修改的名字 from 表明
select 列名 as 要修改的名字 from 表明
4、使用||合并多个列之间添加字符串
要添加字符靠近列名的那一边需要加||,并且要添加的字符串需要用单引号
select ‘找到的id为:’||id||’ 找到的名字为’||last_name as Name from s_emp;
5、对空的值进行替换(替换的值一定是要同类型的)
select nvl(要判断是否有空值的列名,要替换列的同类型的值) from 表名
select nvl(要判断是否有空值的列名,不为空显示的值,为空显示的值) from 表名
3)、sqlplus命令
1、在当前操作的命令行追加内容
a 追加的内容
2、在当前操作的命令行修改内容
c /命令行存在的内容/要被修改的内容
3、清空当前缓存的命令
clear buffer 清空当前缓存咋命令
4、删除当前操作行
del 要删除的行号
5、当前操作命令的下一行插入内容
i 直接i回车就可以在下一行添加内容
6、查看缓存命令
l 行号 :查看指定行号的缓存内容
直接输入l显示的是缓存中所有的
7、输入系统终端命令
Linux环境下使用 !后面跟着终端命令
Window环境下使用 后面跟终端命令 cls
8、执行缓存命令
使用/就可以执行sql语句
9、修改对应行的内容
输入要修改行号,后面直接跟要修改内容就可以
1 要修改的内容
10、退出缓存输入
直接在要准备添加行回车就好
11、保存你缓存的命令到文件中
save 要保存的文件路径 append(这个代表追加到当前要保存的文件路径里面)
12、从文件提取到缓存
get 文件路径
13、执行文件中的sql命令
start 文件路径 或者 @ 文件路径
14、编辑文档
edit 文件路径 用系统默认的东西打开文件
15、保存你的sql语句和执行结果保存到文件(是追加保存的)
你从开始执行spool开始就开始记录了,知道spool off 关闭为止,所输入的所有东西在文件都有记录
spool 文件路径
sql1
result1
sql2
result2
…
spool off 关闭spool功能
4)、格式化输出结果
1、定义要格式化的列或者给列起的名字
使用column关键字
colu 要修改的列名 format a15 //代表列显示的时候最多为15个子节长
2、colu first_name heading ‘Employ|Name’ format a5
给first_name 取了个名字叫做Employ|Name,|表示换行,a5表示5个字节
3、column salary JUSTIFY LEFT FORMAT $99,990.00
Justify left代表列名向左对其
999,999.999代表每一位为0-9之间的数“,”是代表分割符,千分位 000,000.000代表每一位为0-9之间的数,不足的用0补齐
4、column start_date format a8 null ‘not date’;
代表列名如果为空,就用not date文本代替
format后面不能直接跟null 在a8后面写
这里的和替换空和nvl是有区别的,nvl必须要求类型匹配才可以替换
5、column显示所有对列格式的设置
6、显示指定列的设置情况
column 列名
7、删除指定列的设置和删除全部列的设置
column 列名 clear
clear column //删除全部
8、出错的时候
出错的时候不能显示就只显示#######
set linesize(line) 设置sqlplus输出的最大行宽 –
set pagesize 设置页面的最大行数
set newpage 设置页面之间的空行数
spool sqlplus屏幕的文件输入输出命令
edit 使用自定义的编辑器编辑指定文件 其实也可以使用ed.修改后直接使用/即可执行
save 保存当前session最近的sql语句至指定的文件中
host 返回到操作系统环境,类似!
start或@ 执行文件中的命令
edit 使用自定义的编辑器编辑指定文件
define_editor 自定义sqlplus里的编辑器
exit或quit 退出sqlplus
column
column是sqlplus里最实用的一个命令,很多时候sql语句输出的列宽度不合适而影响查看,都需要
用到这个命令来更改select语句中指定列的宽度和标题。大部分时候,我们可以简写column为col即
可,主要有以下两种用法:
?修改列宽度
column c1 format a20 –将列c1(字符型)显示最大宽度调整为20个字符
column c1 format 9999999 –将列c1(num型)显示最大宽度调整为7个字符
?修改列标题
column c1 heading c2 –将c1的列名输出为c2
5)、select条件查询
Where子句的使用(如果报from找不到,就要注意from是不是和某个列写到一起了!)
_: 当且仅当通配一个字符
转义字符:
默认为,可以指定 指定的时候用escape 符号指明即可,转义字符只能转义后面的一 个字符 ,下面这个代表是以_开头后面任意字符的last_name
between 1 and 4: 包括起止值。限定内容为1到4。
in (1,2,4): 限定内容为1,2,4。
is null:对null值操作特定义的操作符,不能使用=否定的Is not nul,not in ,not like ,not butween
3》逻辑操作符
当条件有多个的时候使用
and:且逻辑
or:或逻辑
注意:and逻辑比or逻辑要高
not:非逻辑
需求:
1.查找员工id在[5,20]之间的所有员工的id和last_name
or
2.查找员工id不在[5,20]之间的所有员工的id和last_name
or
这个需要注意的是not匹配的是最近的一样,优先级相对于and是高的,所以加括号
or
需求:查看员工名字以C字母开头的员工的id,工资。
练习:查看员工名字长度不小于5,且第四个字母为n字母的员工id和工资
需求:查看员工名字中包含一个_的员工id和工资
需求:查看员工提成为为空的员工的id和名字
需求:查看员工部门id为41且职位名称为Stock Clerk(存库管理员)的员工id和名字
练习:查看员工部门为41 或者 44号部门 且工资大于1000的员工id和名字
查看员工部门为41且工资大于1000 或者 44号部门的员工id和名字
6)、预定义函数
函数:这里的函数相当于Java中写好的一些方法,有名字,可以传递参数,实现某一项具体功能。
函数分为:
1.单行函数
1.字符函数
2.日期函数
3.数字函数
4.转换函数
2.分组函数(后面的章节再做学习)
学前须知:
哑表dual
dual是一个虚拟表,辅助查找和运算。通常用在select语句中,作为查询的目标表结构,oracle保证dual里面永远只有一条记录。
例如:
显示1+1的结果,可以看出,dual很多时候是为了构成select的标准语法
select 1+1 from dual;
1、字符函数
1) LOWER:转换成小写
2) UPPER:转换成大写
3) INITCAP:首字母变成大写,其余都小写
4) CONCAT:字符串的连接
5) SUBSTR(str,start,length)或者SUBSTR(str,start):字符串的截取
6) LENGTH:求字符串的长度
7) NVL : 转换null的值。(前边已经用过)
nvl2:
8) DECODE:
upper 把字符转换为大写
例如:把’world’转换为大写
select upper(‘world’)
from dual;
例如:把s_emp表中的last_name列的值转换为大写
select upper(last_name)
from s_emp;
initcap 把字符串首字母大写
例如:把’hELLO’转换为首字母大写,其余字母小写
select initcap(‘hELLO’)
from dual;
concat 把俩个字符串连接在一起(类似之前的||的作用)
例如:把’hello’和’world’俩个字符串连接到一起,并且起个别名为msg
select concat(‘hello’,’world’) msg
from dual;
substr 截取字符串
例如:截取’hello’字符串,从第2个字符开始,截取后面的3个字符
select substr(‘hello’,2,3)
from dual;
可以找到第二个字母开头的是什么字母,其他同理
length 获得字符串长度
例如:获得’world’字符串的长度
select length(‘world’)
from dual;
nvl 替换列中为null的值
在前面的章节已经使用过了
nvl(要输出的列名,为空的时候要被替换的值) //要替换的值类型必须要和之前保持一致
例子:
1.查找last_name全小写的值为velasquez的员工的lastname
2.查找last_name的长度>10的所有员工的last_name
instr查找字符串
instr(‘1234;5678’,’;’,1,1)-1
解释:1. ‘1234;5677’==>可以是表达式,也可以是具体数据
2. ‘;’==>为分离的标志,这里为两组数据中的“;”号
3. 第一个1为从左边开始,如果为-1,则从右边开始。
4. 第二个1为“;”出现的第几次。
2、数字函数
1) ROUND:四舍五入
2) TRUNC:截取,不进行四舍五入
3) MOD:取余
(切记-1代表保存小数点后一位,0保留到各位,1保留到10
round(arg1,arg2)第一个参数表示要进行四舍五入操作的数字
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
select trunc(45.67) from dual; 45
select trunc(45.67,1) from dual; 45.6
select trunc(45.67,2) from dual; 45.67
select trunc(45.67,-1) from dual; 40
select trunc(45.67,-2) from dual; 0
select trunc(55.67,-2) from dual; 0
mod 取余
mod(arg1,arg2)
第一个参数表示要进行取余操作的数字
第二个参数表示参数1和谁取余
“`
3、日期函数
1) MONTHS_BETWEEN:两个日期之间的月数,如果是正数前面的值大于后面的值
2) ADD_MONTHS:在指定日期上增加月数
3) NEXT_DAY:指定日期的下一个星期几是哪天
4) LAST_DAY:指定日期的最后一天
5) ROUND:对指定日期进行四舍五入
6) TRUNC:对指定日期进行截取
sysdate关键字
表示系统的当前时间
例如:
显示时间:当前时间
months_between 俩个时间点之间相差多少个月(单位是月)
例如:
30天之后和现在相差多少个月
add_months 返回一个日期数据:表示一个时间点,往后推x月的日期
例如:
‘01-2月-2016’往后推2个月
例如:
当前时间往后推4个月
next_day 返回一个日期数据:表示一个时间点后的下一个星期几在哪一天
例如:
当前时间的下一个星期5是哪一个天
注意:
如果要使用’FRIDAY’,那么需要把当前会话的语言环境修改为英文
last_day 返回一个日期数据:表示一个日期所在月份的最后一天
例如:
当前日期所在月份的最后一天
round 对日期进四舍五入,返回操作后的日期数据。逢16日往月份进一,逢7月往年份进一
round(sysdate,’year/y/yy/yyy/yyyy’) 年 7月节点
round(sysdate,’mm/month’) 月 16号节点
round(sysdate,’d/day’) 星期 星期四节点
round(sysdate,’dd’) : 天 -》 12点节点
例如:
把当前日期四舍五入到月(年月日.时 分 秒 把这个看错数字就可以了)
今天2016年9月5日四舍五入到月,就要看日是否大于16?大于进一,不大于不进一,同时舍弃为1
把当前日期四舍五入到年
大致算一下,今天已经9月了,所以满足大于节点7进一位,同时舍弃年前面的值
trunc 对日期进行截取 和round类似,但是只舍弃不进位
截取和round基本是一样的只是,不进位而已。
4、类型转换函数
1).TO_CHAR 将日期或者数值转换成字符串
2).TO_NUMBER 将字符串转换成数字
3).TO_DATE 将日期字符串转换成日期
to_char 把日期转换为字符
例如:
把当前日期按照指定格式转换为字符串
练习:显示当前时间,查询当前时间是这年的第几天?是这个星期的第几天?是这个月的第几天?
(注意拼接字符串,只有一个别名,是一个整体)
例如:
测试常见的一些日期数据转换为字符串的格式
千年虫:
to_char 把数字转换为字符
L : 本地货币符号
:
. : 小数点
, : 千分符
9 : 0-9
0 : 0-9, 如果位数不足,强制补0
to_number 把字符转换为数字
例如:
//这个写法是错的 abc不能转换为数字
select to_number(‘abc’)
from dual;
to_date 把字符转换为日期
.TO_DATE(char, [‘fmt’]):例如
select TO_DATE (‘10-September-1992’,’dd-Month-YYYY’) from dual
.使用format的元素格式
例如:
select to_date(‘10-12-2016’,’dd-mm-yyyy’)
from dual;
5、extract()函数
oracle中extract()函数从oracle 9i中引入,用于从一个date或者interval类型中截取到特定的部分
//语法如下:
EXTRACT (
//获取两个日期之间的具体时间间隔,extract函数是最好的选择
/
–
select extract(year from systimestamp) year
from dual
/
//
6、exists和 not exists用法
EXISTS(包括 NOT EXISTS )子句的返回值是一个BOOL值。 EXISTS内部有一个子查询语句(SELECT … FROM…), 我将其称为EXIST的内查询语句。其内查询语句返回一个结果集。 EXISTS子句根据其内查询语句的结果集空或者非空,返回一个布尔值。
一种通俗的可以理解为:将外查询表的每一行,代入内查询作为检验,如果内查询返回的结果取非空值,则EXISTS子句返回TRUE,这一行行可作为外查询的结果行,否则不能作为结果。
Exists是子查询的一种条件形式,通过判断Exists的选择表达式(括号内的部分)的结果,如果存在一行或多行结果记录,则Exists整个子查询结果为真,否则为假。由于我们采用Exists来实现子查询,只需要关心是否存在满足条件的记录,所以选择表达式的选择列表采用*来实现,当然,你也可以在选择列表指明具体的某些列,但这些列将在整个搜索过程中被忽略。
Exists实例
查询原理:
遍历dbo.Res_Coach每一条,同时处理where条件(EXISTS (select * from Res_Coach where Resc_id=0) 判断结果为true或者false),为true时拿出该条,false时,放弃该条记录。
SQL 代码
– 1、 where条件中的子查询和主查询没关系
– 2、 where条件中得子查询和主查询有关系
实例备注:不管where条件中得子查询和主查询有没有关系,遍历主查询中得每一条时,判断where条件,exists结果为真,where条件返回true,拿出该条记录,where条件返回false, 不返回该记录。
Exists 和 In 的选择
如果查询的两个表大小相当,那么用in和exists差别不大。如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in
7、sys.wm_concat无效问题,自己写一个
运行project后后台报错:
org.springframework.jdbc.BadSqlGrammarException: StatementCallback; bad SQL grammar [select wmsys.wm_concat(RoleID) from dlsys.tcrole a,dlsys.tcUnit b,dlsys.tcHuman c where a.UnitID = b.UnitID and b.UnitID = c.UnitID and c.HumanID = 161 and RoleID not in(152)]; nested exception isJava.sql.SQLException: ORA-00904: “WMSYS”.”WM_CONCAT”: 标识符无效
原因:
11gr2和12C上已经摒弃了wm_concat函数,当时我们很多程序员在程序中确使用了该函数,导致程序出现错误,为了减轻程序员修改程序的工作量,只有通过手工创建个wm_concat函数,来临时解决该问题,但是注意,及时创建了该函数,在使用的过程中,也需要用to_char(wm_concat())方式,才能完全替代之前的应用。
解决办法:
一.解锁sys用户
二.创建包、包体和函数
以sys用户登录数据库,执行下面的命令
–定义类型body:
三.创建同义词并授权
四.使用子定义的wm_concat
9、Oracle DECODE函数
使用方法:
1、比较大小
例如:
变量1=10,变量2=20
则sign(变量1-变量2)返回-1,decode解码结果为“变量1”,达到了取较小值的目的。
其实decode第一参数是if判断语句的第一个参数,第二个参数是if判断语句的第二个参数
If(12-12==-1)else
12
if else(12-12==1)else
1….
1、插入测试数据
测试一:
结果如下:
如果是中文课程的话, 显示分数, 其他课程分数为零。
这条SQL 看上去使用意义不大。
测试二:
统计中文课程的分数。看上去有点意义。
总体看来, decode 的使用看上去和case when 有点类似。如果只是用作以上两种状况,看上去意义不大。
select name,sum(decode(subject, ‘Chinese’,score,0)) as CHINESE from student_score group by name;
select name,score as CHINESE from student_score;
使用的两句使用后的效果一样,看上去使用decode 多此一举。
2、行转列-有意义的使用
往以上table 再插入一些其他学生的成绩:
使用以下SQL:
将行的数据转化为列, 是不是很有意义了。
使用case then 也可以达到相同的效果。
7)、多表查询
学前须知:
笛卡尔积
在数学中,两个集合X和Y的笛卡尓积(Cartesian product),又称直积,表示为X × Y.
假设集合A={a, b},集合B={0, 1, 2},则两个集合的笛卡尔积为{(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}。
在数据库中,如果直接查询俩张表,那么其查询结果就会产生笛卡尔积
例如:
链接查询分类:
为了避免笛卡尔基的产生,我们可以使用连接查询来解决这个问题。
连接查询分为:
1、等值连接:
利用一张表中的某个列的值和另外一张表中的某个列的值相等的关系,把两张表连接起来
需求:查看每个员工的id,last_name以及所属部门名称
(要用别名,就用表的别名,在用列明名的话会有问题的)
需求:查找员工工资所属的等级名称
2、不等值连接
使用的是除=以外的操作符号的多表查询
例如:使用between and
3、外连接
Outer是可以省略的。加号放在值少的一方,就可以让少的一方值显示,一般来说+所在列的位置,的相反位置就是当前的连接是什么连接!反过来
当使用一个表的记录在另外一张表中不存在的时候,我们仍旧需要显示,使用外链接就可以了
平常规律:加号写法跟在
外连接分为:
右外连接(right join/rigth outer join)
左外连接(right join/left outer join)
全外连接(full join /full outer join)
这个是+的写法
加号只能写一个,写两个不代表全部外连接;
全外连接:就是两个表中不存在的都不会显示
4、自链接
自己和自己连
5、集合连接
:对查询结果集的操作。
6、oracle伪列 rownum
伪列rownum,就像表中的列一样,但是在表中并不存储。伪列只能查询,不能进行增删改操作。它会根据返回的结果为每一条数据生成一个序列化的数字。rownum是oracle才有的伪列
在 Oracle 里面 ROWNUM 主要有可以完成两个任务:
范例:查询前 N 行记录
范例:取出 emp 表之中的 5~10 条
7、Oracle伪列RowID
现在每一行的记录都发现有自己的数据列,而除了这些数据列之外,还存在有每一行数据的唯一的物理地址,而这 个物理地址就只能够通过 ROWID 取得。
那么每一个 ROWID 数据都是包含有存储数据的,以:“AAAR3qAAEAAAACHAAC”为例做一个简单解释:
· “AAAR3q”:数据的对象编号;
· “AAE”:数据保存的相对文件编号;
· “AAAACH”:数据保存的块号;
· “AAC”:保存的数据行号。 数据库之中的所有数据都是在磁盘之中,保存,所以来讲,根据不同的数据会分配不同的空间,而 ROWID 就可以清楚的记录这些空间的信息。
面试题:现在有一张数据表,由于设计的时候缺少一些限制,同时后期使用的过程之中出现了大量的重复数据,要求将重复的数据删除掉,只保留最原始增加的数据。 准备过程:
1、 为了方便观察问题,首先将 dept 表复制为 mydept 表;
2、 观察现在的 mydept 表之中的数据和 ROWID(这个时候的数据就是最重要保存的数据)。
4、向 mydept 数据表之中增加重复数据。
5、
正式问题:
将 mydept 表之中现在所有的重复删除掉,保留最早增加的数据。
解决问题:
1、在 mydept 表之中可以发现重复数据,而且重复数据都重复的很有规律,在 deptno、dname、loc 都重复,于是换个思路,查询出所有数据之中最早的 ROWID,(MIN(ROWID))
2、 不在此范围的数据删除就行了,使用 NOT IN,而且之前的查询返回的是多行单列。
PS:如果你没遇见此类题目,那么你就不用复习了,如果觉得会遇见,你就好好看。
在以后的分析之中,ROWID 依然会出现,只需要记住,ROWID 就像身份证一样,是作为一行具体数据的唯一的物 理标记出现的。
1.Rowid的显示形式
我们从rowid伪列里select出来的rowid是基于base64编码,一共有18位,分为4部分:
OOOOOOFFFBBBBBBRRR
其中:
OOOOOO: 六位表示data object id,根据object id可以确定segment。关于data object id和object id的区别,请参考http://www.orawh.com/index.php/archives/62
FFF: 三位表示相对文件号。根据该相对文件号可以得到绝对文件号,从而确定datafile。关于相对文件号和绝对文件号,请参考http://blog.itpub.net/post/330/22749
BBBBBB:六位表示data block number。这里的data block number是相对于datafile的编号,而不是相对于tablespace的编号。
RRR:三位表示row number。
Oracle提供了dbm_rowid来进行rowid的一些转换计算。
SQL> create table test(id int,name varchar2(30));
Table created.
SQL> insert into test values(1,’a’);
1 row created.
SQL> commit;
Commit complete.
SQL> select rowid from test;
ROWID
AAAGbEAAHAAAAB8AAA
SQL> select dbms_rowid.rowid_object(rowid) obj#,
2 dbms_rowid.rowid_relative_fno(rowid) rfile#,
3 dbms_rowid.rowid_block_number(rowid) block#,
4 dbms_rowid.rowid_row_number(rowid) row#,
5 dbms_rowid.rowid_to_absolute_fno(rowid,’SYS’,’TEST’) file#
6 from test;
OBJ# RFILE# BLOCK# ROW# FILE#
26308 7 124 0 7
2. 如何从rowid计算得到obj#,rfile#,block#,row#
rowid是base64编码的,用A~Z a~z 0~9 + /共64个字符表示。A表示0,B表示1,……,a表示26,……,0表示52,……,+表示62,/表示63可以将其看做一个64进制的数。
所以,
obj#=AAAGbE=6*64^2+27*64+4=26308
rfile#=AAH=7
block#=AAAAB8=64+60=124
row#=AAA=0
3. 如何从obj#,rfile#,block#,row#计算得到rowid
实际上就是将十进制数转化成64进制数,当然,从二进制转化的规则比较简单点。
将二进制数从右到左,6个bit一组,然后将这6个bit组转成10进制数,就是A~Z a~z 0~9 + /这64个字符的位置(从0开始),替换成base64的字符即可。
obj#=26308=110 011011 000100=6 27 4=G b E,补足成6位base64编码,左边填0,也就是A,结果为AAAGbE
rfile#=7=111=7=H,补足成3位,得到AAH
block#=124=1 111100=1 60=B 8,补足成6位,得到AAAAB8
row#=0,3位AAA
合起来就是AAAGbEAAHAAAAB8AAA
4. Rowid的内部存储格式
虽然我们从rowid伪列中select出来的rowid是以base64字符显示的,但在oracie内部存储的时候还是以原值的二进制表示的。一个扩展rowid采用10个byte来存储,共80bit,其中obj#32bit,rfile#10bit,block#22bit,row#16bit。所以相对文件号不能超过1023,也就是一个表空间的数据文件不能超过1023个(不存在文件号为0的文件),一个datafile只能有2^22=4M个block,,一个block中不能超过2^16=64K行数据。而一个数据库内不能有超过2^32=4G个object。
SQL> select dump(rowid,16) from test;
DUMP(ROWID,16)
Base64编码说明
Base64编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前面补两个0,形成8位一个字节的形式。 如果剩下的字符不足3个字节,则用0填充,输出字符使用’=’,因此编码后输出的文本末尾可能会出现1或2个’=’。
为了保证所输出的编码位可读字符,Base64制定了一个编码表,以便进行统一转换。编码表的大小为2^6=64,这也是Base64名称的由来。
8)、组查询
概念:
所谓组查询即将数据按照某列或者某些列相同的值进行分组,然后对该组的数据进行组函数运用,针对每一组返回一个结果。
note:
1.组函数可以出现的位置: select子句和having 子句
2.使用group by 将将行划分成若干小组。
3.having子句用来限制组结果的返回,只能出现在Group by语句中。
语法:
组函数
常见有5个:
avg:求平均值
count:求总数
max:最大值
min:最小值
sum:求和
stddev:求标准差
ariance:求方差
对字符型数据的最大值,是按照首字母由A~Z的顺序排列,越往后,其值越大。当然,对于汉字则是按照其全拼拼音排列的,若首字符相同,则比较下一个字符,以此类推。
练习:
查看各个部门的最高工资
查看各个部门的员工数
查看各个部门的平均工资
查看各个部门的最低工资
group by 子句:(注意:如果select查询语句中有组函数出现,并且还查询了其他的列,则此列必须出现在group by子句中!!)
1.用来将表中的行划分成若干更小的组
2.出现在select子句中,但是没有出现在组函数中的列必须出现在group by子句中
3.出现在group by中的列不一定出现在select子句中。
4.group by子句中的列出现在select结果中,表意性比较强。
5.当group by子句中出现多列的时候,表示按照从左至右的顺序进行分组,即先按照第一列分组, 然后再第一列分好的组里面 按照第二列进行分组,以此类推。
6.限制组结果的返回一定使用having不能使用where。
需求:
1.查看各部门,职称相同的人的平均工资。
2.查找部门平均工资>1000的所有部门的id和平均工资
目标: 部门id , avg(salary)
from : s_emp
分组: 部门平均工资
group by dept_id
组结果的返回:
部门平均工资>1000
组合:
需求:查看所有部门的部门工资总和,按照部门工资的降序排序
having: 限制组结果的返回。
1.如果希望限制组结果的返回,那么直接使用having子句跟在group by 子句之后。
需求:查看部门平均工资大于1000的部门id
需求:
1、查看职称不以VP开头的所有员工,
2.并且将他们以职称分组,
3.求各职称的工资总和,
4.将工资总合>5000的职称和工资总合显示出来。
9)、排序
1、排序Order By(注意:order by后面的元素可以给每一个指定升序和降序)
Order by语句始终位于select语句的最后面
2、order by后可以跟什么:
列名,列的别名,表达式,
排序不指明的会按照select后面的列名,按顺序排序
3、order by后面可以跟多列
表示先按第一列排序,
如第一列有相同值再按
第二列进行排序,如前二列
均有相同值,则按第三列进行排序…
4、默认是asc升序
指明desc是降序的
5、空值排序是最大的
升序排序的时候,空值放在最后
降序排序的时候,空值放在最前面的
6、出现在order by后面的列,不一定出现在select查询的列里面
10)、子查询
所谓子查询,就是一个select语句中嵌套了另外一个或者多个select语句
一、比较值不确定,需要另外一个select语句执行后才能得到,使用子查询
1、单值子查询:子查询的结果为1个
需求:
1.查询和Simith职称相同的所有员工的last_name和职称
分析步骤:
2.查看工资大于Chang员工工资的所有员工的id和名字。
3.查看员工工资小于平均工资的所有员工的id和名字
2、多值子查询:子查询的结果为多个
需求:
1.查询所在区域为2号区域的所有部门的员工的id和last_name
问题:比如上面的题这样写,就会出现问题,他把所有dept_id不为空的全部打印出来了
如果子查询的列写成了主查询的条件,不会报错!会把这个列不为空的查询出来
子查询出现情况二:
查询的内容作为一个表存在
练习:查询各部门的id,name 和部门员工的平均工资
3、子查询返回多行单列
如果说子查询返回的是多行单列数据,实际上就相当于提供了一个数据的查询范围。那么如果要想针对于范围查询, 则要使用三个判断符号:IN、ANY、ALL。
1、IN操作:
指的是在指定范围内。也可以使用 NOT IN 不在范围之内
2、ANY操作(不看)
3、ALL操作(不看)
11)、运行时变量
1、定义:运行的时变量可以让我们和sql语言之间有个交互,容许我们动态传递参数
2、语法 &var
3、运行时变量可以出现在任意位置
(直接这样写是不需要转义的)
note:
1.&代表取值。&varName,代表取varName这个变量的值,如果这个变量值,之前不存在,那么系统会提示输入这个变量的值。如果存在,直接取值。
2.set verify on ,打开交互提示,如果打开,会显示old和new value。现在默认都是打开的。使用set verify off,关闭
4.定义变量:
define[def] varName = value;
查看定义的变量:
define[def] [varName];
只要变量存在的值,会被自动替换
2.def/define : 查看当前环境中定义的所有变量
3.def/define name : 查看变量name的值。
如果不想在select语句中&name的外边使用”,则可以在定义变量name时写成definename=”’zhangsan”’;‘可以用来转义’(其实写一个双引号,里面写一个单引号也是可以的”‘zhangsan’”)
存在def里面的值是这样的显示
5.使用accept用来定义带数据类型和提示符的变量
例如:accept varNum number :代表定义一个变量名字为varNum,类型为Number,当输入类型不是数字类型是报错,提示继续输入。(类型要和你输入的类型保持一致,如果不设置类型默认的是字符)
prompt:当输入变量时,给用户的提示信息。
accept myNum number prompt 区域id:
定义一个Number类型的变量myNum,当按下回车时提示区域id:
accept nyName char prompt 名字:(注意日期传的是当前系统的格式dd-mon-rr mon是简写的月份)
6.取消变量的定义(和define的取消是一样的)
undefine varName;
7.向脚本文件传递参数(也就是读取文件的时候,在后赋值)
在文件中参数使用&n(n代表数字)来表示取第几个参数值,然后再调用文件执行的时候使用
@file val….(多个参数值使用空格分开。)
文件内容
SQL
当然比较方便的一种就是把,accept写到文件的开始,先提示用户赋值,然后在通过赋的值,找。
12)、数据模型和数据库设计
软件开发的步骤可大致分为:
1.需求分析
2.系统设计
3.编码实现
4.系统测试
5.运行维护
student 老师,辅导员class 多对一
数据建模
1.Model of system in client’s mind
2.Entity model of client’s model
3.Table model of entity model
4.Tables on disk
实体-关系图
实体-关系图(Entity Relationship Diagram),也称为E-R图,提供了表示实体类型、属性和关系的方法,用来描述现实世界的概念模型。
3 种类型:
一对一关系 (1 ∶ 1)
多对多关系 (M ∶ N)
may-be 和 must-be
ER图中符号的表示
自己和自己关联,比如经理自己
数据库设计
数据建模完成之后,可以把ER图转换成数据中的表
1.实体的名字转换为表的名字
2.实体的属性转换为表中的列
3.具有唯一特点的属性设置为表中的主键
4.根据实体之间的关系设置为表中某列为外键列(主外键关联)
第一范式:
第二范式:
第三范式:
总之要保证每个表属于一个范畴,表里面的列要完全依赖主键,和主键有间接依赖关系的设置为外键而存在
13)、主键和外键
联合主键联合外键只能是表级约束
主键:
外键:
Nn:代表not null
U:代表unique
Pk:代表primary key
Fk:代表foreign key
建表:
1.映射实体—-表
2.映射属性—-列
3.添加约束
4.描述关系信息(外键)
14)、创建表和约束问题
1.oracle数据库中的多种数据结构:
1.表结构 存储数据
2.视图 一张表或多张表中数据的字节
3.sequence 主要用来生成主键值
4.index 提高检索性能
我们需要学会创建数据结构
2.表结构:
1.表结构可以随意创建
2.表结构不需要预先申请空间
3.可以在线修改。
3.创建语法:
创建表的释放有两种:基本操作 子查询
3.1.2 命名规则
3.1.3 oracle支持的数据类型:
1.char,varchar2,varchar
用法:
区别:char:定长字符
varchar , varchar2:不定长字符
在oracle数据库中,指定变长字符串首选varchar2.
2.number(p,s):
3.date: 日期类型
3.1.4 default:设置默认值
3.1.5 约束
列级约束:直接跟在列完整性定义后边的约束
column dataType unique,
也可以这样写
3.1.6 Primary key:主键
//列级定义
//表级定义
//可以联合主键
3.1.7 .foreign key:外键
一般在设计表与表之间的关系时,为了减少数据冗余,一般做的操作是在其中一张表中设置 一列(组合列),这一列(组合列)的值可以唯一的确定另外一种表中和当前表相关联的一行数据。那么这个列成为外键。
note:
1.可以是单列,也可以是组合列
2.引用当前表或者其他表中(只要想和当前表建立关系的表) 的主键列或者unique列
3.可以是表级别/列级别
4.值必须是引用的列的值或者为null
5.有外键约束时,如果想要删除的父表(被引用的表)中的某一条数据时,必须保证在子表(引用表)中没有和这条数据相关联的数据存在。
6.ON DELETE CASCADE ,指明在删除父表中数据时可以级联删除子表中数据
例如:
3.1.8 check : 自定义约束,定义每一行必须遵循的规则
note:
1.可以是表级/列级约束
例如:
子查询建表
一般使用子查询建表,要将另外一张表中的某些数据存放到一张新的表格中。(相当于将原来打印在控制台上的信息,现在直接定义成一张新的表格。)
复制一个表的指定列数,或者全部
note:
1.在用子查询建表时,只有not Null约束会被复制。
2.创建表时可以指定列名,也可以不指定,但是一定不指定列的数据类型
3.创建表的列跟子查询表的列数要保持一致
5、常见数据类型
数据表的组成就是行和列的 集合,而且每一列 都有其对应的类型 ,所以在进行数据 表创建之前,首先 需要来了解一 下在系统之中常用的数据类型。
虽然 BLOB 字段可以保存电影数据,但是一般正常人没人这么做。而且在一般的开发之中,99%选用的数据类型:
VARCHAR2(VARCHAR)、NUM BER、DATE、CLOB(像 VARCHAR 一样的方式操作)。
6、闪回操作(理解)
从 Oracle 10 g 起为了方便用户进行数据表的恢复。为 Oracle 增加了一个类似 于 windows 的回收站功能,等于是所有 删除是数据表,首先保存在回收站之中,如果用户有需要也可以进行恢复。
范例: 查看回收站
show recyclebin ;
在回收站里面可以发现所有被删除的数据表。
从 Oracle 11g 开始为了方便用户查看数据,提供了一个 SQL Develop er 工具,但是此工具需要配置 java 环境。
JDK 目录:D:\ap p \Teacher\p roduct\11.2.0\dbhome_1\jdk\bin\java.exe
进入到工具之后首先需要配置一个 scott/tiger 用户的数据库连接。
范例: 通过回收站恢复 emp 10 数据表
FLASHBACK TABLE emp 10 TO BEFORE DROP ;
范例: 彻底删除数据表,不让删除的数据表经过回收站,在删除语句之后增加一个 PURGE DROP TABLE emp 10 PURGE ;
范例: 删除回收站之中的一个表
PURGE TABLE emp null ;
范例: 清空回收站
PURGE RECYCLEBIN ;
对于闪回技术,只需要有一定的了解即可,而且也只有 oracle 有此特性。
7、表空间
1、创建表空间
/分为四步 /
/第1步:创建临时表空间 /
/第2步:创建数据表空间 /
/第3步:创建用户并指定表空间 /
/第4步:给用户授予权限 /
2、表数据库实例表空间联系
1、数据库
2、表空间
3、实例
一个数据库可以由多个实例打开,但任何时刻一个实例只能打开一个数据库。多个实例可以同时运行在同一个机器上,它们彼此访问各自独立的物理数据库。
15)、数据字典
1、字典,就是用来帮助人们查看一些信息,查看一些内容
2、数据字典的概述:
3、用户可以通过sql语句访问
Select table_name from dictionary
根据查询结果的不同按照前缀分为四类!
1、以user开头的数据字典:
包含用户拥有的相关的对象信息。能够查到对象的所有者是当前的所有对象
2、以all开头的数据字典:
能够查询当前能所有有访问权限的对象信息
3、当dba开头的数据字典:
只能有dba权限的用户查询,能查到数据库中所有的对象。
4、以v$开头的是动态服务性能视图。
4、数据字典内容包括:
例如:
1.查看当前用户的拥有的对象名和对象类型
2、查看当前用户下的所有表
3、查看当前用户所定义的所有的约束的姓名和类型
4、查找约束姓名和关联列的名字
16)、DML数据操作语言DML
数据操作语言:
insert update delete
事务控制语言:
commit :提交事务
rollback :回滚事务
Savepoint:设置回滚点
1.insert语句
两种格式:
直接插入
子查询插入
直接插入基本语法:
note:
2.使用子查询插入,
和子查询创建不同的是,这里不需要as 关键字,并且不需要出现values
note:
2.delete语句:
语法:delete [from] tbl_name [where option…]
note:在加外键约束的时候,如果想在删除主表的记录的同时对外键表中已经存在的关联关系记录进行操作可以使用下面两个关键词:
on delete cascade:级联删除,删除主表记录,外键表的关联记录一块儿删除
on delete set null:删除主表记录,外键表的关联记录该列的值变成null
如果关联的外键被删除,本表外键的位置会被弄成空,而不会被删除
3.update 语句:
语法:update table_name set column=value,[column=value]
[where condition…];
note:
1.如果不加条件,默认修改表中所有的行。
17)、Oracle事务
1、事务的基本
当一个sql命令执行一个事务就开始了,当遇到一下情况,事务自动完成
note:
commit:提交事务,提交事务是指让这个事务里面的所有操作都生效到数据库中
rollback:回滚事务,回滚事务是指让这个事务里面的所有操作都撤销
事务控制使用:commit,savepoint,rollback;
2、事务的ACID原则:
4、事务隔离级别
为了处理这些问题,SQL标准定义了以下几种事务隔离级别
READ UNCOMMITTED 幻想读、不可重复读和脏读都允许。
READ COMMITTED 允许幻想读、不可重复读,不允许脏读
REPEATABLE READ 允许幻想读,不允许不可重复读和脏读
SERIALIZABLE 幻想读、不可重复读和脏读都不允许
Oracle数据库支持READ COMMITTED 和 SERIALIZABLE这两种事务隔离级别。所以 Oracle不支持脏读
5、持久性:事务提交后,能够持久性影响数据库。
6、隐式事务提交:
1.DDL语句(create..),执行commit
2.DCL语句(gant….),执行commit
3.正常退出终端。
7.事务提交或者回滚之前的状态
1.因为数据库缓存区的存在,数据前一次的状态可以被回复
2.当前用户可以会看使用DML操作的数据的结果,但是其他用户不能看到当前用户的DML操作结果
3.所有受影响的行会被锁定,其他用户不能修改。
8.显示结束事务
commit:之前所做的所有会影响数据库的操作,都会对数据库产生持久的影响。
rollback:取消之前所做的所有操作
18)、修改表结构和约束
添加列不需要关键字column,删除列需要关键字column,修改列用的modify
重命名列的时候rename也需要加关键字column
涉及到的约束添加,删除,约束生效,无效,都需要constraint
目标:
用到的命令:
功能:
1.增加列
语法:
//添加新的一列
//添加新的多列
//添加带有约束的列
2.删除列:
3.修改列属性:(数据类型和约束使用modify)
可以间接性的设置约束,前提是约束必须是不违背当前表里面已有的值
4.增加约束
语法:alter table tb_name add 约束的完整定义
5.删除约束:只能通过约束名字删
语法:alter table tb_name drop 约束名。
删除主键约束时,同时删除和他依赖的外键约束
6.使一个约束失效:
语法:alter table tb_name disable constraint constraint_name [cascade];
note:添加cascade表明要让所有的依赖约束都失效。
7.是一个约束生效:
语法:alter table tb_name enable constraint constraint_name;
note:
1.当启用unique和primary key约束时,会自动创建索引。
//但需要注意的是,数据必须不能违反主键要求!否则不能启用
//只有让原来的数据满足约束条件,才可以开启
8.删除表:
//先为一个表添加父类的外键,然后删除,外键约束直接被删掉了
9.重命名:rename
重命名表:
重命名列:
10.截断表:truncate
语法:truncate table tb_name 语法和drop一样,作用却和delete一样
note:
11.给表加注释:comments
语法:
comments on 表名 is ’内容’
Comments on column表明.列名 is ‘内容’
给表添加注释
给列添加注释
note:
1.添加的注释可以在如下数据字典中查看
所有列的注解
当前用户列的注解
当前所有的表的注释
当前用户表的注释
例如:
19)、创建序列(自动增长)
概念:
所谓序列,在oracle中就是一个对象,这个对象用来提供一个有序的数据列,这个有序的数据列的值都不重复。
查看当前用户的sequence表
创建序列语法:
代表当前的初始值为1,每次增长为1,缓存三个
序列的属性(伪列):
1.nextval : 返回下一个可用的序列值。
通过序列名.nextval获得
2.currval :获取序列当前的值。
通过数据字典查定义的序列
默认缓存是这么大的,默认缓存大小是20
当使用缓存的时候,每次调用序列的nextval就可以让当前值加一,直到当前值等于缓存值的时候,缓存在加上定义缓存的值
使用sequence:
例如:
1.向表中插入数据
2.查看序列的当前值
3.获取序列的下一个值。
缓存:
使用缓存可以提高sequence的访问效率
修改sequence:
只要从新修改了序列,缓存大小,就又开始从1开始自增加了
删除sequence:
20)、创建视图View
概念:
视图:所谓视图就是提取一张或者多张表的数据生成一个映射,管理视图可以同样达到操作原表 的效果,方便数据的管理以及安全操作。
视图的存储:
视图的优势:
视图的分类:
视图的创建:(说到这里,在as关键字出来在别名的时候用,在子查询建表的时候也会用到)
note:
要想创建view不需要有权限,创建权限需要是dba身份下
代表不存在也要创建
换句话说,加上该关键词表示对view进行dml操作的时候,只能操作select语句 中where条件限制的内容
感觉类似于子查询创建表一样,只不过把table 变成了or replace view
此时可以使用:
1.查看视图中所有数据信息
2.执行插入:(创建的时候不加with check option,是可以操作除视图查询条件以外的值)
3.再次查看,找不到刚插入的数据,因为这条数据不满足id<=4,但是查看原始表s_emp,有这条数据。
注意可以取别名,但是要注意,uid也属于关键字!
此时可以使用:
1.查看视图中所有数据信息
2.执行插入:
创建复杂视图:
子查询不许包含order by,而且复杂视图不能做DML操作
复杂视图可能包含分组,组函数,多表连接等。
例如:
查看视图信息
可以使用数据字典user_views;
删除视图对象:
21)、索引Index
概念:
oracle常常是用B树来存储索引
1. 类似书的目录结构
2、 Oracle 的“索引”对象,与表关联的可选对象,提高SQL查询语句的速度
3、 索引直接指向包含所查询值的行的位置,减少磁盘I/O
4、 与所索引的表是相互独立的物理结构
5、 Oracle 自动使用并自动维护索引,插入、删除、更新表后,自动更新索引
创建:
1.自动创建
当在表中指定了primary Key或者unique约束时会自动创建唯一值索引。
2.用户创建。
用户可以创建非唯一值所在以提高在访问行时的效率。
语法:
创建索引的原则:
1.列经常作为where子句的限定条件或者作为连接条件
2.列包含的数据量很大,并且很多非空的值。
3.两个或者更多列频繁的组合在一起作为where的限定条件或者连接条件
4.列总是作为收索条件
5.索引查出的数据量占2%~4%
6.索引不是越多越好,不是索引越多越能加速查找。
7.要索引的表不经常进行修改操作
删除索引:
强制唯一的主键无法删除索引,注意是唯一!!
22)、系统权限
权限允许用户访问属于其它用户的对象或执行程序,
ORACLE系统提供权限:Object 对象级、System 系统级
查看权限的数据字典:
1.系统权限(系统权限是对用户而言):
1,可以创建用户
2. 赋予权限:
一个用户应该具有的基本权限包含:
例如,我们当初在进行操作时写的:
更多权限赋值
– Create the user
– Grant/Revoke role privileges
– Grant/Revoke system privileges
3.回收权限(可以回收用户赋值的角色的权限,或者单独某一个权限)
语法:revoke xxx from user_name;
例如:
4.修改密码:
5.删除用户:
6.对象权限(针对对象,类似表对象等):
对象权限:select, update, insert, alter, index, delete, all //all包括所有权限
对象的拥有者拥有所有的权限。
容许另一个同意后,就可以查询,另一个表的数据了
设置的权限具体到列上
grant update(id) on s_emp to jd1613;
给jd1613赋予能够更新s_emp表上id列的权限。
7.创建同义词: 相当于给对象起别名
语法:
例如:
8.删除同义词:
语法: drop synonym syn_name;
例如:
drop synonym emp;
9.导出数据库
exp,imp不属于sqlplus的命令,所以不是在sqlplus终端执行的。
系统终端:exp userid=briup/briup full=y file=briup.dmp
一路回车
导入:imp userid=briup/briup full=y file=briup.dmp;
导入的前提是必须要有用户呀!是在window终端下执行的
23)、添加表和列注解
Oracle添加注释的语法为:
comment on column 字段名 is ‘注释名’;
举例:
添加表注释:
终于做完了了!!2016-9.9 23点
二、Oracle高级补充
一、Oracle安装
Oracle 数据库如果要想安装请准备出 5G 空间,同时也要清楚一些常见的 Oracle 版本:
· Oracle 8、Oracle 8i:其中“i”表示的是 internet,表示 Oracle 开始向网络发展,1CD;
· Oracle 9i:是 Oracle 8i 的稳定版,也是现在见到最多的版本、3CD;
· Oracle 10g:表示 Oracle 开始基于网格计算推出的数据库,1CD;
· Oracle 11g:是 Oracle 10g 稳定版,现在也算是最主流推广的版本,2G 左右;
· Oracle 12C:“C”表示的是云计算的概念,是现在的最新版本。
对于 Oracle 而言,本身的软件提供的只是一个平台,而在这个平台之上才会进行数据库的管理,那么此时选择的是“创建和配置数据库”就表示在软件安装完成之后会自动的进入到一个新的数据库的创建和配置过程。
在进行 Oracle 安装的时候会询问用户安装的类型,默认的单机数据库选择的是“单实例数据库”,而对于 RAC 属于Oracle 之中比较高级的数据库管理话题,有兴趣的话可以继续再花费 2W 块钱自己学习。
选择“高级安装”可以进入到一些数据库的基础配置界面。
本数据库之中所使用的语言提供有两种“简体中文”,英语。
本次选择安装的版本为企业版
本次将 Oracle 数据库安装在了“D:\app\Teacher”
由于在一开始选择了“创建数 据库”,所以此时会 询问用户要创建的数据 库名称,将名称修改 为“mldn ”,同时可以
发现有一个 Oracle 服务标识符( SID)跟数据库名称完全一样,其中 SID 为日后程序开发之中使用的服务编号,如果没有 此编号,那么程序将无法进行数据库的连接,一般 SID 都和数据库名称保持一致。
在日后的实际开发之中,所使用的编码一定是“UTF-8”编码,在进行 Oracle 安装的时候一定要选择好此编码,否 则日后就可能出现程序的乱码问题。
同时在“示例方案”上选择“创建具有示例方案的数据库”,这样就会出现相应的测试数据,供学习使用,如果没有
选中,则没有相应数据出现。
在Oracle 之中有两个主要的管理员用户:SYS(超级管理员)、SYSTEM(普通管理员),此时就需要配置这些管理员
帐号的密码,但是现在为了方便起见,将所有的管理员密码都统一配置为“oracleadmin”。(但是在新版本的数据库之中, 这样的密码是不符合要求的)。
随后进入到安装前的系统检查,如果此时有错误了,请选择“忽略”。
随后开始进入到 Oracle 的安装程序界面。
当安装完成之后(实际上,此时 mldn数据库也已经配置完成了),但是数据库配置完成之后必须进行一些用户名和 密码的设置。
首先进入到“口令管理”界面,进行以下四个用户名和密码的修改:
此时选择“确定”才表示安装已经完成。在 Oracle 安装完成之后会回到 Oracle 安装的主界面,选择“关闭”。
当Oracle 安装完成之后会自动的在 windows 服务里面进行 Oracle 相关的服务注册,有如下的几个:
但是这些服务默认情况下大 部分都是采用了“ 自动”启动的方式 ,如果你电脑快的 话,电脑启动时没 有影响,但是 建议都将其修改为手工方式,在需要的时候再进行启动。而对于开发者而言,如果要使用 Oracle 进行开发,只需要两个:
二、SQLPLUS 基本命令(重点)
当 Oracle 安装完成之后,用户可以直接在运行窗口处输入“sqlp lus.exe”命令,启动 Oracle 数据库的操作窗口。
输入了正确的用户名和密码就可以直接进入到 Oracle。但是进入到了 sqlp lus 里面还需要使用一些基本的操作命令。
1、显示格式化操作
· 在数据库之中最重要的组成就是数据表(表的结构就是行列的集合),那么下面可以查询一个 emp 的数据表:
SELECT * FROM emp ;
现在发现以上的显示效果不好,所以使用两个命令操作:
· 设 置 每 行显示的数据长 度:SET LINES IZE 300;
· 设 置 每 页显示的数据行 数:SET PAGES IZE 30;
2、调用记事本命令
有些时候在进行 SQL 程序编写的时候,往往需要编写很多行,那么如果只在命令行下就无法处理了。这个时候往往 会调用本机的记事本程序,用户直接按照“ed文件名称”(ed mldn)。
一般后缀名称为*.sql 的都称为数据库脚本文件。
3、切换用户
在 Oracle 里面之前一共提供有四个用户,这四个用户之间的切换可以使用如下的语法完成:
CONN 用户名/密码 [AS SYSDBA]
如果现在使用的是 SYS 帐号登录,那么必须要写上“AS SYSDBA”,而登录之后可以通过“SHOW USER”来查看 当前的登录用户是那一位。
范例: 使用 sys 登录
范例: 使用 scott 登录
4、调用本机命令
COPY 源文件路径 目标文件路径
如果要想在本机调用的话:前面要加上一个 HOST。 范例: 调用本机的 cop y 命令
以上只是一些最基础的操作命令,日后还会接触到其它命令。
5、总结
1、 数据库的安装;
2、 记下数据库之中四个主要的用户信息:
3、 sqlplus 的基本命令要熟悉;
三、sql 查出一张表中重复的所有记录数据
1、在面试的时候碰到一个 问题,就是让写一张表中有id和name 两个字段,查询出name重复的所有数据,现在列下:
2、查询出所有数据进行分组之后,和重复数据的重复次数的查询数据,先列下:
3、一下为 查看别人的 结果,现列下:查询及删除重复记录的方法大全
1、查找表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断select * from people
where peopleId in (select peopleId from people group by peopleId having count(peopleId) > 1)
2、删除表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断,只留有rowid最小的记录
3、查找表中多余的重复记录(多个字段)
4、删除表中多余的重复记录(多个字段),只留有rowid最小的记录
5、查找表中多余的重复记录(多个字段),不包含rowid最小的记录
四、例子
1、比方说
在A表中存在一个字段“name”,
而且不同记录之间的“name”值有可能会相同,现在就是需要查询出在该表中的各记录之间,“name”值存在重复的项;
方法一declare @max integer,@id integerdeclare cur_rows cursor local for select 主字段,count() from 表名 group by 主字段 having count() >; 1open cur_rowsfetch cur_rows into @id,@maxwhile @@fetch_status=0beginselect @max = @max -1set rowcount @maxdelete from 表名 where 主字段 = @idfetch cur_rows into @id,@maxendclose cur_rowsset rowcount 0
方法二"重复记录"有两个意义上的重复记录,一是完全重复的记录,也即所有字段均重复的记录,二是部分关键字段重复的记录,比如Name字段重复,而其他字段不一定重复或都重复可以忽略。
1、对于第一种重复,比较容易解决,使用select distinct * from tableName 就可以得到无重复记录的结果集。 如果该表需要删除重复的记录(重复记录保留1条),可以按以下方法删除select distinct * into #Tmp from tableNamedrop table tableNameselect * into tableName from #Tmpdrop table #Tmp 发生这种重复的原因是表设计不周产生的,增加唯一索引列即可解决。
2、这类重复问题通常要求保留重复记录中的第一条记录,操作方法如下 假设有重复的字段为Name,Address,要求得到这两个字段唯一的结果集select identity(int,1,1) as autoID, * into #Tmp from tableNameselect min(autoID) as autoID into #Tmp2 from #Tmp group by Name,autoIDselect * from #Tmp where autoID in(select autoID from #tmp2) 最后一个select即得到了Name,Address不重复的结果集(但多了一个autoID字段,实际写时可以写在select子句中省去此列)
查询重复
三、PL\SQL
PL/SQL
一 简介
PL/SQL表示SQL的过程式语言扩展(Procedural Language Extension to SQL)。是对SQL的扩充,它吸收了高级语言的许多最高设计特点:如数据封装性、信息隐蔽性、重载等。它允许SQL的数据操纵语言和查询语句包含在块结构
(block_structured)和代码过程语言中,使PL/SQL成为一个功能强大的事务处理语言。
1、为什么使用PL/SQL?
2、优点:
1.提升系统的性能
2.良好的可维护性和可移植性
3.流程控制
4.安全性高
3、缺点:
4、开发环境:
二 PL/SQL程序结构
例如:
1、第一个PLSQL语句
打开输出:set serverout on;或者set serveroutput on–这个语句是用来管理输出的,没有这句话不会把HelloWorld打印到控制台
2、plsql基本语法
3、PLSQL的注释:
4、标识符命名规则:
注:PLSQL对大小写不敏感
5、PLSQL的变量声明
变量名 [CONSTANT] 变量类型 [NOT NULL] [:=初始值]
常量定义:
6、PL/SQl中变量的作用域和可见性
7、PLSQL转义字符: ’ (单引号)
8、字段类型RowType和type
给单个值赋值类型Type
给多个值赋值类型RowType
两个结果都是一样的
三 PLSQL数据类型
1、第一个练习:
2、第二个练习:手动输入要查询的值
(1)标量类型:
数字型:
1.NUMBER
2.BINARY_INTEGER
3.binary_float和binary_double定义的常量
字符型:
常用:CHAR VARCHAR VARCHAR2(STRING)
1、long和longraw
2、rowid和urowid
时间类型
1、date
2、timestamp
Oracle中TIMESTAMP时间的显示格式
Oracle中的TIMESTAMP数据类型很多人用的都很少,所以即使最简单的一个查询返回的结果也会搞不清楚到底这个时间是什么时间点。
例如:
27-1月 -08 12.04.35.877000 上午
这个时间到底是几点呢?中午12:04分,那就错了,其实使用to_char函数转换后得到如下结果:
2008-01-27 00:04:35:877000
说明这个时间是凌晨的00:04分,而不是中午的12:04分。
发生此问题的原因如下:
示例:
首先把一个00:05分的时间进行转换,按照’yyyy-mm-dd hh:mi:ss am’格式进行转换,得到的结果是:
2008-01-29 12:05:10 上午
这说明Oracle在进行日期转换成字符串的过程中,如果小时转换使用的是12进制的格式,则凌晨00点会被认为是上午12点,然后才是上午1点、 2点、3点。。。oracle中12进制的计时不是从0-11,而是从1-12的,所以如果是夜里零点,你不能记成1点,那只能记成12点了。(不知道这 是不是跟洋人的习惯有关?)
现在我们来看一下Oracle中对TIMESTAMP的处理:
返回结果DD-MON-RR HH.MI.SSXFF AM,可以看到,这里默认情况下,使用的TIMESTAMP的格式是12进制的小时。
问题到这里已经找到根源了。
解决方法:
3、interval
–时间间隔+016-11
–当前时间戳+时间间隔:21-11月-33 03.47.42.836000000 下午 +08:00
–时间日期+时间间隔21-11月-33
(2)组合类型
1.RECORD记录类型,包含多个标量类型
使用前,首先进行定义
声明RECORD变量
RECORD属性访问
两个类型相同的RECORD变量可以相互赋值
当RECORD中属性名与select的类型相同,可以直接进行into赋值
2.%ROWTYPE 返回一个基于数据库表定义的类型
注:%rowtype和record的区别
3.PL/SQL表(TABLE类型)
类似数组功能的变量类型,包含一组数据,通过下标的方式访问数据。
定义一个TABLE类型:
TABLE中元素的类型(member_type)可以是复合类型
如果元素i还没有创建就被引用,会抛出异常(ORA-1403: No data found)
(3)运算符
1、赋值运算符
4、连接运算符
3、关系运算符
4、逻辑运算符
–逻辑运算符
四 控制语句
控制语句:条件语句 循环语 句 GOTO语句(不建议使用)
1、条件语句 if case ..
–程序控制 if
–数量大于十条!!
练习一:
判断一个表中记录条数是奇数还是偶数。
练习二:
–练习if,提示用户输入编号判断当前用户工资情况
练习三:
–根据雇员的id查到所在部门,根据所在的部门上涨工资
–要求最高不超过5000,超过5000就按5000算
2、between and
3、in
4、like
5、case
6、内部程序块
–内部程序块
7、异常处理
异常处理流程
1).编译时异常
2).运行时异常
3). 异常处理,需要使用exception
4). 处理赋值异常
–处理赋值异常2 no_data_found 当找不到的数据的时候
5).返回数据过多异常
–处理异常3 返回数据过多!
6).用户自定义异常
–用户自定义异常
/*输入 inputdata 的值: 21
原值 5: v_data :=&inputData;–输入数据
新值 5: v_data :=21;–输入数据
输入数据有问题!!
sqlcode:1
sqlerrm:User-Defined Exception
*/
–用户自定义异常2,设置sqlcode ,抛出异常,保证sqlcode编码要一致才可以抛出
/*
输入 inputdata 的值: 21
原值 6: v_data :=&inputData;–输入数据
新值 6: v_data :=21;–输入数据
输入数据有问题!!
sqlcode:-20789
sqlerrm:ORA-20789:
*/
7).构建动态异常
–构建动态异常
–练习,利用pl/sql动态的为部门表添加信息,如果id存在,则抛出异常提示,id存在
8).预定义异常
五 循环语句
1. LOOP简单循环
格式如下:
LOOP
…
–使用IF与EXIT配合进行退出
1、练习1
–循环语句
2、练习2
2. WHILE循环
—while循环
3. FOR循环
4、循环的选择:
FOR循环:用于明确循环次数的使用
WHILE循环:用于条件判断的循环
LOOP循环:类似JAVA中的do while循环,首先进行一次操作
六、记录类型(Record)
1、什么是记录(Record)?
记录可以直接赋值。RECORD1 :=RECORD2;
记录不可以整体比较.
记录不可以整体判断为空。
2、%ROWTYPE和记录(Record)?
请区别%ROWTYPE和记录(Record)类型。%ROWTYPE可以说是Record的升级简化版。
Record + PL/SQL表可以进行数据的多行多列存储。
3、如何创建和使用记录?
①创建记录类型
语法:
其中,filed1是标量的名字。
②声明记录类型变量:
③填充记录。
④访问记录成员
注意:
语法:
例子:记录可以整体赋值
例子:记录不可以整体比较,只可以比较记录字段
例子:记录不可以整体判断为空,只可以判断记录字段。
例子:使用%TYPE和%ROWTYPE动态指定记录字段。
例子:数据集中的记录和记录类型中的数据关系。
4、使用记录向表中插入数据?
根据表结构合理安排记录字段。比如主外键。
如果用记录(RECORD)插入数据,那么只能使用记录成员;
如果用%ROWTYPE插入数据,可以直接使用%ROWTYPE。
例子:使用记录成员向表中插入数据
5、使用记录更新数据?
如果用记录(RECORD)更新数据,那么只能使用记录成员;
如果用%ROWTYPE更新数据,可以直接使用%ROWTYPE。
例子:使用%ROWTYPE向表中插入数据
6,使用记录删除数据?
删除记录时,只能在delete语句的where子句中使用记录成员。
七、索引表
索引表
–索引表用rowtype
–索引表用record
七、嵌套表
创建嵌套表类型
–新建表内嵌表类型
八、可变数组
可变数组
–定义简单类型的可变数组
–oracle10g drop表后并没有彻底的删除表,而是把表放入回收站,可以用purge完全删除
十、集合运算符
集合运算符
–验证cardinality函数
–验证set取消重复
–验证entry(是否为空)运算符
–验证member of 运算符,判断字符串是否存在
–验证multiset except –找到两个集合中不同的数据
–验证multiset intersect –找到两个集合中相同的数据
–验证multiset union –合并两个集合的数据
–验证是不是子集合
十一、集合函数
–使用delete函数删除一个数据
–使用delete函数删除一个范围数据
–判读数据是否存在EXISTS
–扩充集合长度(x打印的是数字也就是次数)
–获取索引表长度
–索引表数据不是连续的,first获取第一个索引
–验证索引表数据不是连续的
–集合函数trim删除最后一个数据
十二、嵌套表,索引表,可变数组区别
两个表通常使用外键建立数据之间的关联,相对于这样的方式访问数据库,存储在集合中的数据可以更快的被访问。常用的集合类型:
index-by表(索引表)
嵌套表
可变数组
1、index-by表(索引表)
index-by表类似C语言中的数组,但是元素顺序并没有按照特定的顺序排列。元素的个数只受到BINARY_INTEGER的下标大小限制。
–typetable:定义的新类型类型名
–type:定义index-by表的类型
–声明使用类型
–声明变量
–赋值操作
调用没有赋值的元素
–上面赋值的时候只赋了5个值,但是取值的时候取了6个值,报错
–:未找到数据
2、嵌套表
嵌套表和index-by表相比少了index by binary_integer子句。这也是区分两种表的区别。
–嵌套表声明语法
–嵌套表的初始化
3 index-by表:
如果声明类型之后,再声明一个index-by表变量类型,如果没有给该表赋值,那么这个表就是空的,后面可以继续添加
4 嵌套表:
声明嵌套表变量类型时,如果表中没有任何元素,会初始化为null,并且是只读的,如果再添加元素就会出现错误
ERROR
初始化为null后添加元素:引用未初始化的收集
初始化赋值后添加元素:下标超出数量
元素的序列
嵌套表和index-by表很相似,但是嵌套表在结构上是有序的,index-by表是无序的,给嵌套表赋值,下标从1开始,而且依次递增。
上面赋值后的下标依次是:1,2,3,4,5,6
3、可变数组
可变数组声明
—数组声明语法—
type type_name IS {varray|varying array}(maxinum_size)
OF element_type[not null];
–type_name:可变数组的类型名
–maxinum_size:可变数组元素个数的最大值
–element_type:数组元素的类型
—创建一个数组—
–包含星期数组
–包含月份数组
—数组的初始化—
4、集合的属性和方法
index-by表,嵌套表,可变数组是对象类型,本身具有属性和方法。
count:返回集合中数组元素的个数
delete:删除集合中一个或多个元素
delete—删除所有元素
delete(x)—删除第x位置的元素
delete(x,y)—删除两个位置之间的元素
extist:判断集合中元素是否存在
extists(x)—判断x位置的元素是否存在
extend把元素添加到集合末端
extend把一个null元素添加到集合中
extend(x)—将x个null元素添加到集合的末端
extend(x,y)—将x个位于y的元素添加到集合的末端
first和last:first返回集合的第一个元素位置,last返回集合的最后一个元素位置
limit:返回集合中最大元素的个数,嵌套表没有上限,返回null
next(x),prior(x):返回x处元素的前后的元素
trim:删除几个末端的元素
trim—从几个末端删除一个元素
trim(x)—从几个末端删除x个元素,x小于集合的count总数
十三、存储过程PROCEDURE
1、匿名语句块:
不能存储于数据库之中
每次执行都需要重新编译
不能被其他模块调用
2、命名语句块:
编译并存储于数据库中
可以在其他地方调用
可以输入输出参数
3、命名语句块包括:
(1)存储过程 PROCEDURE
(2)函数 FUNCTION
(3)触发器 TRIGGER
(4)包 PACKAGE
4、存储过程创建语法:
参数类型:
IN:只读
OUT:只写
IN OUT:可读可写
存储过程的使用:
注意:存储过程传参数时不能指定形参的长度,只有类型。
形参类型有三种:in. out. in out.默认为in
注:IN OUT或OUT参数对应的实际参数必须是变量,
不能是常量或表达式。
5、调用方式:
1.直接执行:
2.在其他地方调用
3.call my_procedure();
4.利用jdbc调用存储过程:
6、传参方式:
位置标示法
调用时添入所有参数,实参与形参按顺序一一对应
名字标示法
调用时给出形参名字,并给出实参
7、删除过程:
8、查看过程、函数内容:
9、存储过程计算区域的例子
–最终版!!!递归解决
十四、FUNCTION函数
1、函数与存储过程相同点:
都有名字
都有统一的形式:
都可以存储在数据库中声明,执行与异常处理
2、差别:
存储过程调用 本身是一个PL/SQL语句
函数调用 则是PLSQL语句的一部分
函数有返回值而存储过程没有
函数可以在SQL语句中调用
1、标识符不同。函数的标识符为FUNCTION,过程为:PROCEDURE。
2、函数中一般不用变量形参,用函数名直接返回函数值;而过程如有返回值,则必须用变量形参返回。
3、过程无类型,不能给过程名赋值;函数有类型,最终要将函数值传送给函数名。
4、函数在定义时一定要进行函数的类型说明,过程则不进行过程的类型说明。
5、调用方式不同。函数的调用出现在表达式中,过程调用,由独立的过程调用语句来完成。
6、过程一般会被设计成求若干个运算结果,完成一系列的数据处理,或与计算无关的各种操作;而函数往往只为了求得一个函数值
function 可以使用在表达式中 x := func();procedure不能
function 可以做为表达式 select func() from dual;procedure 不能
function 不能BEGIN func();END;;procedure 可以
3、RETURN的使用:
与其他语言的RETURN相同
PLSQL的FUNCTION要求必须拥有一个要执行到的RETURN
当有异常处理部分的时候,必须在每种异常处理部分(when .. then ..)有一个return
函数的plsql块中调用:
4、函数的sql语句中的调用
函数的删除:
十五、PACKAGE包
如果要在oracle中定义包,那么需要定义两个组成部分
包规范:相当于java中的接口。
包体:相当于java接口的实现类
包是可以将逻辑上相关的对象存储在一起的PL/SQL结构
包中可以包括:
声明部分出现的任何东西都能出现在包中。
包中的内容可以在其他地方使用或调用,是全局的内容。
PACKAGE内容包括:包头、包体
使用:
包名.函数名
包名.过程名
例如:
注:包头与包体分开创建,只有包头创建成功才可以创建包体。
1、创建包头:
2、创建包体:
3、包中内容的使用:
4、包的第一个例子
–定义包
–此时返回的是多条记录,所以使用了强类型的游标变量进行的操作,但是只有包规范还是无法使用包体,包体的名字一定要和包规范统一的。
–范例:定义包体
–列object_type是包类型,有PACKAGE和PACKAGE BODY
–条件就是上一部对象名字
– Created on 2017/1/5 by SHINE
5、包的第二个例子,包的作用域
–包的作用域
–在包规范中定义一个变量
–给从新赋值,下面两个一起执行才能有结果,要不找不到
5、Oracle的第三个例子,存储过程重载
–重载包中的子程序
注意:当重载的存储过程参数类型或者参数数目不一致时,就会报错哦!
正确结果:
十六、触发器TRIGGER
后续补充
十七、动态SQL
1、在Oracle中执行动态SQL的几种方法
在一般的sql操作中,sql语句基本上都是固定的,如:
但有的时候,从应用的需要或程序的编写出发,都可能需要用到动态SQl,如:
一、使用动态游标实现
1、声明动态游标
2、声明游标变量
3、使用游标
4、小结:
动态游标可以胜任大多数动态SQL的需求了,使用简洁方便居家旅行之必备杀人放火之法宝。
二、使用 EXECUTE IMMEDIATE
最早大家都使用DBMS_SQL包,但是太太麻烦了,最终都放弃了。但是自从有了EXECUTE IMMEDIATE之后,但要注意以下几点:
使用技巧
1. EXECUTE IMMEDIATE将不会提交一个DML事务执行,应该显式提交
2. 不支持返回多行的查询,这种交互将用临时表来存储记录(参照例子如下)或者用REF cursors.
3. 当执行SQL语句时,不要用分号,当执行PL/SQL块时,在其尾部用分号.
4. 在Oracle手册中,未详细覆盖这些功能。下面的例子展示了所有用到Execute immediate的可能方面.希望能给你带来方便.
5. 对于Forms开发者,当在PL/SQL 8.0.6.3.版本中,Forms 6i不能使用此功能.
EXECUTE IMMEDIATE用法例子
1. 在PL/SQL运行DDL语句
2. 给动态语句传值(USING 子句)
3. 从动态语句检索值(INTO子句)
4. 动态调用例程.
例程中用到的绑定变量参数必须指定参数类型.黓认为IN类型,其它类型必须显式指定
5. 将返回值传递到PL/SQL记录类型;
同样也可用%rowtype变量
6. 传递并检索值.INTO子句用在USING子句前
7.多行查询选项.
对此选项用insert语句填充临时表,用临时表进行进一步的处理,也可以用REF cursors纠正此缺憾.
8.实例一
Oracle 动态SQL
Oracle 动态SQL有两种写法:用 DBMS_SQL 或 execute immediate,建议使用后者。试验步骤如下:
2. 返回单条结果
3. 返回结果集
sql server 自定义函数的使用
自定义函数
用户定义自定义函数像内置函数一样返回标量值,也可以将结果集用表格变量返回
用户自定义函数的类型:
标量函数:返回一个标量值
表格值函数{内联表格值函数、多表格值函数}:返回行集(即返回多个值)
1、标量函数
Schemabinding :将函数绑定到它引用的对象上(注:函数一旦绑定,则不能删除、修改,除非删除绑定)
执行用户自定义函数
select 用户名。函数名 as 字段别名
select dbo.AvgResult(‘s0002’) as result
函数引用
select name from class where ccode = dbo.code(‘c001’)
2、表格值函数
a、 内联表格值函数
格式:
多句表格值函数包含多条SQL语句,至少有一条在表格变量中填上数据值
表格变量格式
对表格变量中的行可执行select,insert,update,delete , 但select into 和 insert 语句的结果集是从存储过程插入。
9.实例二
–1、存储过程不能直接写ddl语句
–2、使用动态sql写ddl语句
–EXECUTE IMMEDIATE 语句
在动态sql中execute immediate 是最重要的执行命令,使用此语句可以方便在pl/SQL程序之中执行
在EXECUTE IMMEDIATE 由以下三个主要语句组成:
INTO:保存动态sql执行的结果,如果返回多行记录可以通过bulk collect 设置批量保存:
USING:用来为动态SQL设置占位符设置内容
RETURNING|RETURN :两者使用效果一样,是取得更新表记录影响的数据,通过BULK COLLECT 来批量绑定
–设置绑定变量使用占位符
–练习一
–练习二
–练习三
–练习四(这个时候只能用拼接sql语句完成不能用占位符)
–练习四_2(这个是可以的)
–练习五returning用法
–练习六returning用法
–对于using和returning语句也可以设置参数模式,in,out,in out,默认的模式是in模式,而对于returning采用的是out模式
–希望动态执行的时候可以把p_deptno内容带回来
10.关于returning的几个问题:
ORACLE的DML语句中可以指定RETURNING语句。RETURNING语句的使用在很多情况下可以简化PL/SQL编程。
这里不打算说明RETURNING语句的使用(其实使用起来也很简单,和SELECT INTO语句没有多大区别。),主要打算说明RETURNING语句的几个特点。
其实这篇文章源于同事问我的一个问题:
使用UPDATE语句的时候,RETURNING得到的结果是UPDATE之前的结果还是UPDATE之后的结果?
这个问题把我问住了。考虑DELETE的情况,RETURNING返回的肯定是DELETE之前的结果,而考虑INSERT的情况,RETURNING返回的一定是INSERT之后的结果。但是UPDATE到底返回那种情况,就无法推断出来了。而且,由于一般在使用UPDATE的RETURNING语句时,都会返回主键列,而主键列一般都是不会修改的,因此确实不清楚Oracle返回的是UPDATE之前的结果还是之后的结果。
当然,一个简单的例子就可以测试出来:
显然,UPDATE操作的RETURNING语句是返回UPDATE操作之后的结果。
顺便总结几个RETURNING操作相关的问题:
1.RETURNING语句似乎和RETURN通用。
2.RETURNING语句也可以使用SQLPLUS的变量,这样,RETURNING语句不一定非要用在PL/SQL语句中。
3.INSERT INTO VALUES语句支持RETURNING语句,而INSERT INTO SELECT语句不支持。MERGE语句不支持RETURNING语句。
这两个限制确实不大方便。不知道Oracle在以后版本中是否会放开。
个人感觉RETURNING语句和BULK COLLECT INTO语句配合使用的机会更多一些。
十八、游标CURSOR
使用游标,用于提取多行数据集。
1、cursor的使用步骤
(1)、游标声明
(2)、打开游标
注:游标最多只能打开一次
(3)、从游标中取出数据 FETCH
游标常用属性:
注:%ROWCOUNT %FOUND %NOTFOUND均需要游标已打开
(4)、关闭
游标关闭后不允许FETCH
游标只能关闭一次
(5)、遍历CURSOR
1.简单LOOP
2.WHILE
3.FOR
注:使用FOR不需要对游标进行open,fetch与close
loop循环:
while循环遍历游标:
for循环遍历游标,显示薪水小于1000的员工的名字
(6)、带参数的CURSOR
声明:
使用:
(7)、自定义游标
声明:
使用: v_cur my_cursor;
2、细分隐式游标例子
–隐式游标1
–隐式游标2
–隐式游标3
–隐式游标4
–隐式游标5多行隐式右表,会返回多行记录
3、细分显示游标例子
–显式游标用while
–显式游标用loop
declare
cursor cur_emp is select * from s_emp;
v_empRow s_emp%rowtype;–保存一行数据
v_num number;
begin
–游标如果要操作一定要保证其已经打开了
if cur_emp%isopen then
null;–如果打开什么也不做。
else
open cur_emp;–然后打开
end if;
–默认情况下游标在第一行记录上
–隐式游标用for(注意for循环不能获得当前执行的次数,不能用%rowcount)
–显示游标用for(注意for循环的cur_emp不能获得当前执行的次数,不能用%rowcount只能用定义好的游标)
–利用索引赋值,在取值
十九、For Update Of
一、对比区别:
1 select * from TTable1 for update 锁定表的所有行,只能读不能写
2 select * from TTable1 where pkid = 1 for update 只锁定pkid=1的行
3 select * from Table1 a join Table2 b on a.pkid=b.pkid for update 锁定两个表的所有记录
4 select * from Table1 a join Table2 b on a.pkid=b.pkid where a.pkid = 10 for update 锁定两个表的中满足条件的行
5. select * from Table1 a join Table2 b on a.pkid=b.pkid where a.pkid = 10 for update of a.pkid 只锁定Table1中满足条件的行
for update 是把所有的表都锁点 for update of 根据of 后表的条件锁定相对应的表
———–
关于NOWAIT(如果一定要用FOR UPDATE,我更建议加上NOWAIT)
当有LOCK冲突时会提示错误并结束STATEMENT而不是在那里等待(比如:要查的行已经被其它事务锁了,当前的锁事务与之冲突,加上nowait,当前的事务会结束会提示错误并立即结束 STATEMENT而不再等待).
如果加了for update后 该语句用来锁定特定的行(如果有where子句,就是满足where条件的那些行)。当这些行被锁定后,其他会话可以选择这些行,但不能更改或删除这些行,直到该语句的事务被commit语句或rollback语句结束为止。
因为FOR UPDATE子句获得了锁,所以COMMIT将释放这些锁。当锁释放了,该游标就无效了。
就是这些区别了
二、关于锁定指定列和表效果一样
问题,如下:select * from emp where empno = 7369 for update; 会对表中员工编号为7369的记录进行上锁。其他用户无法对该记录进行操作,只能查询。select * from emp where empno = 7369 for update of sal; 这条语句是不是意味着只对表中的7369 这一行的sal字段的数据进行了上锁,其他数据则可以被其他用户做更新操作呢。学员测试结果为二条语句的效果是一样的。其他用户对整行都无法更新,那么是不是意味着 for update of columns这句没有什么意义呢?
通过这段代码案例,我们可以得到结论,for update of columns 用在多表连接锁定时,可以指定要锁定的是哪几张表,而如果表中的列没有在for update of 后面出现的话,就意味着这张表其实并没有被锁定,其他用户是可以对这些表的数据进行update操作的。这种情况经常会出现在用户对带有连接查询的视图进行操作场景下。用户只锁定相关表的数据,其他用户仍然可以对视图中其他原始表的数据来进行操作。
Oracle 的for update行锁
SELECT…FOR UPDATE 语句的语法如下:
SELECT … FOR UPDATE [OF column_list][WAIT n|NOWAIT][SKIP LOCKED];
其中:
OF 子句用于指定即将更新的列,即锁定行上的特定列。
WAIT 子句指定等待其他用户释放锁的秒数,防止无限期的等待。
“使用FOR UPDATE WAIT”子句的优点如下:
1防止无限期地等待被锁定的行;
2允许应用程序中对锁的等待时间进行更多的控制。
3对于交互式应用程序非常有用,因为这些用户不能等待不确定
4 若使用了skip locked,则可以越过锁定的行,不会报告由wait n 引发的‘资源忙’异常报告
现在我们看看执行如下操作将会发生什么呢?
在窗口1中执行:
在窗口2中执行:
三、游标用到修改删除数据
通过从游标工作区中抽取出来的数据,可以对数据库中的数据进行操纵,包括修改与删除操作。
要想通过游标操纵数据库,在定义游标的时候,必须加上FOR UPDATE OF子句;
而且在UPDATE或DELETE时,必须加上WHERE CURRENT OF子句,则游标所在行被更新或者删除。
一个FOR UPDATE子句将使所在行获得一个行级排他锁。
UPDATE或DELETE语句中的WHERE CURRENT OF子串专门处理要执行UPDATE或DELETE操作的表中取出的最近的数据。要使用这个方法,在声明游标时必须使用FOR UPDATE子串,当对话使用FOR UPDATE子串打开一个游标时,所有返回集中的数据行都将处于行级(ROW-LEVEL)独占式锁定,其他对象只能查询这些数据行,不能进行UPDATE、DELETE或SELECT…FOR UPDATE操作。
二十、Oracle系统工具包
1、系统自带工具包DBMS_OUTPUT包
–示例一、设置输出打开,enable和关闭disable
–示例二、设置缓冲区
–示例三、使用get_line()和get_lines()函数取回缓冲区数据
2、DBMS_ASSERT包
–示例四、为字符串的前后都加上单引号
–示例五、为字符串的前后都加上双引号,并且变为大写
–示例六、验证字符串是否为有效模式对象名
–示例七、输入错误的械对象
–示例八、验证字符串是否为有效模式名
–实例九,输入错误模式名
3、系统自带工具包DBMS.JOB包
–系统自带工具包DBMS.JOB包
–查询当前用户所有job
–查询当前job数据
–修改执行间隔,在cmd执行
–删除当前job,在cmd执行
4、系统自带工具包DBMS_LOB包
DBMS_LOB包提供了对大对象的操作支持,用户可以直接利用此包的实现对CLOB(大文本)或者BLOB(二进制数据例如:图片,音乐,文字等)类型的列进行操作
注意问题:
四、Oracle结构
其实,我前面一篇讲表空间的时候就介绍了数据库的结构,只是那个图只是简单的层次关系,这张图片看上去挺封复杂的,只要关注几个概念就行了。
Database(数据库) :数据库是按照数据结构来组织、存储和管理数据的仓库。
Tablespaces(表空间) :表空间是数据库的逻辑划分,一个表空间只能属于一个数据库。所有的数据库对象都存放在指定的表空间中。但主要存放的对象是表, 所以称作表空间。
Segments (段): 段是表空间的重要组织结构,段是指占用数据文件空间的通称,或数据库对象使用的空间的集合;段可以有表段、索引段、回滚段、临时段和高速缓存段等。
extents (盘区):是数据库存储空间分配的一个逻辑单位,它由连续数据块所组成。第一个段是由一个或多个盘区组成。当一段中间所有空间已完全使用,oracle为该段分配一个新的范围。
Data Block (数据块):是oralce 管理数据文件中存储空间的单位,为数据库使用的I/O的最小单位,其大小可不同于操作系统的标准I/O块大小。
五、Oracle数据泵导出的各种模式
exp,imp的使用
注: 在splplus环境下执行时,在命令前加 ! 号,这样 SQL> !exp … 和 SQL> !imp …
基本语法和实例:
1. EXP
有三种主要的方式(完全、用户、表)
1.1 完全
1.2 用户模式
1.3 表模式
2. IMP
具有三种模式(完全、用户、表)
1.1 完全:
1.2 用户模式:
1.3 表模式:
/*–示例
–只导出3张表的结构:
–连带数据导出:
–imp导入
**–实践
–只导出表结构**
–导出带数据的表(owner和tables不能同时使用)
–expdp,impdp的使用
数据泵导出的各种模式:
1、 按表模式导出:
2、按查询条件导出:
3、按表空间导出:
4、导出方案
5、导出整个数据库:
impdp导入模式:
1、按表导入
p_street_area.dmp文件中的表,此文件是以gwm用户按schemas=gwm导出的:
2、按用户导入(可以将用户信息直接导入,即如果用户信息不存在的情况下也可以直接导入)
3、不通过expdp的步骤生成dmp文件而直接导入的方法:
4、更换表空间
采用remap_tablespace参数
–导出gwm用户下的所有数据
注:如果是用sys用户导出的用户数据,包括用户创建、授权部分,用自身用户导出则不含这些内容
–以下是将gwm用户下的数据全部导入到表空间gcomm(原来为gmapdata表空间下)下
–导入命令:
导入:
导出:
数据泵导入实用程序提供了一种用于在 Oracle 数据库之间传输
数据对象的机制。该实用程序可以使用以下命令进行调用:
示例:
您可以控制导入的运行方式。具体方法是: 在 ‘impdp’ 命令后输入各种参数。要指定各参数, 请使用关键字:
USERID 必须是命令行中的第一个参数。
下列命令在交互模式下有效。
注: 允许使用缩写
备注:红色标记的选项是比较常用的,需知晓其用法。
操作实例
1、全库模式导入[full]
impdp orcldev/oracle directory=backup_path dumpfile=orcldev_schema.dmp full=Y table_exists_action=replace –如果表已经存在则进行替换操作。
一般来说,在还原数据库操作的时候,首先要删除这个用户,然后在进行impdp还原操作。
eg:
(1)SQL>DROP USER orcldev CASCADE;
(2)impdp orcldev/oracle directory=backup_path dumpfile=orcldev_2013.dmp full=Y
2、Schema模式导入[schema]
–还原orcldev这个方案(用户)
impdp orcldev/oracle directory=backup_path dumpfile=orcldev_schema.dmp schemas=orcldev table_exists_action=replace
3、表模式导入[table]
–还原某个用户下的具体的表
(1)windows版本:
impdp orcldev/oracle directory=backup_path dumpfile=orcldev_table.dmp tables=’TAB_TEST’ table_exists_action=replace
(2)unix版本:需要将’单引号进行转义操作
impdp orcldev/oracle directory=backup_path dumpfile=orcldev_table.dmp tables=\’ius_tran\’ table_exists_action=replace
4、表空间模式导入[tablespace]
impdp orcldev/oracle directory=backup_path dumpfile=orcldev_tablespace.dmp tablespace=user,orcldev
5、传输表空间模式导入[Transportable Tablespace]
(1)Oracle_Online
You cannot export transportable tablespaces and then import them into a database at a lower release level. The target database must be at the same or higher release level as the source database.
The TRANSPORT_TABLESPACES is valid only when the NETWORK_LINK parameter is also specified.
意思就说,目标库的版本要等于或者高于源数据库的版本,TRANSPORT_TABLESPACES参数选项有效前提条件是NETWORK_LINK参数需被指定。
查询数据库版本号SQL语句:SELECT * FROM v$version;
(2)创建数据库dbLink方法:
语法:
CREATE [PUBLIC] DATABASE LINK LINK_NAME
CONNECT TO Username IDENTIFIED BY Password
USING ‘ConnectString’;
注释:
1)创建dblink需要有CREATE DATABASE LINK或CREATE PUBLIC DATABASE LINK的系统权限以及用来登录到远程数据库的帐号必须有CREATE SESSION权限。
2)ConnectString指的是在tnsnames.ora文件中配置的监听名称。
3)当GLOBAL_NAME=TRUE时,dblink名必须与远程数据库的全局数据库名GLOBAL_NAME相同;否则,可以任意命名。
(3)查看GLOBAL_NAME参数方法:
SQL> show parameters global_name;
NAME TYPE VALUE
———————————– ———– ——————————
global_names boolean FALSE
6、REMAP_SCHEMA参数
众所周知:IMP工具的FROMUSER和TOUSER参数可以实现将一个用户的的数据迁移到另外一个用户。
(1)impdp数据泵使用REMAP_SCHEMA参数来实现不同用户之间的数据迁移;
语法:
与REMAP_SCHEMA类似的参数选项,如REMAP_TABLESPACE将源表空间的所有对象导入目标表空间。
将源表空间的所有对象导入到目标表空间中:REMAP_TABLESPACE=source_tablespace:target:tablespace
7、REMAP_TABLE参数
将源表数据映射到不同的目标表中
eg:impdp orcldev/oracle DIRECTORY=backup_path dumpfile=oracldev.dmp remap_table=TAB_TEST:TEST_TB
数据导入到TEST_TB表中,但是该表的索引等信息并没有相应的创建,需要手工初始化。
8、REMAP_DATAFILE参数
语法:REMAP_DATAFILE=source_datafile:target_datafile
Oracle_Online:
Remapping datafiles is useful when you move databases between platforms that have different file naming conventions. The source_datafile and target_datafile names should be exactly as you want them to appear in the SQL statements where they are referenced. Oracle recommends that you enclose datafile names in quotation marks to eliminate ambiguity on platforms for which a colon is a valid file specification character.
9、PARALLEL参数
使用PARALLEL参数可以提高数据泵还原的效率,前提是必须有多个expdp的文件,如expdp01.dmp,expdp02.dmp,expdp03dmp等等,不然会有问题。运行impdp命令时,会先启动一个WOrKER进程将METADATA导入,然后再启动多个WORKER进程将数据以及其他对象导入,所以在前期只会看到一个WOrKER在导入METADATA,而且IMPDP也需要DUMP文件是多个,也可以使用%U来进行导入。
而在11GR2后EXPDP和IMDP的WORKER进程会在多个INSTANCE启动,所以DIRECTORY必须在共享磁盘上,如果没有设置共享磁盘还是指定cluster=no来防止报错。
10、CONTENT参数
CONTENT参数选项有ALL,DATA_ONLY和METADATA_ONLY,默认情况是ALL。可以选择只导入元数据或者是只导入数据。
11、include、exclude、parfile、query和version参数选项与EXPDP命令的参数选项一致。
–数据泵备份(EXPDP命令)
(1)http://www.cnblogs.com/oracle-dba/p/3344230.html
(2)http://docs.oracle.com/cd/B19306_01/server.102/b14215/dp_export.htm#i1007829
六、常识
1、ANSI码(American National Standards Institute)
2、Oracle的表分析是做什么的?
分析的结果被Oracle用于基于成本的优化生成更好的查询计划。
那么,问题在于:Oracle的表分析需要经常进行吗?还是只要跑一回就可以一直有效了?
答:遇到当前表的查询或其他性能不好时,就可以对相应的表进行一次分析。1。如果你的表经常由几千万变成几百万,又变成几千万那么需要制定分析计划定期表分析,同时可以一并分析索引,计算索引中数据的分布情况,这样CBO会选择更加准确的执行计划。2。如果表结构变化了也要做下,也就是经常对表做dml就需要分析,现在推荐使用dbms_stats包。
七、Oracle行转列,列转行总结
1、这个比较简单,用||或concat函数可以实现
字符串转多列
实际上就是拆分字符串的问题,可以使用 substr、instr、regexp_substr函数方式
字符串转多行
使用union all函数等方式
2、wm_concat函数
首先让我们来看看这个神奇的函数wm_concat(列名),该函数可以把列值以”,”号分隔起来,并显示成一行,接下来上例子,看看这个神奇的函数如何应用准备测试数据
效果1 : 行转列 ,默认逗号隔开
效果2: 把结果里的逗号替换成”|”
效果3: 按ID分组合并name
sql语句等同于下面的sql语句
——– 适用范围:8i,9i,10g及以后版本 ( MAX + DECODE )
——– 适用范围:8i,9i,10g及以后版本 ( ROW_NUMBER + LEAD )
——– 适用范围:10g及以后版本 ( MODEL )
measures (cast(name as varchar2(20)) as str) rules upsert iterate(3) until(presentv(str[iteration_number+2],1,0)=0) (str[0] = str[0] || ‘,’ || str[iteration_number+1]) order by 1;
——– 适用范围:8i,9i,10g及以后版本 ( MAX + DECODE )
懒人扩展用法:
案例: 我要写一个视图,类似”create or replace view as select 字段1,…字段50 from tablename” ,基表有50多个字段,要是靠手工写太麻烦了,有没有什么简便的方法? 当然有了,看我如果应用wm_concat来让这个需求变简单,假设我的APP_USER表中有(id,username,password,age)4个字段。查询结果如下
/* 这里的表名默认区分大小写 /
利用系统表方式查询
3、Oracle 11g 行列互换 pivot 和 unpivot 说明
在Oracle 11g中,Oracle 又增加了2个查询:pivot(行转列) 和unpivot(列转行)
参考:http://blog.csdn.net/tianlesoftware/article/details/7060306、http://www.oracle.com/technetwork/cn/articles/11g-pivot-101924-zhs.html
google 一下,网上有一篇比较详细的文档:http://www.oracle-developer.net/display.php?id=506
pivot 列转行
测试数据 (id,类型名称,销售数量),案例:根据水果的类型查询出一条数据显示出每种类型的销售数量。
分组查询 (当然这是不符合查询一条数据的要求的)
行转列查询
注意: pivot(聚合函数 for 列名 in(类型)) ,其中 in(‘’) 中可以指定别名,in中还可以指定子查询,比如 select distinct code from customers
当然也可以不使用pivot函数,等同于下列语句,只是代码比较长,容易理解
unpivot 行转列
顾名思义就是将多列转换成1列中去
案例:现在有一个水果表,记录了4个季度的销售数量,现在要将每种水果的每个季度的销售情况用多行数据展示。
创建表和数据
列转行查询
注意: unpivot没有聚合函数,xiaoshou、jidu字段也是临时的变量
同样不使用unpivot也可以实现同样的效果,只是sql语句会很长,而且执行速度效率也没有前者高
XML类型
上述pivot列转行示例中,你已经知道了需要查询的类型有哪些,用in()的方式包含,假设如果您不知道都有哪些值,您怎么构建查询呢?
pivot 操作中的另一个子句 XML 可用于解决此问题。该子句允许您以 XML 格式创建执行了 pivot 操作的输出,在此输出中,您可以指定一个特殊的子句 ANY 而非文字值
示例如下:
如您所见,列 NAME_XML 是 XMLTYPE,其中根元素是 。每个值以名称-值元素对的形式表示。您可以使用任何 XML 分析器中的输出生成更有用的输出。
结论
Pivot 为 SQL 语言增添了一个非常重要且实用的功能。您可以使用 pivot 函数针对任何关系表创建一个交叉表报表,而不必编写包含大量 decode 函数的令人费解的、不直观的代码。同样,您可以使用 unpivot 操作转换任何交叉表报表,以常规关系表的形式对其进行存储。Pivot 可以生成常规文本或 XML 格式的输出。如果是 XML 格式的输出,您不必指定 pivot 操作需要搜索的值域。
八、索引原理
Oracle提供了大量索引选项。知道在给定条件下使用哪个选项对于一个应用程序的性能来说非常重要。一个错误的选择可能会引发死锁,并导致数据库性能急剧下降或进程终止。而如果做出正确的选择,则可以合理使用资源,使那些已经运行了几个小时甚至几天的进程在几分钟得以完成,这样会使您立刻成为一位英雄。这篇文章就将简单的讨论每个索引选项。主要有以下内容:
[1] 基本的索引概念
[2] 组合索引
特别注意:在Oracle9i之前,只有在使用到索引的前导索引时才可以使用组合索引!
[3] ORACLE ROWID
通过每个行的ROWID,索引Oracle提供了访问单行数据的能力。ROWID其实就是直接指向单独行的线路图。如果想检查重复值或是其他对ROWID本身的引用,可以在任何表中使用和指定rowid列。
[4] 限制索引
限制索引是一些没有经验的开发人员经常犯的错误之一。在SQL中有很多陷阱会使一些索引无法使用。下面讨论一些常见的问题:
4.1 使用不等于操作符(<>、!=)
下面的查询即使在cust_rating列有一个索引,查询语句仍然执行一次全表扫描。
把上面的语句改成如下的查询语句,这样,在采用基于规则的
优化器而不是基于代价的优化器(更智能)时,将会使用索引。
特别注意:通过把不等于操作符改成OR条件,就可以使用索引,以避免全表扫描。
4.2 使用IS NULL 或IS NOT NULL
使用IS NULL 或IS NOT NULL同样会限制索引的使用。因为NULL值并没有被定义。在SQL语句中使用NULL会有很多的麻烦。因此建议开发人员在建表时,把需要索引的列设成NOT NULL。如果被索引的列在某些行中存在NULL值,就不会使用这个索引(除非索引是一个位图索引,关于位图索引在稍后在详细讨论)。
4.3 使用函数
如果不使用基于函数的索引,那么在SQL语句的WHERE子句中对存在索引的列使用函数时,会使优化器忽略掉这些索引。 下面的查询不会使用索引(只要它不是基于函数的索引)
把上面的语句改成下面的语句,这样就可以通过索引进行查找。
4.4 比较不匹配的数据类型
比较不匹配的数据类型也是比较难于发现的性能问题之一。
注意下面查询的例子,account_number是一个VARCHAR2类型,
在account_number字段上有索引。下面的语句将执行全表扫描。
Oracle可以自动把where子句变成to_number(account_number)=990354,这样就限制了
索引的使用,改成下面的查询就可以使用索引:
特别注意:不匹配的数据类型之间比较会让Oracle自动限制索引的使用,
即便对这个查询执行Explain Plan也不能让您明白为什么做了一次“全表扫描”。
[5] 选择性
使用USER_INDEXES视图,该视图中显示了一个distinct_keys列。比较一下唯一键的数量和表中的行数,就可以判断索引的选择性。选择性越高,索引返回的数据就越少。
[6] 群集因子(Clustering Factor)
Clustering Factor位于USER_INDEXES视图中。该列反映了数据相对于已索引的列是否显得有序。如果Clustering Factor列的值接近于索引中的树叶块(leaf block)的数目,表中的数据就越有序。如果它的值接近于表中的行数,则表中的数据就不是很有序。
[7] 二元高度(Binary height)
索引的二元高度对把ROWID返回给用户进程时所要求的I/O量起到关键作用。在对一个索引进行分析后,可以通过查询DBA_INDEXES的B- level列查看它的二元高度。二元高度主要随着表的大小以及被索引的列中值的范围的狭窄程度而变化。索引上如果有大量被删除的行,它的二元高度也会增加。更新索引列也类似于删除操作,因为它增加了已删除键的数目。重建索引可能会降低二元高度。
[8] 快速全局扫描
在Oracle7.3后就可以使用快速全局扫描(Fast Full Scan)这个选项。这个选项允许Oracle执行一个全局索引扫描操作。快速全局扫描读取B-树索引上所有树叶块。初始化文件中的 DB_FILE_MULTIBLOCK_READ_COUNT参数可以控制同时被读取的块的数目。
[9] 跳跃式扫描
从Oracle9i开始,索引跳跃式扫描特性可以允许优化器使用组合索引,即便索引的前导列没有出现在WHERE子句中。索引跳跃式扫描比全索引扫描要快的多。下面的程序清单显示出性能的差别:
[10] 索引的类型
B-树索引
位图索引
HASH索引
索引编排表
反转键索引
基于函数的索引
分区索引
本地和全局索引
逻辑上:
Single column 单行索引
Concatenated 多行索引
Unique 唯一索引
NonUnique 非唯一索引
Function-based函数索引
Domain 域索引
物理上:
Partitioned 分区索引(全局索引和本地索引)
NonPartitioned 非分区索引
B-tree:
Normal 正常型B树
Rever Key 反转型B树
Bitmap 位图索引
索引结构:
B-tree:
适合与大量的增、删、改(OLTP);
不能用包含OR操作符的查询;
适合高基数的列(唯一值多)
典型的树状结构;
每个结点都是数据块;
大多都是物理上一层、两层或三层不定,逻辑上三层;
叶子块数据是排序的,从左向右递增;
在分支块和根块中放的是索引的范围;
Bitmap:
适合与决策支持系统;
做UPDATE代价非常高;
非常适合OR操作符的查询;
基数比较少的时候才能建位图索引;
树型结构:
索引头
开始ROWID,结束ROWID(先列出索引的最大范围)
BITMAP
每一个BIT对应着一个ROWID,它的值是1还是0,如果是1,表示着BIT对应的ROWID有值;
B*tree索引的话通常在访问小数据量的情况下比较适用,比如你访问不超过表中数据的5%,当然这只是个相对的比率,适用于一般的情况。bitmap的话在数据仓库中使用较多,用于低基数列,比如性别之类重复值很多的字段,基数越小越好。
关于分区表和分区索引(About Partitioned Tables and Indexes)对于10gR2而言,基本上可以分成几类:
Range(范围)分区
Hash(哈希)分区
List(列表)分区
以及组合分区:Range-Hash,Range-List。
对于表而言(常规意义上的堆组织表),上述分区形式都可以应用(甚至可以对某个分区指定compress属性),只不过分区依赖列不能是lob,long之类数据类型,每个表的分区或子分区数的总数不能超过1023个。
对于索引组织表,只能够支持普通分区方式,不支持组合分区,常规表的限制对于索引组织表同样有效,除此之外呢,还有一些其实的限制,比如要求索引组织表的分区依赖列必须是主键才可以等。
注:本篇所有示例仅针对常规表,即堆组织表!
对于索引,需要区分创建的是全局索引,或本地索引:
l 全局索引(global index):即可以分区,也可以不分区。即可以建range分区,也可以建hash分区,即可建于分区表,又可创建于非分区表上,就是说,全局索引是完全独立的,因此它也需要我们更多的维护操作。
l 本地索引(local index):其分区形式与表的分区完全相同,依赖列相同,存储属性也相同。对于本地索引,其索引分区的维护自动进行,就是说你add/drop/split/truncate表的分区时,本地索引会自动维护其索引分区。
Oracle建议如果单个表超过2G就最好对其进行分区,对于大表创建分区的好处是显而易见的,这里不多论述why,而将重点放在when以及how。
WHEN
一、When使用Range分区
Range分区呢是应用范围比较广的表分区方式,它是以列的值的范围来做为分区的划分条件,
将记录存放到列值所在的range分区中,比如按照时间划分,2008年1季度的数据放到a分区,08年2季度的数据放到b分区,因此在创建的时候呢,需要你指定基于的列,以及分区的范围值,如果某些记录暂无法预测范围,可以创建maxvalue分区,所有不在指定范围内的记录都会被存储到maxvalue所在分区中,并且支持指定多列做为依赖列,后面在讲how的时候会详细谈到。
二、When使用Hash分区
通常呢,对于那些无法有效划分范围的表,可以使用hash分区,这样对于提高性能还是会有一定的帮助。hash分区会将表中的数据平均分配到你指定的几个分区中,列所在分区是依据分区列的hash值自动分配,因此你并不能控制也不知道哪条记录会被放到哪个分区中,hash分区也可以支持多个依赖列。
三、When使用List分区
List分区与range分区和hash分区都有类似之处,该分区与range分区类似的是也需要你指定列的值,但这又不同与range分区的范围式列值—其分区值必须明确指定,也不同与hash分区—通过明确指定分区值,你能控制记录存储在哪个分区。它的分区列只能有一个,而不能像range或者hash分区那样同时指定多个列做为分区依赖列,不过呢,它的单个分区对应值可以是多个。
你在分区时必须确定分区列可能存在的值,一旦插入的列值不在分区范围内,则插入/更新就会失败,因此通常建议使用list分区时,要创建一个default分区存储那些不在指定范围内的记录,类似range分区中的maxvalue分区。
四、When使用组合分区
如果某表按照某列分区之后,仍然较大,或者是一些其它的需求,还可以通过分区内再建子分区的方式将分区再分区,即组合分区的方式。
组合分区呢在10g中有两种:range-hash,range-list。注意顺序哟,根分区只能是range分区,子分区可以是hash分区或list分区。
提示:11g在组合分区功能这块有所增强,又推出了range-range,list-range,list-list,list-hash,这就相当于除hash外三种分区方式的笛卡尔形式都有了。为什么会没有hash做为根分区的组合分区形式呢,再仔细回味一下第二点,你一定能够想明白~~。
Oracle数据库中,有两种类型的分区索引,全局索引和本地索引,其中本地索引又可以分为本地前缀索引和本地非前缀索引。下面就分别看看每种类型的索引各自的特点。
全局索引以整个表的数据为对象建立索引,索引分区中的索引条目既可能是基于相同的键值但是来自不同的分区,也可能是多个不同键值的组合。
全局索引既允许索引分区的键值和表分区键值相同,也可以不相同。全局索引和表之间没有直接的联系,这一点和本地索引不同。
Table created.
Index created.
Index created.
从上面的语句可以看出,全局索引和表没有直接的关联,必须显式的指定maxvalue值。假如表中新加了分区,不会在全局索引中自动增加新的分区,必须手工添加相应的分区。
Table altered.
TABLE_NAME PARTITION_NAME
ORDERS Q1
ORDERS Q2
ORDERS Q3
ORDERS Q4
ORDERS Q5
INDEX_NAME PARTITION_NAME
ORDERS_GLOBAL_1_IDX GLOBAL1
ORDERS_GLOBAL_1_IDX GLOBAL2
ORDERS_GLOBAL_1_IDX GLOBAL3
ORDERS_GLOBAL_1_IDX GLOBAL4
使用全局索引,索引键值必须和分区键值相同,这就是所谓的前缀索引。Oracle不支持非前缀的全局分区索引,如果需要建立非前缀分区索引,索引必须建成本地索引。
接下来再来看看本地分区。
本地索引的分区和其对应的表分区数量相等,因此每个表分区都对应着相应的索引分区。使用本地索引,不需要指定分区范围因为索引对于表而言是本地的,当本地索引创建时,Oracle会自动为表中的每个分区创建独立的索引分区。
创建本地索引不必显式的指定maxvalue值,因为为表新添加表分区时,会自动添加相应的索引分区。
Index created.
INDEX_NAME PARTITION_NAME
ORDERS_LOCAL_1_IDX LOCAL1
ORDERS_LOCAL_1_IDX LOCAL2
ORDERS_LOCAL_1_IDX LOCAL3
ORDERS_LOCAL_1_IDX LOCAL4
Table altered.
INDEX_NAME PARTITION_NAME
ORDERS_LOCAL_1_IDX LOCAL1
ORDERS_LOCAL_1_IDX LOCAL2
ORDERS_LOCAL_1_IDX LOCAL3
ORDERS_LOCAL_1_IDX LOCAL4
ORDERS_LOCAL_1_IDX Q5
这里系统已经自动以和表分区相同的名字自动创建了一个索引分区。同理,删除表分区时相对应的索引分区也自动被删除。
本地索引和全局索引还有一个显著的差别,就是上面提到的,本地索引可以创建成本地非前缀型,而全局索引只能是前缀型。
Index created.
从上面的输出可以看出,虽然索引的键值是part_no,但索引分区的键值仍然和表的分区键值相同,即ord_date,也即是所谓的非前缀型索引。
最后,再引用一个例子说明前缀索引和非前缀索引的应用。
假设有一个使用DATE列分区的大表。我们经常使用一个VARCHAR2列(VCOL)进行查询,但这个列并不是表的分区键值。
有两种可能的方法来访问VCOL列的数据,一是建立基于VCOL列的本地非前缀索引,
| |
| | (10 more | |
Values: A.. Z.. partitions here) A.. Z..
另一种是建立基于VCOL列的全局索引,
| |
| | (10 more | |
Values: A.. D.. partitions here) T.. Z..
可以看出,如果能够保证VCOL列值的唯一性,全局索引将会是最好的选择。如果VCOL列值不唯一,就需要在本地非前缀索引的并行查询和全局索引顺序查询以及高昂的维护代价之间做出选择。
B~树
1.前言:
这样我们就提出了一个新的查找树结构——多路查找树。根据平衡二叉树的启发,自然就想到平衡多路查找树结构,也就是这篇文章所要阐述的主题B~tree(B树结构),B-tree这棵神奇的树是在Rudolf Bayer, Edward M. McCreight(1970)写的一篇论文《Organization and Maintenance of Large Ordered Indices》中首次提出。具体介绍可以参考wikipedia中的介绍:http://en.wikipedia.org/wiki/B-tree,其中还阐述了B-tree名字来源以及相关的开源地址。
2.外存储器—磁盘
计算机存储设备一般分为两种:内存储器(main memory)和外存储器(external memory)。内存存取速度快,但容量小,价格昂贵,而且不能长期保存数据(在不通电情况下数据会消失)。
外存储器—磁盘是一种直接存取的存储设备(DASD)。它是以存取时间变化不大为特征的。可以直接存取任何字符组,且容量大、速度较其它外存设备更快。
2.1磁盘的构造
磁盘时一个扁平的圆盘(与电唱机的唱片类似)。盘面上有许多称为磁道的圆圈,数据就记录在这些磁道上。磁盘可以是单片的,也可以是由若干盘片组成的盘组,每一盘片上有两个面。如下图6片盘组为例,除去最顶端和最底端的外侧面不存储数据之外,一共有10个面可以用来保存信息。
当磁盘驱动器执行读/写功能时。盘片装在一个主轴上,并绕主轴高速旋转,当磁道在读/写头(又叫磁头) 下通过时,就可以进行数据的读 / 写了。
一般磁盘分为固定头盘(磁头固定)和活动头盘。固定头盘的每一个磁道上都有独立的磁头,它是固定不动的,专门负责这一磁道上数据的读/写。
活动头盘 (如上图)的磁头是可移动的。每一个盘面上只有一个磁头(磁头是双向的,因此正反盘面都能读写)。它可以从该面的一个磁道移动到另一个磁道。所有磁头都装在同一个动臂上,因此不同盘面上的所有磁头都是同时移动的(行动整齐划一)。当盘片绕主轴旋转的时候,磁头与旋转的盘片形成一个圆柱体。各个盘面上半径相同的磁道组成了一个圆柱面,我们称为柱面。因此,柱面的个数也就是盘面上的磁道数。
2.2磁盘的读/写原理和效率
磁盘上数据必须用一个三维地址唯一标示:柱面号、盘面号、块号(磁道上的盘块)。
读/写磁盘上某一指定数据需要下面3个步骤:
(1) 首先移动臂根据柱面号使磁头移动到所需要的柱面上,这一过程被称为定位或查找。
(2) 如上图6盘组示意图中,所有磁头都定位到了10个盘面的10条磁道上(磁头都是双向的)。这时根据盘面号来确定指定盘面上的磁道。
(3) 盘面确定以后,盘片开始旋转,将指定块号的磁道段移动至磁头下。
经过上面三个步骤,指定数据的存储位置就被找到。这时就可以开始读/写操作了。
访问某一具体信息,由3部分时间组成:
● 查找时间(seek time) Ts: 完成上述步骤(1)所需要的时间。这部分时间代价最高,最大可达到0.1s左右。
● 等待时间(latency time) Tl: 完成上述步骤(3)所需要的时间。由于盘片绕主轴旋转速度很快,一般为7200转/分(电脑硬盘的性能指标之一, 家用的普通硬盘的转速一般有5400rpm(笔记本)、7200rpm几种)。因此一般旋转一圈大约0.0083s。
● 传输时间(transmission time) Tt: 数据通过系统总线传送到内存的时间,一般传输一个字节(byte)大概0.02us=2*10^(-8)s
磁盘读取数据是以盘块(block)为基本单位的。位于同一盘块中的所有数据都能被一次性全部读取出来。而磁盘IO代价主要花费在查找时间Ts上。因此我们应该尽量将相关信息存放在同一盘块,同一磁道中。或者至少放在同一柱面或相邻柱面上,以求在读/写信息时尽量减少磁头来回移动的次数,避免过多的查找时间Ts。
所以,在大规模数据存储方面,大量数据存储在外存磁盘中,而在外存磁盘中读取/写入块(block)中某数据时,首先需要定位到磁盘中的某块,如何有效地查找磁盘中的数据,需要一种合理高效的外存数据结构,就是下面所要重点阐述的B-tree结构,以及相关的变种结构:B+-tree结构和B*-tree结构。
3.B-tree
B-tree又叫平衡多路查找树。一棵m阶的B-tree (m叉树)的特性如下:
(其中ceil(x)是一个取上限的函数)
为了简单,这里用少量数据构造一棵3叉树的形式。上面的图中比如根结点,其中17表示一个磁盘文件的文件名;小红方块表示这个17文件的内容在硬盘中的存储位置;p1表示指向17左子树的指针。
其结构可以简单定义为:
假如每个盘块可以正好存放一个B-tree的结点(正好存放2个文件名)。那么一个BTNode结点就代表一个盘块,而子树指针就是存放另外一个盘块的地址。
模拟查找文件29的过程:
(1) 根据根结点指针找到文件目录的根磁盘块1,将其中的信息导入内存。【磁盘IO操作1次】
(2) 此时内存中有两个文件名17,35和三个存储其他磁盘页面地址的数据。根据算法我们发现17<29<35,因此我们找到指针p2。
(3) 根据p2指针,我们定位到磁盘块3,并将其中的信息导入内存。【磁盘IO操作2次】
(4) 此时内存中有两个文件名26,30和三个存储其他磁盘页面地址的数据。根据算法我们发现26<29<30,因此我们找到指针p2。
(5) 根据p2指针,我们定位到磁盘块8,并将其中的信息导入内存。【磁盘IO操作3次】
(6) 此时内存中有两个文件名28,29。根据算法我们查找到文件29,并定位了该文件内存的磁盘地址。
分析上面的过程,发现需要3次磁盘IO操作和3次内存查找操作。关于内存中的文件名查找,由于是一个有序表结构,可以利用折半查找提高效率。至于3次磁盘IO操作时影响整个B-tree查找效率的决定因素。
当然,如果我们使用平衡二叉树的磁盘存储结构来进行查找,磁盘IO操作最少4次,最多5次。而且文件越多,B-tree比平衡二叉树所用的磁盘IO操作次数将越少,效率也越高。
上面仅仅介绍了对于B-tree这种结构的查找过程,还有树节点的插入与删除过程,以及相关的算法和代码的实现,将在以后的深入学习中给出相应的实例。
上面简单介绍了利用B-tree这种结构如何访问外存磁盘中的数据的情况,下面咱们通过另外一个实例来对这棵B-tree的插入(insert),删除(delete)基本操作进行详细的介绍:
下面以一棵5阶B-tree实例进行讲解(如下图所示):
其满足上述条件:除根结点和叶子结点外,其它每个结点至少有ceil(5/2)=3个孩子(至少2个关键字);当然最多5个孩子(最多4个关键字)。下图中关键字为大写字母,顺序为字母升序。
结点定义如下:
插入(insert)操作:
咱们通过一个实例来逐步讲解下。插入以下字符字母到空的5阶B-tree中:C N G A H E K Q M F W L T Z D P R X Y S,5序意味着一个结点最多有5个孩子和4个关键字,除根结点外其他结点至少有2个关键字,首先,结点空间足够,4个字母插入相同的结点中,如下图:
当咱们试着插入H时,结点发现空间不够,以致将其分裂成2个结点,移动中间元素G上移到新的根结点中,在实现过程中,咱们把A和C留在当前结点中,而H和N放置新的其右邻居结点中。如下图:
当咱们插入E,K,Q时,不需要任何分裂操作
插入M需要一次分裂,注意M恰好是中间关键字元素,以致向上移到父节点中
插入F,W,L,T不需要任何分裂操作
插入Z时,最右的叶子结点空间满了,需要进行分裂操作,中间元素T上移到父节点中,注意通过上移中间元素,树最终还是保持平衡,分裂结果的结点存在2个关键字元素。
插入D时,导致最左边的叶子结点被分裂,D恰好也是中间元素,上移到父节点中,然后字母P,R,X,Y陆续插入不需要任何分裂操作。
最后,当插入S时,含有N,P,Q,R的结点需要分裂,把中间元素Q上移到父节点中,但是情况来了,父节点中空间已经满了,所以也要进行分裂,将父节点中的中间元素M上移到新形成的根结点中,注意以前在父节点中的第三个指针在修改后包括D和G节点中。这样具体插入操作的完成,下面介绍删除操作,删除操作相对于插入操作要考虑的情况多点。
删除(delete)操作:
删除元素,移动相应元素之后,如果某结点中元素数目小于ceil(m/2)-1,则需要看其某相邻兄弟结点是否丰满(结点中元素个数大于ceil(m/2)-1),如果丰满,则向父节点借一个元素来满足条件;如果其相邻兄弟都刚脱贫,即借了之后其结点数目小于ceil(m/2)-1,则该结点与其相邻的某一兄弟结点进行“合并”成一个结点,以此来满足条件。那咱们通过下面实例来详细了解吧。
以上述插入操作构造的一棵5阶B-tree为例,依次删除H,T,R,E。
首先删除元素H,当然首先查找H,H在一个叶子结点中,且该叶子结点元素数目3大于最小元素数目ceil(m/2)-1=2,则操作很简单,咱们只需要移动K至原来H的位置,移动L至K的位置(也就是结点中删除元素后面的元素向前移动)
下一步,删除T,因为T没有在叶子结点中,而是在中间结点中找到,咱们发现他的继承者W(字母升序的下个元素),将W上移到T的位置,然后将原包含W的孩子结点中的W进行删除,这里恰好删除W后,该孩子结点中元素个数大于2,无需进行合并操作。
下一步删除R,R在叶子结点中,但是该结点中元素数目为2,删除导致只有1个元素,已经小于最小元素数目ceil(5/2)-1=2,如果其某个相邻兄弟结点中比较丰满(元素个数大于ceil(5/2)-1=2),则可以向父结点借一个元素,然后将最丰满的相邻兄弟结点中上移最后或最前一个元素到父节点中,在这个实例中,右相邻兄弟结点中比较丰满(3个元素大于2),所以先向父节点借一个元素W下移到该叶子结点中,代替原来S的位置,S前移;然后X在相邻右兄弟结点中上移到父结点中,最后在相邻右兄弟结点中删除X,后面元素前移。
最后一步删除E,删除后会导致很多问题,因为E所在的结点数目刚好达标,刚好满足最小元素个数(ceil(5/2)-1=2),而相邻的兄弟结点也是同样的情况,删除一个元素都不能满足条件,所以需要该节点与某相邻兄弟结点进行合并操作;首先移动父结点中的元素(该元素在两个需要合并的两个结点元素之间)下移到其子结点中,然后将这两个结点进行合并成一个结点。所以在该实例中,咱们首先将父节点中的元素D下移到已经删除E而只有F的结点中,然后将含有D和F的结点和含有A,C的相邻兄弟结点进行合并成一个结点。
也许你认为这样删除操作已经结束了,其实不然,在看看上图,对于这种特殊情况,你立即会发现父节点只包含一个元素G,没达标,这是不能够接受的。如果这个问题结点的相邻兄弟比较丰满,则可以向父结点借一个元素。假设这时右兄弟结点(含有Q,X)有一个以上的元素(Q右边还有元素),然后咱们将M下移到元素很少的子结点中,将Q上移到M的位置,这时,Q的左子树将变成M的右子树,也就是含有N,P结点被依附在M的右指针上。所以在这个实例中,咱们没有办法去借一个元素,只能与兄弟结点进行合并成一个结点,而根结点中的唯一元素M下移到子结点,这样,树的高度减少一层。
为了进一步详细讨论删除的情况。再举另外一个实例:
这里是一棵不同的5阶B-tree,那咱们试着删除C
于是将删除元素C的右子结点中的D元素上移到C的位置,但是出现上移元素后,只有一个元素的结点的情况。
又因为含有E的结点,其相邻兄弟结点才刚脱贫(最少元素个数为2),不可能向父节点借元素,所以只能进行合并操作,于是这里将含有A,B的左兄弟结点和含有E的结点进行合并成一个结点。
这样又出现只含有一个元素F结点的情况,这时,其相邻的兄弟结点是丰满的(元素个数为3>最小元素个数
2),这样就可以想父结点借元素了,把父结点中的J下移到该结点中,相应的如果结点中J后有元素则前移,然后相邻兄弟结点中的第一个元素(或者最后一个元素)上移到父节点中,后面的元素(或者前面的元素)前移(或者后移);注意含有K,L的结点以前依附在M的左边,现在变为依附在J的右边。这样每个结点都满足B-tree结构性质。
如果想了解相关代码,见最后参考。
4.B+-tree
B+-tree:是应文件系统所需而产生的一种B-tree的变形树。
一棵m阶的B+-tree和m阶的B-tree的差异在于:
1.有n棵子树的结点中含有n个关键字; (B-tree是n棵子树有n-1个关键字)
2.所有的叶子结点中包含了全部关键字的信息,及指向含有这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大的顺序链接。 (B-tree的叶子节点并没有包括全部需要查找的信息)
3.所有的非终端结点可以看成是索引部分,结点中仅含有其子树根结点中最大(或最小)关键字。 (B-tree的非终节点也包含需要查找的有效信息)
a) 为什么说B+树比B-tree更适合实际应用中操作系统的文件索引和数据库索引?
1) B+-tree的磁盘读写代价更低
举个例子,假设磁盘中的一个盘块容纳16bytes,而一个关键字2bytes,一个关键字具体信息指针2bytes。一棵9阶B-tree(一个结点最多8个关键字)的内部结点需要2个盘快。而B+-tree内部结点只需要1个盘快。当需要把内部结点读入内存中的时候,B-tree就比B+-tree多一次盘块查找时间(在磁盘中就是盘片旋转的时间)。
2) B+-tree的查询效率更加稳定
b) B+-tree的应用:
5.B*-tree
B-tree是B+-tree的变体,在B+-tree的非根和非叶子结点再增加指向兄弟的指针;B*-tree定义了非叶子结点关键字个数至少为(2/3)M,即块的最低使用率为2/3(代替B+树的1/2)。给出了一个简单实例,如下图所示:
B+-tree的分裂:
B*-tree的分裂:
所以,B*-tree分配新结点的概率比B+-tree要低,空间使用率更高;
6.总结
B-tree,B+-tree,B*-tree总结如下:
B-tree:有序数组+平衡多叉树;
B+-tree:有序数组链表+平衡多叉树;
B*-tree:一棵丰满的B+-tree。
在大规模数据存储的文件系统中,B~tree系列数据结构,起着很重要的作用,对于存储不同的数据,节点相关的信息也是有所不同,这里根据自己的理解,画的一个查找以职工号为关键字,职工号为38的记录的简单示意图。(这里假设每个物理块容纳3个索引,磁盘的I/O操作的基本单位是块(block),磁盘访问很费时,采用B+-tree有效的减少了访问磁盘的次数。)
对于像MySQL,DB2,Oracle等数据库中的索引结构有待深入的了解才行,不过网上可以找到很多B-tree相关的开源代码可以用来研究。
九、v$session详解
VSESSION是APPS用户下面对于SYS.V_SESSION 视图的同义词。
在本视图中,每一个连接到数据库实例中的session都拥有一条记录。包括用户session及后台进程如DBWR,LGWR,arcchiver等等。
1、V$SESSION中的常用列
V$SESSION是基础信息视图,用于找寻用户SID或SADDR。不过,它也有一些列会动态的变化,可用于检查用户。如例:
SQL_HASH_VALUE,SQL_ADDRESS:这两列用于鉴别默认被session执行的SQL语句。如果为null或0,那就说明这个session没有执行任何SQL语句。PREV_HASH_VALUE和PREV_ADDRESS两列用来鉴别被session执行的上一条语句。
注意:当使用SQL*Plus进行选择时,确认你重定义的列宽不小于11以便看到完整的数值。
STATUS:这列用来判断session状态是:
l Achtive:正执行SQL语句(waiting for/using a resource)
l Inactive:等待操作(即等待需要执行的SQL语句)
l Killed:被标注为删除
下列各列提供session的信息,可被用于当一个或多个combination未知时找到session。
2、Session信息
l SID:SESSION标识,常用于连接其它列
l SERIAL#:如果某个SID又被其它的session使用的话则此数值自增加(当一个 SESSION结束,另一个SESSION开始并使用了同一个SID)。
l AUDSID:审查session ID唯一性,确认它通常也用于当寻找并行查询模式
l USERNAME:当前session在oracle中的用户名。
3、Client信息
数据库session被一个运行在数据库服务器上或从中间服务器甚至桌面通过SQL*Net连接到数据库的客户端进程启动,下列各列提供这个客户端的信息
l OSUSER: 客户端操作系统用户名
l MACHINE:客户端执行的机器
l TERMINAL:客户端运行的终端
l PROCESS:客户端进程的ID
l PROGRAM:客户端执行的客户端程序
要显示用户所连接PC的TERMINAL、OSUSER,需在该PC的ORACLE.INI或Windows中设置关键字TERMINAL,USERNAME。
4、Application信息
调用DBMS_APPLICATION_INFO包以设置一些信息区分用户。这将显示下列各列。
l CLIENT_INFO:DBMS_APPLICATION_INFO中设置
l ACTION:DBMS_APPLICATION_INFO中设置
l MODULE:DBMS_APPLICATION_INFO中设置
下列V$SESSION列同样可能会被用到:
l ROW_WAIT_OBJ#
l ROW_WAIT_FILE#
l ROW_WAIT_BLOCK#
l ROW_WAIT_ROW#
5、V$SESSION中的连接列
示例:
1.查找你的session信息
2.当machine已知的情况下查找session
3.查找当前被某个指定session正在运行的sql语句。假设sessionID为100
寻找被指定session执行的SQL语句是一个公共需求,如果session是瓶颈的主要原因,那根据其当前在执行的语句可以查看session在做些什么。
视图应用:
6、V$session 表的妙用
v$session 表中比较常用的几个字段说明:
1. sid,serial#
通过sid我们可以查询与这个session相关的各种统计信息,处理信息.
查询用户相关的各种统计信息.
b. 查询用户相关的各种io统计信息
c. 查询用户想在正在打开着的游标变量.
d. 查询用户当前的等待信息. 以查看当前的语句为什么这么慢/在等待什么资源.
e. 查询用户在一段时间内所等待的各种事件的信息. 以了解这个session所遇到的瓶颈
f. 还有, 就是当我们想kill当前session的时候可以通过sid,serial#来处理.
command 字段, 表明当前session正在执行的语句的类型.请参考reference.
taddr 当前事务的地址,可以通过这个字段查看当前session正在执行的事务信息, 使用的回滚段信息等
lockwait字段, 可以通过这个字段查询出当前正在等待的锁的相关信息.
(sql_address,sql_hash_value) (prev_sql_addr,prev_hash_value) 根据这两组字段, 我们可以查询到当前session正在执行的sql语句的详细信息.
7.ROW_WAIT_OBJ#,ROW_WAIT_FILE#,ROW_WAIT_BLOCK#,ROW_WAIT_ROW#可以通过这几个字段查询现在正在被锁的表的相关信息.^_^
a. 首先得到被锁的的信息
b. 根据row_wait_file#可以找出对应的文件的信息.
c. 在根据以上四个字段构造出被锁的字段的rowid信息.
十、Oracle:DBMS_STATS.GATHER_TABLE_STATS的语法
作用:DBMS_STATS.GATHER_TABLE_STATS统计表,列,索引的统计信息.
DBMS_STATS.GATHER_TABLE_STATS的语法如下:
参数说明:
ownname:要分析表的拥有者
tabname:要分析的表名.
partname:分区的名字,只对分区表或分区索引有用.
estimate_percent:采样行的百分比,取值范围[0.000001,100],null为全部分析,不采样. 常量:DBMS_STATS.AUTO_SAMPLE_SIZE是默认值,由oracle决定最佳取采样值.
block_sapmple:是否用块采样代替行采样.
method_opt:决定histograms信息是怎样被统计的.method_opt的取值如下:
for all columns:统计所有列的histograms.
for all indexed columns:统计所有indexed列的histograms.
for all hidden columns:统计你看不到列的histograms
for columns SIZE | REPEAT | AUTO | SKEWONLY:统计指定列的histograms.N的取值范围[1,254]; REPEAT上次统计过的histograms;AUTO由oracle决定N的大小;SKEWONLY multiple end-points
with the same value which is what we define by “there is skew in the data
degree:决定并行度.默认值为null.
granularity:Granularity of statistics to collect ,only pertinent if the table is partitioned.
cascace:是收集索引的信息.默认为falase.
stattab指定要存储统计信息的表,statid如果多个表的统计信息存储在同一个stattab中用于进行区分.statown存储统计信息表的拥有者.以上三个参数若不指定,统计信息会直接更新到数据字典.
no_invalidate: Does not invalidate the dependent cursors if set to TRUE. The procedure invalidates the dependent cursors immediately if set to FALSE.
force:即使表锁住了也收集统计信息.
例子:
例如:
在使用DBMS_STATS分析表的时候,我们经常要保存之前的分析,以防分析后导致系统性能低下然后进行快速恢复。
2、导出表分析信息到stat_table中
COUNT(*)
4
EXPORT_COLUMN_STATS:导出列的分析信息
EXPORT_INDEX_STATS:导出索引分析信息
EXPORT_SYSTEM_STATS:导出系统分析信息
EXPORT_TABLE_STATS:导出表分析信息
EXPORT_SCHEMA_STATS:导出方案分析信息
EXPORT_DATABASE_STATS:导出数据库分析信息
IMPORT_COLUMN_STATS:导入列分析信息
IMPORT_INDEX_STATS:导入索引分析信息
IMPORT_SYSTEM_STATS:导入系统分析信息
IMPORT_TABLE_STATS:导入表分析信息
IMPORT_SCHEMA_STATS:导入方案分析信息
IMPORT_DATABASE_STATS:导入数据库分析信息
GATHER_INDEX_STATS:分析索引信息
GATHER_TABLE_STATS:分析表信息,当cascade为true时,分析表、列(索引)信息
GATHER_SCHEMA_STATS:分析方案信息
GATHER_DATABASE_STATS:分析数据库信息
GATHER_SYSTEM_STATS:分析系统信息
4、删除分析信息
没有查到分析数据
5、导入分析信息
('pre.prettyprint code').each(function () { var lines = numbering = $('