Oracle数据库 2021.1.7~2021.1.13

六天心得

Oracle学了6天,学的挺快的,老师只根据我们的情况与需求讲了部分吧,感觉没有前面学java学的扎实,每天都是只学习理论知识,并没有做过什么练习和作业;话说oracle也并没有想象中这么难,只是多了很多它自己的东西,pl-sql;

ORACLE

网络资料:https://docs.oracle.com/cd/E11882_01/index.htm(oracle数据库文档11.2)

https://bk.tw.lvfukeji.com/baike-数据库规范化?wprov=srpw1_3(数据库规范化)

dba/dbo:数据库管理员/操作员

db:数据库

dbms:数据库管理系统

rdbms:关系型数据库管理系统-->oracle

SQL

structure query languge 结构化查询语言(设计之初是为了应用于关系型数据库,数据库都要遵循这个标准,数据库sql之间有着细小的区别)

rdb:关系型数据库-->为了解决数据关联性的问题;

数据类型(DataType)

(oracle能够识别任意一种数据库类型)

Character Data Types(字符数据类型)

存储字符数据,任意数据文本

CHAR Data Type:固定长度的字符串,最大为2000字节,当数据类型要求固定时可以使用,比如性别等。(NCHAR Data Type-->N-->字符编码采用Unicode的)

​ char(length)可以存储length个byte的字符串;

​ char(length char)可以存储length个插入的字符;

​ 如果插入的值小于char的长度,oracle将会在值的右边补空格直到指定的长度为止;

​ 如果插入的值大于char的长度,oracle将会报错。

VARCHAR2 Data Type:可变长度的字符串,精准插入字符,插入几个保存几个字节/字符,比CHAR更节省内存,最大为4000字节。(VARCHAR Data Type-->VARCHAR2 Data Type是升级版,NVARCHAR2 Data Type-->N-->字符编码采用Unicode的)

​ varchar2(length)

​ varchar2(length char)

length为插入的最大长度,最小为一个字节,但是传入的值可以为空,不能超过指定的插入的长度,不然会报错;实际存储的值与插入指定的值是一致的。

Numeric Data Types(数字数据类型)

可以存储正数、负数、浮点数、零、无穷数、"not a number"非数字-->NAN。

NUMBER Data Type:正数,负数,零,固定的数。范围:1.0 x 10^-130到1.0 x 10^126不包含本身。

​ NUMBER(p,s):

​ NUMBER(p)

​ p:precision(精确度),数字所有有效的部分

​ s:scale(扩展),扩展的部分,小数点后面的。

​ p与s的位数时共用的,输入的值整数部分加小数部分必须小于等于p,不然会报错;当s小于输入值的小数部分,则可以四舍五入,能够截取,(例如:123.89-->NUMBER(6,1)-->123.9)整数不能;负数是从整数位往前推几位,后面都为0(例如:123.89-->NUMBER(6,-2)-->100.00),范围:-84到127;

FOLAT Data Type(BINARY_FLOAT32位,BINARY_DOUBLE64位,二进制的)

​ FOLAT(n);

​ n:有效位;

DATE Data Type:日期加时间(已经够用)

​ datetime

​ 格式:to_date('timevalue','YYYY-MM-DD HH24:MI:SS')

TIMSTAMP Data Type:对DATE的扩展,还带地理位置,有时区;

LARGE OBJECT:

插入图片,文档等;

运算符(这里的是各个数据库通用的)

比较运算符

(>,>=,<,<=,=,<>,!=);(<>与!=含义一致)

in,not in:范围内,不在范围内;(当需要多个字段在一个范围,where (column1,column2......)in.....)

is null, is no null:为空,不为空;

between x and y:在x到y范围之内,是闭区间;

exists:某个值是否存在,较为复杂,空也是存在的,因为它为一行;

like:模糊查找,主要查找字符串,通配符:"%" -->匹配任意长度的任意字符串和"_"-->单个任意字符,比较耗时,而且会让索引失效,并不是很好,数据量不能太大,小范围使用,初期能用用;

逻辑运算符

and or not:与,或,非;

括号运算符

() 改变运算优先级

数据库设计三范式(数据库统一的标准)

尽量去满足这个三个规范,一般2NF都有,1NF与3NF不一定满足。

1NF:列不可分,为了排除重复组的出现,所采用的方法是要求数据库的每个列的值域都是由原子值(不可分)组成;每个字段的值都只能是单一的值。

2NF:数据表中除了主键之外的其他列,都必须依赖于主键存在,不然不应该设计在同一表中。(主键-->自增int数字,为了方便区分,比较,数字之间比较很快,方便索引存储)

