-----在输入用户名和密码之后,需要切换用户名用:su-用户名
1.Windowsserver服务器安装数据库忘记对某个用户解锁,比如Scott,我们可以通过system用户来对该用户解锁:
步骤如下:
注:sys/system/oracle数据库用户都是管理员用户
(1)在运行中输入sqlplus,进入Oracle
alteruserscottaccountunlock
2.oracle常用的sqlplus命令
--(1)然后输入sqlplus/nolog命令,
--(4)若用户需要修改密码,可使用如下命令:
passwd(该命令用于修改用户的密码)
基本用法:
password用户名:
(如果给自己修改密码,则可以不带用户名;如果给别人修改密码,则需要带用户名(修改密码的前提是(system或者sys)管理员用户给其他用户来修改密码))
--(5)disc(该命令用户断开和Oracle的连接,但是不退出sqlplus窗口)
--(6)exit(该命令是用户断开和Oracle的连接同时退出sqlplus窗口)
---(7)linesize(用于控制每行显示多少个字符,默认80个字符,不设置的话是自动换行,显示很乱)
setlinesize140(可以自己加显示行的大小)
---(8)pagesize(用于控制每页显示多少行,不设置的话默认是显示14行就分页了)
setpagesize100(可以自己设置每页显示的行数)
---(9)&的用法
例:select*fromxxcj_empwherejob='&job';
3.Oracle用户管理
然后输入sqlplus/nolog命令,
---(1)创建用户、给用户赋予权限、回收权限、删除用户
connect---表示可连接
resource----表示可分配资源,什么都可以操作
createuser用户名identifiedby密码----创建用户(在oracle中创建一个新的用户使用createuser语句,一般是具有dba数据库管理员的权限才能创建)
grantresourceto用户名---给创建的用户赋予创建表和可操作的权限(增删改查的权限)
revokeconnectfrom用户名-----把创建连接的用户名进行回收删除(需用管理员的权限在操作)
revokeresourcefrom用户名----把赋予给创建用户的操作权限进行回收删除
dropuser用户名[cascade]-----删除创建的用户(如果删除一个用户的时候,这个用户自己已经创建过数据对象(指表或索引或触发器等等),那么我们在删除该用户的时候,需要加选项cascade表示把这个用户删除同时,把该用户创建的数据对象一并删除)
withadminoption---系统权限(如果是系统权限,则带withadminuption)
withgrantoption----对象权限(表示得到对象的权限用户,可以把权限继续分配)
----(2)了解:方案(schema)
理解:当一个用户创建好后,如果该用户创建了任意一个数据对象,这时,我们的dbms就会创建一个对应的方案与该用户对应,并且该方案的名字和用户名一致。
----(3)用户练习题:
1.创建用户tea,stu,并给这两个用户resource,connect角色
createuserteaidentifiedbytea---创建tea用户,密码
grantresourcetotea---赋予用户resource(增删改查)角色
grantconnecttotea---赋予用户connect(连接权限)角色
createuserteaidentifiedbystu---创建tea用户
grantresouretostu---赋予用户resource角色
grantconnecttostu---赋予用户connect角色
2.使用scott用户把对emp表的select权限给tea
connscott/scott----连接scott用户
grantselectonemptotea
使用tea查询scott的emp表
conntea/tea-----连接tea用户
select*fromscott.emp
使用scott用户把对emp表的所有权限赋给tea
connscott/scott
grantallonemptotea
使用tea更新/删除/插入scott的emp表
conntea/tea
updatescott.empsetjob='teacher'wherejob='&job'
deleteformscott.empwherejob='&job'
insertintoscott.empvalues(6,'fors','teacher',222)
使用scott回收权限
revokeselectonscott.empfromtea
revokeallonscott.empfromtea
3.想办法将让tea把自己拥有的对scott.emp的权限转给stu
grantallonscott.emptoteawithgrantoption
grantallonscott.emptostu
使用stu查询scott用户的emp表
connstu/stu
使用tea收回给stu的权限
revokeallonscott.empfromstu
4.使用profile文件对口令进行管理
----(1)账户锁定
基本语法:
createprofile文件名limitfailed_logon_attempts3password_lock_time2-----设置用户名输错3次账号锁定2天,2天后才能使用
alertuser用户名profile文件名----分配文件(把输错次数就锁用户的方法分配给某个用户(完成输入错误3次锁2天))
----(2)账号解锁
alteruser用户名accountunlock----被锁的用户进行解锁
-----(3)终止口令
需求:为让用户定期修改密码可以使用终止口令,需管理员身份来操作,一个账号密码最多使用10天,宽限期为2天,到时必须设置新的密码
createprofile文件名limitpassword_life_time10password_grace_time2------设置一个账号密码最多使用10天,宽限期为2天,到时必须设置新的密码
alteruser用户名profile文件名-------分配文件(把设置账号的期限文件分配给该用户)
-----(4)删除profile口令文件
dropprofile文件名---当不需要某个profile文件时,可以删除该文件
5.Oracle数据库的启动流程
(1)windows操作系统启动步骤
在cmd命令中操作:
lsnrctlstart----用于启动监听服务
oradmin-startup-sid数据库实例名------启动Oracle实例服务
systeminfo------查询操作系统的详细信息
(2)Linux操作系统启动步骤
lsnctlstart----启动监听
sqlplus/nolog------切换到sqlplus命令
startup
6.数据库管理员密码丢失如何找回(前提:Windows服务器系统安装Oracle数据库服务端)
---(1)在安装Oracle数据库路径中找到密码文件PWD数据库实例名.ora文件(数据库实例名是自己安装数据库时取的名字)
----(2)把密码文件(PWD数据库实例名.ora)备份
----(3)生成新的密码文件,在dos控制台下输入命令:
7.数据库表的基本操作语句
altertable表名add(新的列名列的数据类型)----表中添加一个新的字段,列名和数据类型
altertable表名modify(列名新字段类型)----表中修改一个字段的类型
altertable表名dropcolumn(字段名)---删除一个字段,可同时删除几个字段名
rename旧表的名字to新的名字---给表修改名字
----用户锁定操作方法:
(1)锁定用户命令:
alteruser用户名accountlock;
(3)解锁命令:
alteruser用户名accountunlock
例题:
删除一个用户,同时保留该用户的数据对象
-1.锁定该用户
alteruserscottaccountlock;
-3.解锁用户
alteruserscottaccountunlock;
例:查1982-1-1后出生的信息
select*fromempwhereto_char(birther,'yyyy-mm-dd')>'1982-1-1'
查四月份出生的信息
select*fromempwhereto_char(birther,'mm')='4'
查23日出生的信息
select*fromempwhereto_char(birther,'dd')='23'
-----看如何取消重复行
例:selectdistinctdeptno,jobfromemp;-----distinct是去重(返回的数据完全一样才是重复行)
-----函数NVL的使用
NVL(COMM,0)------如果comm列中的字段为空,就取0,如果comm列中的字段不为空就取comm列中的字段值(用于处理数据null的问题)
上面截图中的comm列中,有空字段(空加任何数为空,空乘任何数为空)
------表中列字段的拼接(拼接符||)
在查询的时候如果希望把多列拼接成一列返回,可以使用||,具体使用如下:
-----groupby和having的用法
groupby------用于对查询的结果进行分组;
having-----子句用于过滤分组显示的结果
例:-1)如何显示每个部门的平均工资和最高工资
selectavg(sal),max(sal),deptnofromempgroupbydepto
-2)如何显示每个部门的每种岗位的平均工资和最低工资
selectavg(sal),min(sal),deptno,jobfromempgroupbydeptno,jobordebydeptno---不同部门的不同岗位的平均工资和最低工资
-3)显示部门平均工资低于2000的部门号和它的平均工资
selectavg(sal),deptnofromempgroupbydeptnohavingavg(sal)<2000
-----子查询语句all和any的用法(行的子查询)
------all的使用
例:如何显示工资比部门30号的所有员工的工资高的员工的姓名、工资和部门号
select*fromempwheresal>all(selectsalfromempwheredeptno=30)
或
select*fromempwheresal>(selectmax(sal)fromempwheredeptno=30)
----any的使用
例:如何显示工资比部门30号的任意一个员工的工资高的员工的姓名、工资和部门号
select*fromempwheresal>any(selectsalfromempwheredeptno=30)
select*fromempwheresal>(selectmin(sal)fromempwheredeptno=30)
------子查询语句(多列子查询)
例:如何查询与smith的部门和岗位完全相同的所有雇员
思路:先查出Smith所在的部门和岗位
selectdeptno,jobfromempwhereename='smith'
然后查询相同部门和岗位的人
select*fromempwhere(deptno,job)=(selectdeptno,jobfromempwhereename='smith')
-----用查询结果创建新表
这个命令是一种快捷的建表方法
createtablemytable(id,name,sal,job,deptno)asselectempno,ename,sal,job,deptonfromemp
------自我复制数据(蠕虫复制)
有时,为了对某个sql语句进行效率测试,我们需要海量数据时,可以使用此方法为表创建海量数据
selectintomytable(id,name,sal,job,deptno)selectempno,ename,sal,job,deptnofromemp
8.数据库中的函数及事务、序列
(1)事务
事务(transaction)基本概念:事务是把对数据库一系列操作看作一个整体,要么全部成功要么全部失败,利用事务我们可以保证数据的完整性,事务具有原子性。
(2)序列
在表中希望田间一条记录的时候,通过序列(sequence)来完成自动增长,该列值能够自动的增长(比如从1开始增长,每次增长1)
例:在sqlserver和MySQL中都是可以在定义表的时候直接指定自动增长。
sqlserver中:
createtabletemp1(
idintprimarykeyidentity(1,1),
namevarchar(36)
)
mysql中
idintprimarykeyauotincrment,
解决方式:Oracle是利用创建序列(sequence)来完成,如下:
Oracle创建一个系列:
createsequencemyseq------myseq序列名
startwith1------序列从1开始
incrementby1-----序列每次增长1
minvalue1---------最小值是1
maxvalue3000-----最大增长至3000
cycle-----cycle表示序列增加到3000,从新从1开始。nocycle表示不重新开始
nocache---------nocache表示不缓存,[cache10:表示一次产生10个数供使用,使用缓存产生号,优点是提高效率,缺点是可能产生跳号]
例:下图中的myseq是关键字,nextval是获取下一个数的关键字
序列的细节:
a.可以为表中的列自动产生值
b.由用户船舰数据库对象,并与由多个用户共享
如果system使用Scott创建的序列,从什么时候开始增长?-----接着增长
c.一般用于主键或唯一列(unique)
d.可以使用序列名.currval来看当前序列号到多少号了
select序列名.currvalfromdual;
e.如果希望去查看序列.currval必须先使用序列.nextval值,否则出错
9.索引
索引的分类
(1)单列索引
createindex索引名on表名(列名);
(2)复合索引
createindex索引名on表名(列名1,列名2)
例:
createtableusers(namevarchar2(30),agenumber,emailvarchar2(36));
createindexinx_nameonusers(name);
细节:
a.在大表上建的索引才有意义
b.在where子句或是连接条件上经常引用的列上建索引
select*from表名where列名=‘条件值’
c.索引的层次不要超过4层
d.在逻辑型类型字段上,或者值就是固定几种的列上也不要建立索引
索引缺点:
a.建立索引会增加表的大小1.2
b.索引会影响数据插入,删除,修改的效率
10.管理权限和角色
1)系统权限
系统权限是指执行特定类型sql命令的权利
常用的有:
createsession连接数据库
createtable建表
createview建视图
createpublicsynonym建同义词
createprocedure建过程,函数,包
createtrigger建触发器
createcluster建簇
如何使用select来查询有哪些权限
select*fromsystem_privilege_maporderbyname;
---1.1创建两个用户,并指定密码
createuserkenindentifiedbym123;
createusertomindentifiedbym123;
grant权限名称to用户名
例:grantcreatesessiontokenwithadminoption------带withadminoption就表示ken可以把他得到权限继续向别的用户转发
grantcreateviewtoken;
2)回收系统权限
使用system回收ken(createsession权限)
revoke权限名称from用户名
revokecreatesessionfromken;
1)对象权限
概念:指访问其他方案对象的权限,用户可以直接访问自己方案的对象,但是如果要访问别的方案的对象,则必须具有对象的权限,比如Smith用户要访问scott.empb表(Scott:方案,emp:表),则必须在Scott.emp表上具有对象的权限。常用的有:
alter修改delete删除select查询insert添加update修改index索引reference引用execute执行
查看Oracle提供的所有的对象权限(需要dba用户可以查看)
selectdistinctprivilegefromdba_tab_privs
grant对象权限on方案.数据对象to用户[withgrantoption]
grant对象权限on方案.数据对象to角色[witngrantoption]
特别说明:可以把权限直接赋给角色
----1)希望mokey可以查询scott.emp表,则必须授予相应的对象权限
grantselectonscott.emptomokey
----2)希望mokey可以删除scott.emp表,则必须授予相应的对象权限
grantdeleteonscott.emptomokey
---3)把增删改查的权限都赋给mokey
grantallonscott.emptomokey
----4)在别的方案的表上建立索引,则具有index对象权限,让black可以在scott.emp上建立索引,给其加index的对象权限
connscott/tiger
grantindexonscott.emptoblack
---5)使用withgrantoption
该选项用于转授对象权限,但是选项只能被授予用户,而不能授予角色
grantselectonemptoblakewithgrantoption
connblack/shumping
grantselectonscott.emptojones
2)回收对象权限
可以使用dba用户(sys,system)来完成
回收对象权限后,用户就不能执行相应的sql命令。但是要注意的是对象的权限是会被级联收回
基本语法
revoke对象权限on方案.数据对象from用户
对象的权限是会被级联回
1)角色管理
查询用户具有怎样的角色
语法:
Select*fromdba_role_privswheregrantee=‘用户名’-----用户名一定要大写
角色是一组权限的集合,目的是为了简化对权限的管理,从而达到简化对用户的管理
角色的分类:
(1)预定义角色
Oracle提供了33种预定义角色,常用的预定义角色connect,resource,dba
如何知道某个角色具有怎样的权限
Select*fromdba_sys_privswheregrantee=’DBA’-----DBA一定要大写(DBA包含了所有的权限,所有不进行截图)
Select*fromdba_sys_privswheregrantee=’CONNECT’------connect一定要大写
Select*fromdba_sys_privswheregrantee=’RESOURCE’----resource一定要大写
角色赋给用户的语法
grant角色名to用户名[withadminoption]
---1)connect角色
connect角色具有一般应用开发人员需要的大部分权限,只要给用户授予connect和resource角色就够了,connect具有的系统权限如下:
createsession
可以通过select*fromdba_sys_privswheregrantee='CONNECT'语句查询
---2)resource角色
resource角色具有引用开发人员所需要的其他权限,比如建立存储过程,触发器等,这里需要注意的是resource角色隐含了unlimitedtablespace系统权限。
resource角色包含以下系统权限:
Createcluster
Createindextype
Createtable
Createsequence
Createtype
Createprocedure
Createtigger
可以通过Select*fromdba_sys_privswheregrantee=’RESOURCE’语句查询权限
---3)dba角色
但是dba角色不具备(启动和关闭数据库)
创建一个用户Jack,并把Jack设为具有dba角色的用户
Createuserjackindetifiedbym123;
Grantdbatojack
(2)自定义角色
Oracle设计这认为33种预定义角色可能不能满足所有的需求,所以可以使用自定义角色来解决。
自定义角色根据自己的需求来定义,一般是dba来建立,如果用别的用户来建立,则需要具有createrole的系统权限,在建立角色时可以只当验证方式(不验证,数据库验证等)
----1)建立角色(不带验证---常用)
createrole角色名notidentified;
---2)建立角色(数据库验证)
createrole角色名identifiedby密码;
假如有用户1,2,3为了让他们都拥有权限
a.连接数据库
b.在scott.emp表上select,insert,update
---使用自定义角色来完成
createrolemyrolenotidentified;
---给角色赋权限
grantcreatesessiontomyrole;
grantselectonscott.emptomyrole;
grantinsertonscott.emptomyrole;
grantupdateonscott.emptomyrole;
---这是可以把myrole这个自定义角色赋给指定的某个用户hsp
createuserhspidentifiedbym123;
grantmyroletohsp;
(3)删除角色
droprole角色名
预定义角色能删除,但是要慎重,不要删除预定义角色
角色可以包含系统权限,也可以包含对象权限。
11.PLSQL编程
基本概念:plsql实行标准sql语句基础上扩展的一种对Oracle数据库进行编程的语句。可以定义常量和变量,而且可以使用条件语句和循环语句。
因为使用纯sql语句来操作数据库,所有有技术缺陷;
技术缺陷:
a.不能模块化过程,为了完成下订单,可能我们要发出几条sql
b.执行速度
c.安全性问题
d.浪费带宽
解决方法:
使用PL/SQL来编写存储过程,以提高效率
1)创建存储过程语法
createprocedure过程名(参数1......,参数2)
is
begin
//执行语句
end
2)调用存储过程语法
exec过程名(参数1......,参数2)
例1:
开发一个简单的存储过程,可以完成向某表添加一条记录
createprocedurepro1
insertintoemp(emp,ename)values(444,'张三')
调用执行存储过程
execpro1
例2:
接受输入参数的简单存储过程
createprocedurepro2(in_empnonumber)
deletefromempwhereempno=in_empno;
execpro2(444)
PLSQL编写规范:
11.块(block)的介绍
概念:块是pl/sql的基本程序单元,编写pl/sql程序实际上就是编写pl/sql块。要完成相对简单的应用功能,可能只需要编写一个pl/sql块,但是如果要实现复杂的功能,可能需要一个pl/sql块中嵌套其他的pl/sql块。
块的结构示意图:
pl/sql块中有三个部分构成:定义部分、执行部分、例外处理部分。如下:
declare
//定义部分-------定义常量、变量、游标、例外、复杂的数据类型(该部分可选的)
//执行部分-----要执行的pl/sql语句和sql语(执行部分从这里开始,该部分是必须的)
exception
//例外处理部分-----处理运行时的各种错误(例外处理部分从这里开始,该部分可选)
end;
只包含执行部分的案例
dbms_output.put_line('helloworld')
特别说明:在默认情况下,helloworld不会输出,需要setserveroutpuron;
dbms_output是Oracle所提供的包,该包包含一些存储过程,put_line就是dbms_output包的一个存储过程。
包含部分和执行部分
v_enamevarchar2(36)-----定义变量格式,变量名称变量类型
selectenameintov_enamefromempwhereempno=&empno----把查询的ename值放入v_ename变量
dbms_output.put_line('雇员名是‘||v_ename)-----输出v_ename
------例2改为存储过程的写法
createprocedurepro4(in_empnonumber)
v_enamevarchar2(16);---定义变量的格式是:变量名称变量类型
selectenameintov_enamefromempwhereempno=in_empno----把查询的ename值放入v_ename变量
dbms_output.put_line('雇员名是'||v_ename);
end;
执行存储过程
execpro4(4444);
例3:
包含定义部分、执行部分和例外处理部分的块
(1)比如在实例2中,如果输入了不存在的雇员号,应该做例外处理,如下图所示
从上面的案例可以看出,如果输入的用户编号不存在,则系统会提示异常,为了更明确的指出错误,Oracle提供了异常execption处理机制。
快速入门:
v_enamevarchar2(36);----定义变量格式,变量名称变量类型
selectenameintov_enamefromempwhereempno=&empno;----把查询的ename值放入v_ename变量
dbms_output.put_line('雇员名是'||v_ename);-------输出v_ename
execption
whenno_data_foundthen
dbms_output.put_line("输入的编号有误");
对该案例系统说明,这里设计到异常处理:
异常处理的基本语法:
when异常名称then
//对异常进行处理的代码;
when异常名称2then
//对异常处理的代码;
oracle提供的异常有(详情可参考官方文档)
异常处理的作用
(1)可以给出捕获异常,并给出明确提示
(2)有时可以利用异常,来进行业务处理
例4:
查询的信息不存在,就加入编号为1,名字为张三这么个人的信息
v_enamevarchar2(16);-----定义变量格式,变量名称变量类型
selectenameintov_enamefromempwhereempno=&empno----把查询你的ename值放入v_ename变量
dbms_output.put_line('雇员名为’||v_ename);
dbms_output.put_line('输入的编号有误,我帮你加一条');
insertintoemp(empno,ename)values(1,'张三')
12.存储过程进一步讲解
oracle过程可以指定参数是输入的参数(in),还是输出的参数(out)
createprocedure过程名(变量名in变量类型......,变量名out变量类型.....)
//定义变量
请考虑编写一个存储过程,可以输入雇员名,新工资,可修改雇员的工资
特别说明:当我们编写过程时,可以输入showerror来显示具体的错误信息。
createorreplaceprocedurepro5(in_enameinvarchar2,in_new_salinnumber)
updateempsetsal=in_new_salwhereename=in_ename;
调用存储过程
execpro5('张三',10)
使用java代码调用此存储过程:
对SQLHelper类升级,添加一个可以调用存储过程的方法
//调用存储过程的方法(封装的类)
13函数
函数用于返回特定的数据,当建立函数时,在函数头部必须包含return子句,而在函数体内必须包含return语句返回的数据。我们可以使用createfunction来建立函数,实际案例:
存储过程和函数的区别:
-----1)函数必须有返回值,而存储过程可以没有
----2)函数和存储过程在Java中调用的方式不一样,
函数是select自己的函数名(列)from表
过程使用callableStatement去完成调用
函数语法:
createorreplacefunction函数名(参数1......,参数2)
return返回的数据类型
//定义变量;
//执行语句;
调用函数
select函数名(实际参数)fromdual;------在控制台调用
编写一个函数,可以接收用户的名字并返回用户的年薪
createorreplacefunctionfunl(in_enamevarchar2)
returnnumber
v_annual_salnumber;---定义一个变量,来接收年薪
select(sal+nvl(comm,0))*13intov_annual_salfromempwhereename=in_ename;
returnv_annual_sal;
调用函数:
selectfunl(‘张三’)fromdual;---dual是虚表,因为函数中已经写了emp实表。
在Java中调用
14包(packages)
使用包更好的管理自己写的函数、存储过程
(1)包的基本语法
create[orreplace]package包名
编写一个包,该包有一个存储过程,该存储过程可以接收用户名和新的薪资(将来用于通过用户名去更新薪资),还有一个函数,该函数可以接收一个用户名(将来要实现得到该用户的年薪是多少)
createorreplacemypackage1
procedurepro1(v_in_enamevarchar2,v_in_newsalnumber);
functionfun1(v_in_enamevarchar2)returnnumber;
如果语句报错可以查看详细的报错信息,用showerror命令可以查看详细报错信息。
(2)包体
createorrepalcebackagebody包名
createprocedure过程名(参数列表......)is-----------实现过程
createfunction函数名(参数列表.....)return数据类型------实现函数
编写包体的案例
crateorrepalcepachagebodymypackage1
----实现存储过程
procedurepro1(v_in_enamevarchar2,v_in_newsalnumber)
updateempsetsal=v_in_newsalwhereename=v_in_ename;
-------实现函数
functionfun1(v_in_enamevarchar2)returnnumberis
v_annual_salnumber;
select(sal+nvl(comm,0))*13intov_annual_salfromempwhereename=v_in_ename;
调用包体:
execpackage1.pro1('张三',222)
细节说明
(2)在调用包中的某个方法的时候需要这样调用:
exec方案名.包名.过程名(参数值......);
call方案名.包名.函数名(参数值.......);
stringsql="{callscott.mypackage1.pro1(,)}";
stringsql="selectscott.mypackage1.fun1('张三')annualfromdual";
15plsql中的语法
plsql中的数据类型分为:
(1)标量类型
可以理解为就是Oracle数据库里的类型
----(1)定义一个变长字符串
v_enamevarchar2(10);
-----(2)定义一个小数,范围-9999.99~9999.99
v_salnumber(6,2);
-----(3)定义一个小数并给一个初始值为5.4:=是pl/sql的赋值号
v_sal2number(6,2):=5.4
------(4)定义一个日期类型的数据
v_hiredatedate;
------(5)定义一个布尔变量,不能为空,初始值为false
v_validboolena:=false;
说明:pl/sql在定义一个变量的时候,如果要赋初值,则需要使用:=
例:v_enamevarchar(32):='顺平'
以输入员工号,显示雇员姓名、工资、个人所得税(税率为0.03)为例。说明变量的使用,看看如何编写。
%type类型:
为了让我们在pl/sql编程中,让变量的类型和大小与表的列的大小和类型一致可以使用%type。
(2)pl/sql复合变量
type自己定义的记录名称idrecord(
变量变量的类型,
编写一个过程,该过程可以接收一个用户编号,并显示该用户的名字,薪水,工作岗位(注意,要用plsql记录实现)
调用:
(3)复合类型---plsql表
type自己定义的plsq数据类型istableofemp.sal%typeindexbybinary_integer;
变量名自己定义的pl/sql数据类型;------定义一个这样的变量
(4)参照变量--(重要)
----(1)游标变量(重要)
原来图,通过游标,我们可以取得返回结果集(结果集往往是select语句的结果)的任何一行数据,从而提供共享的效率
请使用plsql编写一个存储过程,可以输入部门号,并显示该部门所有员工的姓名和他的工资。
createorreplaceprocedurepro(v_in_deptnonumber)is
typehsp_emp_cursorisrefcursor;-------先定义一个游标变量类型
v_emp_cursorhsp_emp_cursor;------定义一个游标变量
v_enameemp.ename%type;---------定义两个变量
v_salemp.sal%type;
openv_emp_cursorforselectename,salfromempwheredeptno=v_in_deptno;-----执行语句
loop
fetchv_emp_cursorintov_ename,v_sal;-----取出游标指向的每行数据,用循环语句
exitwhenv_emp_cursor%notfound;----判断当前游标是否到达最后
dbms_output.put_line('用户名'||v_ename||’薪水‘||v_sal);--------输出
endloop;
-----关闭游标【完后一定记住关闭游标】
closev_emp_cursor;
在例1基础上,增加个条件,如果某个员工的工资低于200元,就加100元。
16pl/sql进阶
控制结构
任何语句都有各种控制语句(条件语句,循环结构,顺序控制结构....),在pl/sql中也存在这样的控制结构。
特别说明:字符串的比较是=比如‘abc’='ttt'返回假
(1)条件分支语句
-----1)if....then
if条件表达式then
endif;
----2)if.....then.....else
//执行语句...
else
-----3)if.....then.....elsif....elsif.....-else;
elsif条件表达式then
[这里可以有很多elsif.....]
例:if...then
编写一个过程,可以输入一个雇员号,如果该雇员的工资低于2000,就给该雇员工资增加10%
createorreplaceprocedurepro1(v_in_enamevarchar2)is
v_salemp.sal%type;-----定义工资变量
selectsalintov_salfromempwhereename=v_in_ename;
ifv_sal<2000then
updateempsetsal=sal*1.1whereename=v_in_ename;
execpro1('张三');
例:if.....then.....else
编写一个存储过程,可以输入一个雇员名,如果该雇员的补助不是0就在原来的基础上加100;如果补助为0,就把补助设为200
createorreplaceprocedurepro1(v_in_enamevarchar)is
v_commemp.comm%type;----定义补助
selectcommintov_commfromempwhereename=v_in_ename;
ifv_vomm<>0then
updateempsetcomm=comm+100whereename=v_in_ename;
updateempsetcomm=200whereename=v_in_ename;
调用存储过程:
execpro1('张三')
例:if.....then.....elsif....elsif.....-else;
编写一个存储过程,可以输入一个雇员编号,如果该雇员的职位是president就给他的工资增加1000,如果该雇员的职位是manager就给他的工资增加500,其他职位的雇员工资增加200
createorreplaceprocedurepro1(v_in_empnonumber)is
v_jobemp.job%type;---定义职位变量
selectjobintov_jobfromempwhereempno=v_in_empno;
ifv_job='persident'then
updateempsetsal=sal+1000whereempno=v_in_empno;
elsifv_job='manager'then
updateempsetsal=sal+500whereempno=v_in_empno;
updateempsetsal=sal+200whereempno=v_in_empno;
execpro1('333');
(2)循环控制语句
-----1)loop循环
exitwhen'条件表达式'
说明:这里的条件表达式如果为true,则继续执行,否则退出
编写一个存储过程,可输入用户名,和添加用户的个数n;
循环添加个用户到users表中,用户编号从1开始增加,直到n
createtableusers5(
idnumberprimarykey,
namevarchar2(32)
createorreplaceprocedurepro1(v_in_enamevarchar2,nnumber)is
v_empnonumber:=1;---定义变量,赋初值
insertintousers5values(v_empno,v_in_ename);----执行添加任务
exitwhenv_empno=n;
v_empno:=v_empno+1;---自增
execpro1('张三',20);
------2)while循环
while条件表达式loop
例:两道判断题
结论:上面的存储过程是错误,原因是在is.....begin间不能对变量赋值,如果要重新赋值,则需要在begin....end间。
结论:上面存储过程中,不能对输入参数的值进行重新赋值。
-----3)for循环
推荐使用loop循环结构,不推荐使用for循环。
(3)顺序控制语句
----1)goto控制语句
goto语句用于跳转到特定标号去执行语句
说明:
PL/SQL支持goto和标号的使用
goto语句不要轻易的使用
----2)null控制语句
null主要的用处是提高代码的可读取性,其实他是什么都不做。
17PL/SQL编写分页过程
通过分页过程,目的是让大家把前面学习的各个技术综合运行。
因为分页过程比较复杂,所以采用循序渐进的方式学习。
----1)在Java中调用没有返回值的过程;
---2)在Java中如何调用返回,非列表的值
编写一个存储过程,可以输入雇员编号,返回该雇员的姓名。
说明:定义变量中的in是定义变量(v_in_empno)的输入变量,out变量是定义变量(v_out_ename)的输出变量
----定义输出变量的类型
createorreplaceprocedurepro1(v_in_empnoinnumber,v_out_enameoutvarchar2)
selectenameintov_out_enamefromempwhereempno=v_in_empno;
在Java中去调用该存储过程,并接受返回的用户名
说明:(1)对于存储过程的输入值,使用setXXX,对于输出值,使用registerOutparameter,问号的顺序要对应,同时考虑类型。
(2)取出存储过程返回值的方法是用CallableStatement提供的getXXX(输出参数的位置);同时要考虑输出的参数的类型。
-------3)在Java中调用返回列表中(集合/表)
编写一个存储过程,输入部门,返回该部门所有雇员信息
1创建包:
createorreplacepackagepack1is-----创建一个包,在该包中定义一个游标类型
typemy_cursorisrefcursor;-------定义一个游标数据类型
2编写存储过程:
createorreplaceprocedurepro1(v_in_deptnoinnumber,v_out_resultoutpack1.my_cursor)
Is
openv_out_resultforselect*fromempwheredeptno=v_in_deptno;
--------不能在这里关游标,是为了让Java程序可以使用游标
3.编写java程序:
-----4)完成一个分页存储过程
例:
编写一个存储过程,要求可以输入表名,每页显示记录数、当前页,返回返回的结果集。
1.建包使用游标类型(如果又这个游标数据类型,则可以直接使用)
createorreplacepackagepack1is----定义一个游标类型
typemy_cursorisrefcursor;
2.编写存储过程
3Java调用存储过程
分页的select查询语句实例:
selectt2.*from(Selectt1.*,rownumrnfrom(select*fromemp)t1whererownum<=9)t2wherern>=4
例:对上面分页的存储过程进行扩展,让分页过程更加灵活,更加实用
编写一个存储过程,要求可以输入表名,每页显示记录数,当前页,返回返回的结果集,返回共有多少页,返回共有多少条记录。
Java调用存储过程
18视图
视图时Oracle的又一种数据对象,视图的主要用处时简化操作,提高安全,可以满足不同用户的查询需求,视图不是一个真正存在的物理表,他是根据别的表,动态生成的。
(1)创建视图
语法
createview视图名字asselect语句[withreadonly]
说明:如果我们创建视图的时候,我们带了withreadonly则表示该视图只能读,不能进行其他的操作,如果没有带withreadonly则可以进行其他的操作,删除视图中的一条数据原表中的一条数据也会被删除。
如果创建视图的时候不希望用户通过视图对原表进行其他操作,则建议带withreadonly。
创建一个视图和emp表(empno,ename,job)完全一致的视图
createviewempviewasselectempno,ename,jogfromemp;
视图可以简化操作:
比如:希望查询雇员的名字和部门编号和部门名称。
存在查询两张表,可以用视图进行查询。
createorreplaceviewmyviewasselectemp.ename,dept.deptno,dept.dnamefromemp,deptwhereemp.deptno=dept.deptnowithreadonly
(2)创建视图和修改视图
createorreplaceview视图名saselect语句[withreadonly]
(3)删除视图
dropview视图名
19触发器
触发器是一个隐含执行的过程,不是有程序员或者dba来显示调用,而是因为某个操作引发执行的。
触发器的分类:
dml(insert,delete,update)触发器;
ddl(createtable,createview,drop…)触发器;
createorreplacetrigger触发器名称
{before/after}{update/delete/insert}on表名
[foreachrow]
-----before/after:触发器是在数据操作之前还是之后执行;
----insert/update/delete:指定触发器是在插入、更新、还是删除操作;
-----表名:指触发器指定的表;
-----foreachrow:可选项,表示触发器对每行数据都执行一次,如果不指定该选项,则触发器整个语句执行一次。
在某张表(my_emp)添加一条数据的时候,提示‘添加了一条数据’
1建表
createtablemy_emp(
idnumber,
2创建一个触发器
createorreplacetriggertri1
afterinserton
scott.my_emp
dbms_output.put_line(‘添加了一条数据’);
3执行语句
setserveroutputon;---------是设置提示信息输出能看见
insertintomy_empvalues(1,'shumping');------添加一条数据
执行结果截图:
(1)行级触发器和语句级触发器
foreachrow行级触发器的标志。没有的是语句级触发器
在某张表(my_emp)修改多条数据的时候,提示‘多次’修改了数据。
createorreplacetiggertri2
afterupdateon
scott.emp
foreachrow----表示这是一个行级触发器
dbms_output.put_line(‘修改了一条数据’);
执行结果:
示例中使用的emp表的结构:
(2)dml触发器
为了禁止工作人员在休息日改变员工信息,开发人员可以建立before语句触发器,从而实现数据的安全。
createorreplacetriggertri2
beforedeleteon
ifto_char(sysdate,’day’)in(‘星期日’,‘星期六’)then
dbms.output.put_line(‘对不起,休息日不能删除员工’);----该信息只是提示信息,没有其他用途
raise_application_error(-20001,’对不起,休息日不能删除员工’);------该语句是阻止程序对信息进行删除。
特别说明:raise_application_error这个存储过程是Oracle提供的,可以传入两个参数,第一个是自定义的错误号(-20000~-20999之间),第二个参数是提示一个信息。
例2
使用条件谓词来精确提示用户的操作。
为了禁止工作人员在休息日改变员工信息,开发人员可以建立before语句触发器,从而实现数据的安全,在给出提示时,明确提示用户是进行的insert,update还是delete操作。
(3)触发器的:old和:new的使用
当触发器被触发时,要使用被插入、更新或删除的记录中的列值,有时要使用操作前、后列的值。
:new修饰符访问操作完成后列的值
:old修饰符访问操作完成前列的值
(1)在修改emp表雇员的薪水时,显示雇员工资修改前和修改后的值;
(2)如何确保在修改员工工资不能低于原有工资。
编写一个触发器的时候,保证当用户在删除一张表(emp)记录的时候,自动把删除的记录的id和name两个字段备份到另外一张表(emp_bak)中。
1创建备份表
createtableemp_bak(
namevarchar2(2000)
2创建触发器
3执行删除语句
编写一个新的触发器,如何控制员工的新工资不能低于原来的工资,同时也不能高出原来工资的20%,使用约束显示无法实现该规则
createorreplacetriggertri5
beforeupdateon
foreachrow
if(:new.sal<:old.salor:new.sal>:old.sal*1.2)then
dbms_output.put_line('工资范围不对!');
raise_application_error(-20010,'工资范围不对');
语句执行结果:
阻止把小于18岁的用户添加到数据库的表中,编写一个触发器完成该操作。
1创建一张表,表中字段有birthday
createtableemp2(
namevarchar2(32),
birthdaydate
createorreplacetriggertri6
beforeinserton
ifadd_month(:new.birehday,18*12)>sysdatethen
dbms_output.put_line('你年龄小');
raise_application_error(-20011,'你年龄小');------阻止添加
3执行添加语句
(4)系统触发器(数据库的用户需是管理员的用户,才能创建ddl触发器)
常用的属性函数
ora_client_ipaddress-----返回客户端的IP
ora_database_name-----返回数据库名
ora_login_user-----返回登陆用户名
ora_sysevent-----返回触发触发器的系统事件名
ora_des_encrypted_password-----返回用户des(md5)加密后的密码
createorreplacetrigger触发器名
after[before]logon[logoff]ondatabase
createtablelog_table(
usernamevarchar2(20),
logon_timedate,
logoff_timedate,
addressvarchar2(20)
createorreplacetriggertri7
afterlogonondatabase
insertintolog_table(username,logon_time,address)values(ora_login_user,sysdate,ora_client_ipaddress)
3创建退出触发器
createorreplacetriggertri8
beforelogoffondatabase
insertintolog_table(username,logoff_time,address)values(ora_login_user,sysdate,ora_client_ipaddress)
(5)ddl触发器(数据库的用户需是管理员的用户,才能创建ddl触发器)
ddl触发器主要的用途是记录在Oracle中发生的ddl操作
afterddlon方案名.schema-------如scott.schema(scott是数据库管理员用户名schema是关键字)
编写一个触发器,可以记录某个用户进行的ddl操作
1创建一张表
createtablemy_ddl_record(
eventvarchar2(64),
usernamevarchar2(64),
ddl_timedate
createorreplacetriggertri9
afterddlonscott.schema------scott是管理员用户
insertintomy_ddl_recordvalues(ora_sysevent,ora_login_user,sysdate);
触发器总结:在oracle中dml触发器需要手动提交(如果没有手动提交,当退出控制台时,Oracle会自动提交),ddl触发器语句自动提交
(6)管理触发器
指让触发器临时失效
altertrigger触发器名disable;
altertrigger触发器名enable;
altertable表名disablealltriggers;---禁止一张表所有触发器
altertable表名enablealltriggers;----激活一张表所有触发器
droptrigger触发器名
20.Oracle例外(异常)处理
在pl/sql执行过程中发生异常时系统所作的处理称为一个例外情况(exception)。通常情况有三种:
----预定义的Oracle例外情况,对于这种预定义的例外情况无须再程序中定义,由Oracle自动触发(重点)。下图是帮助文档的预定义的例外情况文档。
-----非预定义的Oracle例外情况由使用者增加定义例外情况,然后Oracle自动将其触发执行
-----自定义例外,这个用的比较少。
预定义的例外情况有如下几种:
例外常见的几种异常:
-------(1)cast_not_found案例
-------(2)no_data_found案例
-------(3)too_many_rows案例
//捕获异常
when例外名称then
whenothersthen
//其他
编写一个存储过程,可接收雇员的编号,并显示该雇员的姓名,如果编号不存在就会抛出异常(捕获异常的目的:给用户提示更加明确;可能需要对异常进行业务处理。)
v_enameemp.ename%type;
selectenameintov_enamefromempwhereempno=v_in_empno;
dbms_output.put_line('名字是'||v_ename);
whenNO_DATA_FOUNDthen
dbms_output.put_line('你输入的编号不存在');
dbms_output.put_line('不明错误')
21.Oracle数据库和表的备份和恢复
每个Oracle数据库应该至少有一个数据库管理员(dba),对于一个小的数据库,一个dba就够了,但一个大的数据库可能需要多个dba分担不同的管理职责。
数据库管理员主要的职责:
---(1)安装和升级Oracle数据库;
----(2)建库、表空间、表、视图、索引......
-----(3)制定并实施备份与恢复计划
-----(4)数据库权限管理、调优、故障排除
-----(5)对于高级dba,要求能参与项目开发,会编写sql语句、存储过程、触发器、规则、约束、包
管理数据库的用户主要是sys和system;(sys相当于董事长,system相当于总经理)
两个用户的区别:
(1)从重要性的区别,存储的数据的重要性不同
sys:所有Oracle数据字典的基表和视图都是放在sys用户中,这些基表和视图对于Oracle的运行是至关重要,由数据库自己维护,任何用户都不能手动更改。sys用户拥有dba(角色)、sysdba(系统权限)、sysoper(系统权限)角色或权限,是Oracle权限最高的用户。
system:用于存放次一级的内部数据,如Oracle的一些特性或工具的管理信息。system用户拥有dba角色、sysdba系统权限。
(2)其次的区别,权限不同
(3)sys和system用户的比较
sys用户对应方案存放的数据更重要system用户对应的方案存放次一级的数据
逻辑备份是指使用工具export将数据对象的结构和数据导出到文件的过程,
逻辑恢复是指当数据库对象被误操作后使用工具import利用备份的文件把数据对象导入到数据库的过程。
物理备份即可在数据库open的状态下进行也可在关闭数据库后进行,但是逻辑备份和恢复只能在open的状态下进行。
原理图:
导出具体的分为:导出表、导出方案、导出数据库三种方式。
导出使用exp命令来完成的,该命令常用的选项有你:
(1)导出自己的表
expuserid=用户名/密码@数据库实例名tables=(表名1,表名2.....)file=备份路径
例:导出scott.emp表
expuserid=scott/m123@orclhsptables=(emp,dept)file=d:/emp.dmp
特别说明:该命令需要在dos命令下执行。
备份文件的后缀名一般是.dmp但是这个不是必须的。
(2)导出其他方案的表
如果用户要导其他方案的表,则需要dba的权限或是exp_full_database的权限,比如system就可以导出scott的表。
expuserid=用户名/密码@数据库实例名tables=(方案名.表名1,方案名.表名2.......)file=备份路径
如果希望导出其他方案的表(其他数据对象),则往往是system用户来完成
(3)导出表的结构
expuserid=用户名/密码@数据库实例名tables=(表名1.....)file=备份路径rows=n
rows=n表示不要行数,n是no的意思。
(4)使用直接导出方式(数据量比较大可以使用,提高导出速度)
expuserid=用户名/密码@数据库实例名tables=(表名1....)file=备份路径direct=y
direct=y表示直接导出的意思,y是yes的意思。
这种方式比默认的常规方式速度要块,当数据量大时,可以考虑使用这样的方法。
这时需要数据库的字符集要与客户端字符集完成一致,否则会报错。
导出方案是指使用export工具导出一个方案或是多个方案中的所有对象(表、索引、约束.....)和数据。并列放到文件中。
(1)导出自己的方案
exp用户名/密码@数据库实例名owner=用户名file=备份路径
(2)导出其他方案
如果用户要导出其他方案,则需要dba的权限或是exp_full_database的权限,例如system用户就可以导出任何方案
exp用户名/密码@数据库实例名owner=(所有者1,所有者2)file=备份路径
所有者1,所有者2是指导出的数据库的用户名
说明:如果用户权限够大,则可一次性导出多个用户的方案,比如system.
当某张表被破坏,我们可以使用imp命令来恢复数据
impuserid=用户名/密码@数据库实例名tables=(表名1.....)file=备份文件
impuserid=scott/m123@orclhsptables=(emp,dept)file=d:/emp.dmp
22Oracle的卸载
一般运用程序,安装后,可以通过uninstal工具来卸载,但是Oracle没有。
Oracle卸载步骤如下:
2.使用universalinstaller来完成初步卸载,该工具不会把Oracle注册表的信息清除,所以
就会给我们后续安装oracle、升级Oracle带来麻烦。
3.到注册表中删除Oracle的注册信息,运行regedit命令,删除以下内容:
4.删除环境变量
删除环境变量classpath,path中含有Oracle字样的值。
在默认情况下,Oracle卸载不会删除你的数据库文件,所以需要手动删除,如果删除出现错误,则需重启机器在删除。(数据库文件在安装盘下的\oracle目录。)
======================================2023.12.10整个关于数据库的视频笔记完成,感谢观看!============================================================