部分内容摘抄于:https://www.oraclejsq.com/article/010100478.html
https://blog.csdn.net/qq_43270074/article/details/85727108
Oralceo数据库基本操作及用法
[ DDL语句管理表 ]
①创建表空间
语法:
create tablespace 表空间的名称
datafile ‘文件的路径(服务器上)’
size 大小
autoextend on 自动扩展
next 每次扩展的大小
[ 代码:
[ 删除表空间 ]
②创建用户
create user 用户名 (hname)
identified by 密码 (nametest)
default tablespace 表空间的名称 (hname)
[ 给hname授权 ]
grant dba to hname;
[ Oralce中的数据库类型 ]
int ---数值类型,只能存储整数
number ----数值类型,可以存储整数也可以存储浮点数 number(3,1)
varchar2 ----字符类型,可变长字符类型 varchar2(6)
char ---字符类型,定长字符类型 char(6)
date ---日期类型,在oracle中精确到秒,
---该数据类型可以使用java的Date类型接收,接收后只能精确到日。
[ 创建表 ]
创建一个person表
create table person(
pid number(10),
pname varchar2(10)
);
----修改表结构
---添加一列
alter table person add gender number(1);
---修改列类型
alter table person modify gender char(1);
---修改列名称
alter table person rename column gender to sex;
---删除一列
alter table person drop column sex;
----增删改数据
--查询数据
select * from person;
---添加数据
insert into person (pid, pname) values (1, '小明');
commit;
---oracle中除了别名都必须使用单引号。
---修改数据
update person set pname = '小马' where pid = 1;
commit;
---三种删除
drop table person;--删除表结构
---这种在数据量大的情况下效率低
delete from person;--删除表中全部数据
---此中删除数据是先删除表结果,再次创建表
---删除表结构的时候会先把表中所有的索引和约束等删除
---然后再除数据,最后才删除表。
---这种方式在数据库大的情况下删除数据效率高,
---因为它避开了索引和约束对增删改效率的影响。
truncate table person;--删除表中全部数据
----序列:序列是给主键赋值使用的。
---序列默认从1开始自增,每次增加1。
---创建一个序列
----序列:序列是给主键赋值使用的。
---序列默认从1开始自增,每次增加1。
---创建一个序列
create sequence seq_person;
---dual虚表:虚表只是为了补全语法,没有任何意义。
----oracle中查询语句必须有from关键字。
---但是很多函数或方法根本就不属于任何表,我们单一看特性的时候,可以只从虚表中查询。
---查询序列
select seq_person.nextval from dual;
--查询当前值,如果是一个新的序列没有用过,直接查询是报错的。
select seq_person.currval from dual;
---使用序列添加数据
insert into person (pid, pname) values (seq_person.nextval, '小明');
commit;
select * from person;
---SCOTT用户 密码是tiger
---解锁scott用户
alter user scott account unlock;
---解锁密码【此句可以用来重置密码】
alter user scott identified by tiger;
---切换到scott用户下
---emp表典型的树形结构表
select * from emp;
---查询工资高于2000的员工信息
---where要先于select
---除了子查询,其余任何时候条件中都不能出现别名
select s.ename, s.sal sa from emp s where s.sal > 2000;
---查询出员工姓名和工作,在一列上显示。比如:xx的工作为ss。
---说明concat在oracle中只能连接两个字符串
select concat(e.ename, e.job) from emp e
---oracle中连接多个字符串使用||
select e.ename || '的工作为' || e.job "工作信息" from emp e
---字符函数
select upper('yes') from dual;--YES
select lower('YES') from dual;--yes
---数值函数
select round(58.69, -2) from dual;---四舍五入
select trunc(58.69,1) from dual;---直接截取
---日期函数
---日期类型可以直接和数字做算术运算,单位按天来算
---算出emp表中所有员工入职距离现在多少天
select round(sysdate-e.hiredate) from emp e;
---算出emp表中所有员工入职距离现在多少礼拜
select round((sysdate-e.hiredate)/7) from emp e;
---算出emp表中所有员工入职距离现在多少月
select round(months_between(sysdate, e.hiredate)) from emp e;
---算出emp表中所有员工入职距离现在多少年
select round(months_between(sysdate, e.hiredate)/12) from emp e;
---算出明天此时
select sysdate+1 from dual;
----转换函数
to_char--转成字符串
--当前日期转成字符串
select to_char(sysdate, 'fm yyyy-mm-dd hh24:mi:ss') from dual;
to_date--转成日期
--把字符串转成日期
select to_date('2019-01-03 16:24:50', 'yyyy-mm-dd hh24:mi:ss') from dual;
---常用的日期转换说明
select to_char(sysdate, 'yyyy') from dual;--2019
select to_char(sysdate, 'year') from dual;--twenty nineteen
select to_char(sysdate, 'mm') from dual;--01
select to_char(sysdate, 'month') from dual;--january
select to_char(sysdate, 'mon') from dual;--jan
select to_char(sysdate, 'dd') from dual;--03
select to_char(sysdate, 'day') from dual;--thursday
select to_char(sysdate, 'dy') from dual;--thu
---把数值转成字符串
select to_char(123456789, '999,999,999.000') from dual;
---通用函数
---注意:null值做任何算术运算结果都是null
---查询出emp表中所有员工的年薪
---nvl(e.comm, 0)当第一个参数为null时,使用第二个参数
select e.sal*12+nvl(e.comm, 0) from emp e;
----条件表达式
---条件表达式是根据条件处理数据。
---条件表达式等值判断案例
---给emp表中所有员工起中文名
select e.ename,
case e.ename
when 'SMITH' then '曹贼'
when 'ALLEN' then '司马老贼'
--else '诸葛小儿'
end 中文名 from emp e;
---条件表达式范围判断案例
---工资超过3000显示有钱人
---工资在1500到3000之间显示中产阶级
---工资低于1500显示穷人
select e.ename,
case
when e.sal>3000 then '有钱人'
when e.sal>1500 then '中产阶级'
else '穷人'
end 工资等级 from emp e;
---以上条件表达式都是mysql和oracle通用
---oracle专用条件表达式【不常用】
select e.ename,
decode(e.ename,
'SMITH', '曹贼',
'ALLEN', '司马老贼',
'诸葛小儿')
中文名 from emp e;
----多行函数【聚合函数】
----聚合函数如果是在group by中使用,是组内聚合。
----聚合函数有一个特性,可以吧多行记录变成一个值。
----是可以改变表结构的一种函数。
select count(1) from emp;
select max(sal) from emp;
select min(sal) from emp;
select avg(sal) from emp;
select sum(sal) from emp;
---笛卡尔积
select * from emp, dept;
---等值连接
select * from emp e, dept d where e.deptno=d.deptno;
---内连接
select * from emp e inner join dept d on e.deptno = d.deptno;
---外连接
---查询出所有部门以及部门下所有员工信息
select * from emp e right join dept d on e.deptno = d.deptno;
---oracle中专用的外连接
--查询出所有部门以及部门下所有员工信息
select * from emp e, dept d where e.deptno(+)=d.deptno;
---子查询
----子查询结果当条件使用
---查询出和SCOTT工资一样的员工信息
select * from emp where sal in
(select sal from emp where ename='SCOTT');
----子查询结果当表使用
----查询出每个部门最低工资员工姓名,最低工资,部门名称
---先查询出每个部门的最低工资
select deptno, min(sal) msal from emp group by deptno;
---然后三表联查
select e.ename, d.dname, t.msal from emp e, dept d, (select deptno, min(sal) msal
from emp
group by deptno) t
where e.deptno=d.deptno
and e.deptno=t.deptno
and e.sal=t.msal;
---自连接
---自连接是站在不同的角度把一张表看成多张表。
---查询出员工姓名,员工领导姓名
select e1.ename, e2.ename
from emp e1, emp e2
where e1.mgr=e2.empno;
---查询出员工姓名,员工部门名称,员工领导姓名,领导部门名称
select e1.ename, d1.dname, e2.ename, d2.dname
from emp e1, emp e2, dept d1, dept d2
where e1.mgr=e2.empno
and d1.deptno=e1.deptno
and d2.deptno=e2.deptno;
----作业:查询出员工姓名,员工部门名称,员工工资等级,
-----员工领导姓名,领导部门名称,领导工资等级,
-----要求工资等级显示汉字。
----分组查询
---查询出每个部门平均工资
---只有在group by后面出现的原始列,才能出现在select后面
---如果没有出现在group by后面,要想出现在select后面,必须加聚合函数
---因为聚合函数可以把多行记录变成一个值。
select e.deptno, avg(e.sal) from emp e group by e.deptno;
---查询出平均工资高于2000的部门
select e.deptno, avg(e.sal) asal from emp e group by e.deptno having avg(e.sal)>2000;
---查询出每个部门工资高于1000的员工的平均工资
select e.deptno, avg(e.sal) from emp e where e.sal>1000 group by e.deptno;
---where过滤的分组前原来表的数据
---having是过滤分组后新表的数据
---下面这样写不行
select e.deptno, avg(e.sal) from emp e where avg(e.sal)>1000 group by e.deptno;
-------------------------------
union或者union all
视图__
oracle视图可以理解为数据库中一张虚拟的表,他是通过一张或者多张基表进行关联查询后组成一个虚拟的逻辑表。查询视图,本质上是对表进行关联查询。
视图的本身是不包含任何数据,只是一个查询结果,当基表的数据发生变化时,视图里面的数据也会跟着发生变化。我们经常在实际开发过程中遇到的视图可以大概分为三种:单表视图、多表关联视图、视图中含有子视图。
[ 视图的作用和优势 ]
既然视图在实际开发过程当中被广泛使用到,它到底有哪些作用和优势呢?
1、使数据简单化:可以将复杂的查询创建成视图,提供给他人使用,他人就不需要去理解其中复杂性的业务关系或逻辑关系。这样对视图的使用人员来说,就简化了数据的,屏蔽了数据的复杂性。
2、表结构设计的补充:系统刚刚开始设计时,大部分程序是直接访问表结构的数据的,但是随着业务的变化、系统的更新等,造成了某些表结构的不适用,这时候去修改表结构对系统的影响太大,开发成本较高,这个时候可以创建视图来对表结构的设计进行补充,降低开发成本。程序可以直接通过查询视图得到想要的数据。
3、增加安全性:视图可以把表中指定的字段展示给用户,而不必把表中所有字段一起展示给用户。在实际开发中,视图经常作为数据的提供方式,设置为只读权限提供给第三方人员进行查询使用。
[ 创建视图 ]
[ 栗子 ]
利用学生信息表(stuinfo)、班级表(class)关联创建视图,只提供一些学生基本信息和班级信息(剔除学生一些敏感信息:如身份证,家庭地址等)。
[ 代码如下:
序列
Oracle序列Sequence是用来生成连续的整数数据的对象,它经常用来作为业务中无规则的主键。Oracle序列可以是升序列也可以是降序列。
索引
创建索引:
修改索引:
alter index index_old rename to index_new;--重新命名索引
删除索引
查看索引
栗子1:
栗子2:
三种索引的状态:
查询结果:
PL/SQL基本语法
DECLARE
message varchar2(20):= 'Hello, World!';
BEGIN
dbms_output.put_line(message);
END;
解释:
DECLARE 声明部分
此部分开头使用关键字DECLARE。它是一个可选的部分,并限定在该程序中使用的所有变量,游标,子程序,和其他元素。
BEGIN执行命令块
此部分是封闭关键字BEGIN和END,这是一个强制性的部分。它由程序的可执行文件的PL/SQL语句。它应具有至少一个可执行的代码行,这可能仅仅是一个空命令,以指示什么都不执行。
[ 声明部分声明了一个 长度为20的varchar2类型 变量 message 并且初始化。 := 为赋值号。
在程序执行块中使用dbms_output.put_line()函数输出出来。]
__DECLARE部分 :
①定义基本类型变量
类型:char,varchar2,date,number,boolean,long
定义语法:变量名 数据类型(长度) 如: name varchar2(100), age number(10) .....
②引用型变量%TYPE类型 和 记录型变量%ROWTYPE类型
引用型变量 my_name emp.ename%type;
[ --表示my_name这个变量的类型是引用emp这个表的ename列的类型
相当于引用某一个数据到student表中 ]
栗子:
declare
my_name emp.ename%type;
begin
select t.name into my_name
from student t;
记录型变量 my_name emp.ename%rowtype
[ --my_name相当于一个数组,存的类型是一条记录中的类型,打印某一列的时候,直接用 emp_rec.列名即可 相当于引用一行数据到student表中 ]
栗子:
declare
my_info emp.ename%rowtype;
begin
select t.* into my_info
from student t
where t.stuid='SC10086';
如: my_info.stuname || ' 学号:' || ls_info.stuid || ' 年龄:' || my_info.age;
-----------------------------------------------------------------------------------------------------------------------------------
流程控制
IF-THEN-END IF (与java中if else差不多)
if (条件) then
--满足条件执行体;
endif;
if my_info.sex='1' then --性别编码为1的是男生
my_number+1; --(当my_info.sex='1'条件满足时执行my_number+1)
end if;
IF-THEN-ELSE- END IF
if 条件 then
--满足条件执行体;
else
--不满足条件执行体;
end if;
if my_info.sex='1' then--性别编码为1的是男生
my_number_boy+1;--(当my_info.sex='1'条件成立时,执行my_number_boy+1操作)
else
my_number_boy-1;--(当my_info.sex='1'条件不成立时,执行my_number_boy-1操作)
end if;
IF-THEN -ELSIF-THEN -END IF
if 条件1 then
--条件1成立执行体;
els if 条件2 then
--条件1不成立,条件2成立执行体;
else
--条件都不成立执行体;
end if;
if my_info.sex='1' then--性别编码为1的是男生
my_number_boy+1;--(当my_info.sex='1'条件成立时,执行my_number_boy+1操作)
els if my_info.sex='2' then--性别编码为1的是男生
my_number_boy+2;--(当my_info.sex='1'条件不成立时,执行my_number_boy+2操作)
else
my_number_boy-3;--(当my_info.sex='1'条件不成立时,执行my_number_boy-3操作)
end if;
CASE...WHEN...THEN (与java中switch差不多)
CASE选择体
WHEN表达式1 then执行体;
WHEN表达式2 then执行体;
WHEN表达式3 then执行体;
......
ELSE表达式n then执行体;
END CASE;
case my_info.age
when 26 then
my_number_26+1;
when 27 then
my_number_27+1;
else
my_number-1;
end case;
循环结构
Oracle 提供的循环类型有:FOR 循环语句和WHILE循环语句。
栗子:
Declare
int NUMBER(2):=0; (定义一个变量)
BEGIN
LOOP (执行语句)
int :=int+1 (循环内容)
DBMS_OUTPUT.PUT_LINE('int的当前值:'||int); (输出内容)
EXIT WHEN int=10; (exit when 条件满足时 退出循环)
END LOOP;
END;
WHILE循环
栗子:
Declare
x NUMBER(1):=1; (定义一个变量x)
BEGIN
WHILE x<10 LOOP (条件满足时循环)
DBMS_OUTPUT.PUT_LINE('X的当前值为:'||x);
x:=x+1;
END LOOP;
FOR循环
BEGIN
FOR int in 1..10 LOOP
DBMS_OUTPUT.PUT_LINE('int的当前值为:'||int);
END LOOP;
注:每循环一次,循环变量自动加1;使用关键字REVERSE,循环变量自动减1。跟在IN REVERSE 后面的数字必须是从小到大的顺序,而且必须是整数,不能是变量或表达式。可以使用EXIT 退出循环。
--------------------------------------------------------------------------------------------------------------------------------
异常处理
Oracle一共提供了25种预定义异常名称 (命令如下)
select * from dba_source t where t.TEXT like '%EXCEPTION_INIT%' AND NAME='STANDARD';
栗子:
declare
my_info stuinfo%rowtype;
begin
select t.* my_info
from stuinfo t
where t.stuid='SC2018010061';
--该学号找不到对应的学生
exception
when no_data_found then (对应图中的第7条)
dbms_output.put_line('该学生在学生信息表中找不到');
end;
-----------------------------------------------------------------------------------------------------------------------------------
游标
(%FOUND, %NOTFOUND, %ISOPEN, %ROWCOUNT) 游标属性
Oracle游标 可以分为显式游标和隐式游标两种之分。
显式游标:指的是游标使用之前必须得先声明定义,一般是对查询语句的结果事进行定义游标,然后通过打开游标循环获取结果集内的记录,或者可以根据业务需求跳出循环结束游标的获取。循环完成后,可以通过关闭游标,结果集就不能再获取了。全部操作完全由开发者自己编写完成,自己控制。
隐式游标:指的是PL/SQL自己管理的游标,开发者不能自己控制操作,只能获得它的属性信息。
隐式游标虽然不能像显式游标一样具有操作性,但是在实际开发过程当中还是经常使用到它的属性值,隐式游标主要是用在select语句活DML语句时,PL/SQL程序会自动打开隐式游标,这个隐式游标是不受开发者控制的
1、声明游标:
声明游标是给游标命名并给游标关联一个查询结果集,具体声明语法如下:
declare cursor cursor_name(游标名) is select_statement(查询语句);
2、打开游标:
游标声明完,可以通过打开游标打开命令,初始化游标指针,游标一旦打开后,游标对应的结果集就是静态不会再变了,不管查询的表的基础数据发生了变化。打开游标的命令如下:
open cursor_name;
3、读取游标中数据:
读取游标中的数据是通过fetch into语句完成,把当前游标指针指向的数据行读取到对应的变量中(record 变量)。游标读取一般和循环LOOP一起使用,用于循环获取数据集中的记录。
fetch cursor_name into record变量
4、关闭游标:
游标使用完,一定要关闭游标释放资源。关闭后,该游标关联的结果集就释放了,不能够再操作了,命令如下:
close cursor_name;
隐式游标
隐式游标虽然不能像显式游标一样具有操作性,但是在实际开发过程当中还是经常使用到它的属性值,隐式游标主要是用在select语句活DML语句时,PL/SQL程序会自动打开隐式游标,这个隐式游标是不受开发者控制的
触发器
Oracle触发器可以根据不同的数据库事件进行特定的调用触发器程序块,因此,它可以帮助开发者完成一些PL/SQL存储过程完成不了的问题,比如操作日志的记录、防止一些无效的操作、校验数据的正确性、限制一些对数据库对象的操作、提供数据同步的可行性。但是不推荐在触发器当中写业务逻辑程序,因为这样对后期数据的维护将大大提高成本。
触发器的类型
触发器按照用户具体的操作事件的类型,可以分为5种触发器。大致如下:
1、数据操作(DML)触发器:此触发器是定义在Oracle表上的,当对表执行insert、update、delete操作时可以触发该触发器。如果按照对表中行级数据进行触发或语句级触发,又可以分为行级(row)触发器,语句级触发器,按照修改数据的前后触发触发器,又可以分为 after 触发器和before触发器之分。
2、数据定义操作(DDL)触发器:当对数据库对象进行create、alter、drop操作时,触发触发器进行一些操作记录保存、或者限定操作。
3、用户和系统事件触发器:该类型的触发器是作用在Oracle数据库系统上,当进行数据库事件时,触发触发器,一般用来记录登录的相关信息。
4、INSTEAD OF 触发器:此类型的触发器是作用在视图上,当用户对视图进行操作时,触发该触发器把相关的操作转换为对表进行操作。
5、复合触发器:指的是对数据操作(DML)触发器当中的多种类型触发器进行复合,比如;一个触发器当中包含着after(或before)的行级触发器和after(或before)的语句级触发器,来完成一些更为复杂的操作。
语法解析:
1、or replace :存在同名的触发器就覆盖保存。
2、trigger:创建触发器的关键词。
3、before | after 表示是选择的触发器是数据改变之前触发、数据改变之后触发。
4、delete| insert | update:表示触发器触发的事件类型是删除、插入或更新。
5、for each row: 表示行级触发器、不填就是语句级触发器
6、follows :表示触发器的顺序是跟在哪个之后。
7、when 表示触发器语句触发的条件
创建DML类型触发器