3NF:要求所有非主键属性都只和候选键有相关性,也就是说非主键属性直接应该是独立无关的。

sql语句

1、DDL,数据定义语言,建,修改,删除表等的语句
create table 建表(desc tableName 查看表信息)
create table tableName(column definition references FK_tableName(id),(在创建时添加外键)column definition )(column字段/列,definiton定义)
column definition(字段的定义):
columnName(字段名),datatype(数据类型), constraint(约束)。
constraint (约束): not null(非空),primary key(主键),foregin key(外键),(默认值)default value...

建立表的结构时,存储数据之前,要先把数据的格式给定义清楚。命名根据公司的规范,没有就尽量符合java的命名规范就行。

alter table 修改表
	add column(添加列)
		alter table tableName add column defintion;
	drop column(删除列)
		alter table tableName drop column columnName;
	modify column datatype(修改列的数据类型)(必须先保证列的值为空)
		alter table tableName modify columnName newDatatype;
	rename column name(修改列的名称)
		alter table tableName rename column oldColumName to newColumName;
	rename table(修改表的名称)
		alter table tableName rename to newTableName;
constraint 约束

​ 非空约束:

​ 主键约束:(非空约束+唯一约束)

	alter table tableName add constraint PK_NAEM primary key(columnName);(添加主键约束,括号里可以填两列,称为联合主键约束,但一般很难见到)

	alter table tableName drop constranint PK_NAEM;(删除主键约束)

​ 唯一约束:(空值不会受限制)

	alter table tableName add constraint UQ_NAME urique(columName);(添加)
	alter table tableName drop constraint UQ_NAME;(删除)

​ 外键约束:

​ 含义:表与表之间数据的关系,另外一张表的主键放在另一张表中作为一个字段来联系两张表。

	alter table tableName add constraint FK_NAEM foreign key(NewcolumName) references PK_TABLE_NAEM(PK_COLUMN_NAME);(这里的新的字段名必须先存在)

​ 主键表(主表),外键表(从表),删除数据时需要先删除从表的,才能再删主表的。

​ 检查约束:(mysql不支持)

	alter table tableName add constraint CK_NAME check(check expression);(添加)
	alter table tableName drop constraint CK_NAME;(删除)
drop table删除表
drop table tableName;
2、DML,对数据表进行操作的语句

插入,修改,删除-->更新语句;查询-->查询语句。

INSERT 插入数据。
insert into tableName(columnName,columnName,...) value(columNameValue,...);--字符串需要使用单引号,前后括号的值需要对应,顺序,个数。
UPDATE 修改数据
update tableName set colunmName =somevalue,colunmName =somevalue...... where condition;
--(可以改多个属性,也可以根据条件改几行)
DELETE 删除数据
delete from tableName where condition;
SELECT 查询语句(最复杂,单独为一类)
query(标准的查询语句)

(执行顺序,from-->where-->group by-->having-->order by-->)

​ selcet:(选择列)column 别名(前面不能加as,mysql可以;当别名为字符串时不加单引号,某些数据库要加,别名可指代这个字段)不能加*来查询全部,因为在数据大时与填写字段查会有很大区别,数据库优化第一步,去除所有 的 *,

​ from tableName(来源那张表)

​ where 对记录进行筛选

聚合函数/单行函数:max最大值,min最小值;(对字符串进行比较时,看编码集大小)sum(求和,只能对数字使用),avg(平均值),count(1-->id主键,统计表的所有字段,统计);(聚合函数调用时,所有null值都会被忽略;数据库通用的函数)

​ nvl(columnName,defaultvalue):并不是数据库通用的,部分数据库有,设置默认值,当字段值为空时,会自动填充默认值。(oracle中十分重要)

​ group by colum:分组,将值相同的分到同一组;一般都会与聚合函数联用,为了方便展示,因为分组后会根据字段值分为几个组的数据,数据条数可能不同,不好展示。having:对group by的结果进行再次过滤,针对分组后的几个组的数据进行过滤,不需要对那个字段进行过滤;后面也加聚合函数,与group by使用的聚合函数可以相同也可以不同;

​ order by column;根据字段排序,可通过多个字段排序,默认升序asc,降序desc;(空值排序没有统一标准)

多表查询(左连接,右连接,全连接,内连接,笛卡尔集)

​ 以空间换取时间

(权限设计,五表权限-->user用户 user_role role角色 role_resource resource权限)

​ 左/右连接:拿左/右边的表为基准,根据某一个字段拼接右/左边这张表,一般要以多,外键表来作为基准,这样就不会重复数据,根据具体情况而定;连接查询后,表的字段会横向变多,

​ form tableName1 left/right join tableName2 on(table1.column = tableName2.column );

​ 内连接:inner join,取交集,以全连接作为基准,筛选条件符合的数据;

​ 全连接:full join,左连接+右连接;

​ 笛卡尔集:拿a表的每一条去拼接b表的每一条,a*b;

select column from tableName1,tableName2; 

select * from tableName1,tableName2 where table1.column = tableName2.column;--与内连接效果相同
子查询,条件子查询

​ 条件子查询:将一个查询作为另一个查询的条件;

​ 例子,查询每个部门中薪水最大的人的信息

select deptid,max(salary) from emp group by deptid;这条语句查询了每个部门id和最大薪水,而查询的人必须再从emp中筛选,且满足上面的部门id与薪水。可以把这个查询的数据作为一张临时表,再用emp表去内连接它:

select emp.* from emp,(

select deptid,max(salary) maxsalary from emp group by deptid

) emp2 where emp.deptid=emp2.deptid and emp.salary=emp2.maxsalary;

--另一种实现方法:

select * from emp e where e.salary =(

select max(salary) from emp e2 where e.deptid = e2.deptid group by e.deptid

);--可看作关联子查询,条件子查询,这条性能没有上面的好,要进行多次筛选。	
	select distinst column from tableName;--去重,但公司禁用,性能太低,数据量大时运行容易出问题。
	--查找重复的数据
	
	select * from table where column in(
        
	select column from tableName group by column having count(1)>1);
	--删除重复的数据
	
	delete from tableName where name in
	
	(select name from tableName group by name having count(1)>1)
	
	and id not in
	
	(select max(id) from tableName group by name having count(1)>1);--删除name重复项且留下id最大的name;
横竖表转换

​ 横表在操作时,需要跨很多表进行操作,这明显不现实,并且设计时将会有很多张表;而竖表会更加方便,操作更加方便,但数据量会变大,以空间换时间;所以我们会设计使用竖表,展示使用横表展示给用户。

横表

id name shuxue yuwen yinyu
1 xxx 90 80 70
2 xxx2 80 90 70

竖表

id name subject chengji
1 xxx 数学 90
2 xxx 语文 80
3 xxx 英语 60

横表转竖表

insert into score2--(直接将表插入)

select name,'语文' subject,yuwen from score1;

union--(纵向地拼接结果集)

select name,'数学',shuxue,from score1;

union

select name,'英语',yingyu,from score1;

竖表转横表

select t1.name,t1.score yuwen,t2.score shuxue,t3.score yingyu from(  
select name,score from score2 where subject =‘语文’; 
)t1

left join

(  
select name,score from score2 where subject =‘数学’;
)t2 on t1.name = t2.name

left join

(   
select name,score from score2 where subject =‘英语’;   
)t3 on t2.name = t3.name
结果集运算
	minus -减 union +加 (plus)INTERSECT 求交集

	union [all](并集,默认会去重,加上all不去重)
	select column1,column2 from tableName
	union
	select column3,column4 from tableName;(纵向拼接/相加两个表,上下两个对应的字段可以名字不同,但数量和数据类型必须相同)
	minus(差集)
select * from student where rownum<=4
minus
select * from student where rownum<=2;(这条用于学习minus集合相减,性能并不好)

PLSQL编程

​ 基于sql语句,是oracle用来操作数据库的扩展,体现oracle的不同,提升其操作性能;P-->存储过程,L-->language;除了sql的数据类型,还会有扩展的数据类型,集合,记录等;

静态sql语句,自己写定的;

动态sql语句,由别人传过来的,事先不知道的;

​ EXECUTE IMMEDIATE 字符串:立即执行

declare
	mysql varchar2(50);
begin
	mysql:=&mysql;--会弹出一个输入框让你输入mysql的值,可以输入一条sql更新命令,命令需要用单引号引起
	dbms_output.put_line(mysql);
	execute immediate mysql;--执行这条sql语句,如果是查询语句不会有结果,因为是pl-sql语句块,不是正常的sql语句
end

select * from student;--查询更新结果

1、基本组成

declare -- 变量声明
begin 
		-- 业务逻辑
exception -- 异常处理[可选]
end;

2、hello word(例子)

begin
	dbms_output.put_line('hello world');(打印语句不能打印布尔值)
end;

3、变量声明

​ declare

​ 变量名 CONSTANT(加上为声明常量) 变量的数据类型(可为sql datatype,也可为 pl/sql datatype) :=变量值;(:=赋值运算符)

​ begin

​ 变量名:=变量值;(也可分开写,先定义后赋值)

​ 业务逻辑

​ end;

赋值运算符

​ :=,select into

	declare
	i int;
	begin
	select 123 into i;--(可以查出某个数据或者将某个数据赋给一个变量)
	end

4、运算符(与sql差不多)

​ 算术运算符

​ + - * / **(多少次幂)

​ ||:连接符,拼接两个字符串;

​ 2**3:2的3次方;

​ 比较运算符

​ 字符串比较用is;

​ 逻辑运算:and,or,not;(boolean值除了true,false外,还可以为null,如果不赋值的话,默认为空)

​ true and null ==> null;

​ true or null ==> true;

​ null and null ==> null;

​ 赋值运算符

5、流程控制

(1)顺序流程
(2)分支/选择流程控制
if、if else、if elsif语句
		if condition then
			statement;
		end if;


		if condition then
			statement;
		else
			statement;
		end if;


		if condition then
			statement;
		elsif condition then
			statement;
		[elsif condition then......]
		end if;
case when
		case var
			when constant then statement;
			[when constant then statement;......]
			else statement;
		end case;
		secach case(多个条件分别进行判断)
			case 
			when condition then statement;
			[when condition then statement;......]
			else statement;
		end case;
(3)循环流程
a、Basic LOOP

​ (exit-->相当于java中的back,exit when 当条件满足时结束循环,if condition exit end if <===> exit when condition;continue,continue when)

loop
statement;
end loop;
b、FOR LOOP Index

for index in [reverse] (反向) lower_bound..upper_bound(范围,只能从小到大,包括两个边界值) loop(这里的index在循环体中只能读,不能修改,可赋值给别的变量;且与循环体外的同名的index不相关,出了循环体,index不能使用;如要在循环体内使用循环体外与index同名的变量,则需要使用main.index)
statement;
end loop;
c、WHILE LOOP
while condition loop
statement;
end loop;
d、GOTO statement
e、NULL statement

​ null;(什么都不执行)

6、pl-sql DataType

​ a、boolean

​ b、integer

​ c、cursor

​ d、%type %rowtype

​ %type(变量2取前面变量1/字段一样的数据类型)

​ 变量2 变量1/字段名%type;

​ 多使用在查询某个字段,根据字段的类型给某个变量赋数据类型,以方便赋值;

​ 例子:

		declare
			maxage studnet.age%type;
		begin
			select max(age) into maxage from student;(查询兼赋值)
		end; 

​ %rowtype (某一条记录的数据类型)

​ 变量名 tableName%rowtype;(存储一行的数据)

​ 例子:

		declare
			sturow student%rowtype;
		begin
			select * into sturow from student where id = 1;
			dbms_output.put_line(sturow.name || '--' || sturow.age);
		end;

7、伪例

​ 在oracle执行查询语句时,所临时生成的字段(列);

rownum 查询时生成的序号;(不适用于直接的>计算)

​ 用来做分页查询(淘宝使用的全文搜索 Elestatic Seach ES,该技术基于谷歌的论文, lucene谷歌的技术)

例子1:

select id,name,age,gender from
(
select rownum,tableName* from tableName where rownum<=2;
)

-- from student

-- 提取第一条记录 rownum(1) 1 aaa 18 male

-- 提取第二条记录 rownum(2) 2 abc 19 female

例子2:

select rownum,student.* from student where rownum <= 4 and rownum>2;

-- from student

-- 提取第一条记录 rownum(1) 1 aaa 18 male(不符合where条件,去掉,rownum会跟记录一起丢弃,所以后面两条将会是rownum(1),(2),所以四条记录都不符合条件,上面语句不会查出记录)

-- 提取第二条记录 rownum(2) 2 abc 19 female (同理)

下面是正确的解法:(与分页查询相关)

​ currentPage 当前第几页;

​ pageSize 每页显示多少条

	select id,name,age,gender
	from
	(
select rownum r,student.* from student where rownum<=4(currentPage * pageSize表示这页结束后的总记录条数)
	) t where t.r>2((currentPage-1) * pageSize前面页数的记录总和); 
rowid 查询时生成的唯一的字符串(oracle独有);

​ 特点:给了表的每一行记录后,值就不会变,无论怎么查询,不会像rownum一样根据查询的记录数发生改变;如果将某条记录删除后,再次插入一条新的,则rowid也会改变;

8、cursor(游标,一种静态sql)

​ 含义:一个指针,指向一个私有的sql区域,关于一个select语句或者dml语句的执行过程中的信息;(与jdbc中的结果集类似)

​ 作用:

implicit cursor/sql cursor:隐式游标,PL-SQL创建和管理的;

​ oracle隐式游标只有一个,名字为sql;每次执行一个select,DML语句,PL-SQL就会打开一个叫做SQL的隐式游标,语句结束时,这个游标会自动关闭,但是它还是会保持一个可用的状态,直到下一个select,DML语句运行,前面的值将会覆盖掉,所以,如果没有运行下一个语句,sql的信息就是最近运行的那一条语句的信息;因为游标是session级别的,所以不会有并发的问题,我们执行不能在一个时间同时执行多条sql,只能执行一条sql语句,所以sql的信息会是最近执行的那一条语句的;(这时候可以在覆盖,也就是下一条语句覆盖之前,需要获取的sql信息赋给本地变量以便使用)

​ 可以通过SQLattribute来获取隐式游标的属性信息;(这里需要注意%isopen属性一直是false状态,因为每次运行sql时,结束后都会关闭,所以它是在执行语句的同时打开的,当你看到语句的结果时,已经关闭了)

​ SQL游标大部分用于更新语句,查询语句一般用显式游标;

SQL游标的属性值:

​ select insert/update/delete

​ %isopen false false

​ %found 查询有结果return true,否则false 有影响的行数,true,否则false

​ %notfound 跟%found相反 跟%found相反

​ %rowcount 查询的结果集的记录数 受影响的行数

explicit cursor:显式游标,由操作者创建和管理;
a、显式游标的定义:

​ cursor cursorName is query sql;

b、打开游标:

​ open cursorName:

​ 打开游标会执行如下动作:

​ a、分配数据库资源;

​ b、执行查询,标记好对应的结果集,如果有带有for updata子句,锁定结果集的记录;

​ c、将游标指向结果集第一行记录的前面(字段行)

c、关闭游标:

​ close cursorName:

​ 关闭已打开的游标,关闭之后可以再次打开,没有关闭不能再次打开;

d、抓取数据:

​ fetch cursorName into var:

​ 每次抓取一条记录,每抓取一次记录,游标自动向下移动;

e、显式游标的属性:

​ %found(没有抓取数据之前,返回null,这时这个属性是没有意义的)

​ 分别返下列三种情况:

​ null:在游标打开之后,在第一次抓取数据之前,return null;

​ true:最近的一次fetch操作,如果返回了一行,return true;

​ false:除以上两种情况外,retrun false;

​ %notfound

​ 跟%found是逻辑的相反值

​ 返回null,true,false;(true与false的情况跟%found相反)

​ %isopen

​ 返回boolean,检查游标是否打开;(在代码量大时,在每次打开或者关闭游标时都需要使用这个进行判断,为了避免报错)

​ %rowcount

​ 在打开后,第一次抓取数据之前,使用返回为零,判断总共有多少条记录被fetch;

f、for loop cursor(类似增强for循环)

​ for item(游标中每个变量的值) in cursorName loop

​ end loop;

​ 例子:

declare
 cursor mycur is select * from student;
 sturow student%rowtype;(%rowtype表示一行记录的变量)
begin
 for sturow in mycur loop--当循环开始时,游标会自动打开,循环结束时会自动关闭
 	dbms_output.put_line('id:' || sturow.id);--在循环里可以直接使用,会自动抓取值
 end loop;
end;
例子:(将一张表的信息全复制到另一张表中)

​ 第一种做法:(需要知道其id,并且这个id还必须是int类型,根据id一个一个查,再一个一个放入另一张表,十分麻烦)

	declare
		sturow student%rowtype;
	begin
		for i in 1..4 loop
			select * into sturow from student where id=i;
insert into student2(id,name,age,gender) 	values(sturow.id,sturow.name,sturow.age,sturow.gender);								    		end loop;
	end;

create table studnt2 as select * from student where 1<>1;(将表结构给到另一张表,不给里面的值,不加where条件则结构与数据都给另一张表)

​ 第二种使用游标:

	declare	
		cursor mycur is selcet * from student;
		sturow student%rowtype;
	begin
		open mycur;
		loop
			fetch mycur into sturow;
			dbms_output.put_line  (sturow.name);
			exit when mycur%notfound;(抓取不到数据时退出)
		end loop;
		close mycur;
	end
session cursor会话级别游标:登入客户端一直有效,直到登出客户端才会失效;
PGA cursor:全局级别游标,可跨会话使用;

​ (请求级别:一般语句里面的变量,在语句结束后就没有效果了;)

9、sequence(序列,oracle独有)

与自增的id差不多

创建完sequence,将会从属于整个数据库,可以多个表使用;可以用它自动生成唯一的一个整形数,或者一个主键值,当这个序列产生后会自动往上加,独立在事务回滚之外的,如果多个用户并发地使用同一个序列,对它进行增长,这时要求有一个间隙,可以使用缓存cache来解决这个问题;

create sequence sequenceName start with(从几开始) 
integer increment by(自增的度长,默认每次加一,设置为几,每次加几)integer max/minvalue[no max/minvalue](最大/小值,没有最大/小值,一般设为九个九) 
cycle[no cycle](循环,没有循环;意思是当到达设置的最大或最小值之后,再增则会回到开始值重新自增) 
no/cache(缓存,先准备一个值放着,来的时候直接取值)
no/order(不按顺序性能好一点,只要唯一就可以;按顺序);(这个自增值可以为负数,为负数,则可设置最小值;设置正数,则可设置最大值)

例子:

create sequence mysql start with 1 increment by 2 maxvalue 999999999;

nextval currval(下一个,当前值)

​ nextval优先级大于currval,一行中多条nextval,只会执行一次nextval;

​ dual:虚拟表,虚拟表中永远都只有一条记录;(只计算一次表达式时使用)

drop sequence sequenceName;(删除序列)

10、tcl transaction control languge(事务控制语言)

​ 事务的概念:数据库的最小操作单位;

​ 特性:

​ 原子性A,最小操作单位,不可分割;

​ 一致性C,事务内的所以操作,要么一起成功,要么一起失败;

​ 隔离性I,事务相互之间不影响;

    持久性D,事务生效之后,会永久保存在硬盘上;

​ (ACID)

​ 隔离级别:Oracle只有两种(已提交读与串行化)myslq有四个:未提交读,已提交读,可重复读,串行化;

COMMIT;(提交事务)
ROLLBACK;(回滚事务)
SAVEPOINT;(保存点)

​ 执行更新语句后,不会立即生效,oracle会自动开启事务,等待提交或者回滚;

​ DDL执行之后,默认自带commit;

例子:

insert into student(id,name,age,gender) values(1,'eee',23,'male');
savepoint s1;
insert into student(id,name,age,gender) values(1,'eee',23,'male');
savepoint s2;
insert into student(id,name,age,gender) values(1,'eee',23,'male');
savepoint s3;
insert into student(id,name,age,gender) values(1,'eee',23,'male');
savepoint s4;
insert into student(id,name,age,gender) values(1,'eee',23,'male');

rollback to s3;--回滚s3这个保存点,当某些语句出错误时,回滚到对应的处理;

11、procedure(存储过程,多用于更新)

​ (会对数据库服务器造成很大压力,移植性差,所以越来越少使用,会将相应的逻辑代码放入java代码中去优化)

​ 创建语法:

create [or replace] procedure procedureName--(创建或者覆盖)
	(parameter list)--(参数列表)
	is
	local_varicable declare--(本地变量声明)
	begin	
	business statement;
	end;

​ 简单例子:

	create or replace procedure mypro
	is
	begin
		dbms_output.put_line('hello procedure!!!');
	end;

​ 有参数的例子:

	create or replace procedure mypro2
	(
    i [in/out/in out] int default 1,--这里的类型不能类似varchar2(50),括号不能用-->varchar2;数据类型前可加形参的模式
    j int default 2 --可设默认值,设置默认值后调用可以不传参数,不然必须传参数
    )
	is
	s int;
	begin
		s:=i+j;
		dbms_output.put_line(s);
	end;	
	call mypro2(3,4);--结果为7
	call mypro2();--结果为3
	call mypro2(j => 5);-- 名称表示法"=>" 修改默认值,结果为6

​ 调用时使用call procedureName;

​ drop procedure procedureName(删除存储过程)

形式参数(存储过程,函数都有)
参数的三种模式

​ IN mode:默认的模式,只读模式;这个模式的参数是只读的,存储过程开始调用的时候,将实参的值赋给形参。在整个存储过程的内部,in模式的形参,不可更改,为常量。(不能作为赋值的目标)in模式的参数不会影响实参;

​ OUT mode:只写,必须手动指定。在存储过程调用之前,out模式的形参是根据他的数据类型取默认值(null),当存储过程调用完后了之后,会将形参的值赋给实参;out模式的实参是不能为常量的;

​ IN OUT mode:手动指定,in与out模式的结合体;

参数的传递方法

​ 位置表示法:按照实参的顺序匹配对应的形参

​ 名称表示法:(形参的名字=>实参)

​ 混合表示法:

​ 例子:(求学生表中全班的平均年龄,还有男,女某一个性别人数总和)

create or replace procedure mypro4
(
gen in varchar2,
avgage out number,
gendercount out int
)
is
begin
	select avg(age) into avgage from student;
	select count(1) into gendercount from student where gender=gen;
end;

declare
	gender varchar(50):='male';
	avga number;
	gcount int;
begin
	mypro4(gen => gender,avgage => avga,gendercount => gcount);
	dbms_output.put_line('性别为:' || gender || '人数总和是:' || gcount);
	dbms_output.put_line('全班平均年龄为:' || avga);
end;

12、function(函数多用于查询)

​ (函数与存储过程在结构上的区别就是函数可以有返回值)

create [or replace] function functionName
(parameter list)
retrun datatype--返回值数据类型
is
local_varicable declare--(本地变量声明)
begin	
business statement;
end;

select functionName() form dual;--调用
drop function functionName();--删除函数

function内部不能执行更新语句,procedure内部可以执行更新语句;

procedure的事务跟调用事务是一起的,但是,如果procedure的内部存在commit语句的话,会分割为两个事物,则procedure的事务单独提交;

简易例子:

create or replace function mufun
retrun int
begin
	dbms_output.put_line('hello myfunction');
	return 1;
end;

--计算和         
create or replace function mufun2
(
i in int,
j in int
)
retrun int
is
begin
	return i+j;
end;
select mtfun2(2,3) from dual;

--某性别的总人数
create or replace function mufun3
(
gen varchar2
)
retrun int
is
cc int;
begin
	select count(1)form student where gender=gen;
	retrun cc;
end;
select mtfun3('male') from dual;
oracle内置的函数(其他数据库不一定有效)
数值/数学函数:(常用的几个)

​ ABS(); 求绝对值

​ CEIL(); 向上取整

​ FLOOR(); 向下取整

​ MOD(); 取余

select mod(13,4) from dual;--结果为1
select mod(13.4,4) from dual;--结果为1.4
select mod(-13,4) from dual;--结果为-1
select mod(13,-4) from dual;--结果1

​ SQRT();求平方根

字符函数

​ CONCAT(a,b); 字符串连接(与||效果一样);

​ CHR(); 传一个数字进去,返回相应编码的字符;

​ INITCAP(); 每一个单词首字母大写;

​ LOWER(); 转换为小写;

​ UPPER(); 转换为大写;

​ L/RPAD(); 在字符的L左边/R右边使用某些字符进行补全到指定长度字符;

select LPAD('Page 1',15,'*.') from DUAL;
--结果为*.*.*.*.*Page 1

​ L/RTRIM(); 去除字符左/右边指定的字符,当遇到不是指定字符后将会停止;

​ TRIM(); 可以去头或者去尾,也可以都去;

select LTRIM('<======>BROWNING<======>','<>=') from DUAL;
--结果为BROWNING<======>

​ REGEXP_REPLACE(); 与正则表达式相关;

​ SUBSTR(); 根据字符为单位长度,截取字符串;

​ TRANSLATE(); 关键字屏蔽,字符转换;

select translate('abacadefgtttt','abcdefg','123456') from dual;
--结果为12131456tttt,将第二个字符串一个一个对应的转换为第三字符串的字符,如果第二个字符有多出的会被省略,可以理解为替换为null;
转换函数
null函数
系统环境函数
日期函数

​ extract(datetime);提取时间里面的信息,时分秒等;

select extract(year from birthday) from student where id=1;
select extract(day from sysdate)from dual;

​ sysdate; 返回操作系统的时间,后面不用加括号;

​ current_date; 根据时区返回系统时间,后面不加括号;

​ add_months; 添加月份,负数为减少;

select add_months(sysdate,1) from dual;--月份加一
select add_months(sysdate,-1) from dual;--月份减一

​ months_between; 求两个日期间隔多少个月,返回的是浮点数;

​ next_day; 某个日期的下个星期几;

​ to_char(); 将对应的日期转换为对应的格式;

select to_char(sysdate,'YYYY"年"MON/DD HH/MI/SS') from dual;--格式中如果有中文需要加双引号引起;

​ trunc(); 传入一个日期,指定一个日期属性,如年份year,则除年份外其他属性都清除掉,回到原点,x月y日回到1月1日;

13、trigger(触发器)

定义:

​ 触发器跟存储过程一样,是一个PL-SQL单元块,存储在数据库里。但是触发器不能被显式的调用;

​ 触发器是可以启用和禁用的,默认创建时处于启用状态;

​ 当指定的事件发生的时候,触发器就会被oracle调用执行,那么这个过程称之为触发器触发(fires)。

组成:

​ 触发事件:触发器要执行的指定事件;(DML触发器指定的触发事件就是DML操作,更新(insert,delete,update)语句)

​ 触发目标:触发器指定的事件在什么对象上执行,可以是table,view,schema(用户),database;

​ 触发时机:触发器在指定事件之前还是之后执行;

​ 触发频率:分为两种,行级触发器与语句级触发器;

​ 触发条件:在触发器定义中,通过when子句,指定触发器触发的条件。

创建:
create or replace trigger triggerName
before | after | instead of --触发的时间
INSERT or UPDATE[of column,...] or DELETE ON tableName--多个的话加or;update有一点区别,加of columnb表示对某一个字段进行修改,多个字段加逗号
[referencing clause]
[for each row ]
begin
 business statement;
end;
例子:
--删除表,打印
create or replace trigger mytrigger
before delete on student
for each row
begin
 dbms_output.put_line('delete a row on student');
end;

delete from student;


--删除表数据时,将删除的数据插入到备份表中
create or replace trigger mytrigger
after delete on student
referencing old as oo
for each row
begin
	insert into student_back(id,name,age,gender)
	values(:oo.id,:oo.name,:oo.age,:oo.gender);
end;

delete from student where id = 1;
--referencing old/new as name(可以对下面的语句进行改名,不该默认为old与new)
--:old(执行删除语句时,引用即将删除的数据)
--:new(执行插入语句时,引用即将插入的数据)


create or replace trigger mytrigger
before update of name on student--更新name这一列时才起作用
referencing old as oo new as nn
for each row
begin
	dbms_output.put_line('old name:' || oo.name);
	dbms_output.put_line('new name:' || nn.name);
end;

update student set age = 100 where id=1;--这条不会触发
update student set naem = "sadad" where id=1;--这条语句执行才会触发

14、view(视图)

​ 保存的就是一个sql语句;类似创建一个中间表方便查询,简化查询,即当一个查询语句十分复杂时,将结果放入视图作为中间表,查询起来更方便;在视图中进行更新操作会影响到原表,所以可以在创建视图时可以在语句后加一个with read only;

create view viewName as 语句 [with read only];

​ 当需要连接多个表进行查询的时候,导致其查询语句十分复杂,这时就可以将这条查询语句放进视图中,再次查询就可以通过视图进行查询,简化查询;

15、index(索引,为了增加查询速度)

​ 表中的数据量很大时,需要最快搜索到某一条记录,怎么做?

​ 首先,我们需要知道根据什么进行查询数据;如果是根据id主键进行查询,因为id已经排好序,所以查询会比较快,只需要将数据按合适的分组进行查询就可以了;但如果是别的字段,我们需要将id与这个字段提取出来放在另一个表中,然后对这个字段进行排序和分组查询,查询到这个字段后,在根据其id去找原表的数据,这就是索引的原理;

​ 百分之八十查询慢的问题,都可以通过使用索引来优化;使用索引时要使用后置匹配,前置匹配会导致索引失效;

​ 索引也有缺点,当索引中的数据在原表中被修改,那么索引中也要改,这样反而会影响更新的性能,所以一般在索引里的值不常改;但是如果一定要改,这个时候涉及到一个术语-- 数据归档,当数据中有某一些数据是很久之前的,一般不会再去修改的时候,这时会将这些数据定死/归档,或者专门移到另一个表中,然后再建立索引去查询;

16、exception(异常)

​ 与java作用一样,为了不让语句异常终止;

​ 捕获异常

declare
begin
exception	--捕获指定异常名称的异常,然后执行下面语句
	when exceptionName then
		statement;
end;

​ 手动引发异常

RAISE 异常名字:提示信息--类似java中的throw

​ 例子:

declare
	i int := 0;
begin
	i :=5/i;
exception
	when ZERO_DIVIDE then
		dbms_output.put_line('除数不能为零!');
end;

ORACLE DBMS

容灾,读写分开,集群等;

备份-->import导入 export导出;

grant ,赋予权限,用户不具备删库删表的权限,避免删库跑路;只有逻辑删除,没有物理删除,标记删除的数据,实际上每条数据进入数据库中不会被删除;我们只有查询更新的权限。

原文地址:https://www.cnblogs.com/zzdbk/p/14274936.html