ORACLE RDBMS 中级进阶技术

举报
tea_year 发表于 2023/12/06 22:15:09 2023/12/06
【摘要】  一.视图[应用]视图就是封装了一条复杂查询的语句。语法 1.:CREATE VIEW 视图名称 AS 子查询范例:建立一个视图,此视图包括了 20 部门的全部员工信息create view empvd20 as select * from emp t where t.deptno = 20 视图创建完毕就可以使用视图来查询,查询出来的都是 20 部门的员工语法 2:CREATE OR RE...

 



.视图[应用]

视图就是封装了一条复杂查询的语句。


语法 1.:CREATE VIEW 视图名称 AS 子查询

范例:建立一个视图,此视图包括了 20 部门的全部员工信息

create view empvd20 as select * from emp t where t.deptno = 20 视图创建完毕就可以使用视图来查询,查询出来的都是 20 部门的员工

语法 2:CREATE OR REPLACE VIEW 视图名称 AS 子查询

如果视图已经存在我们可以使用语法 2 来创建视图,这样已有的视图会被覆盖。create or replace view empvd20 as select * from emp t where t.deptno = 20


那么视图可以修改吗?




我们尝试着修改视图但是发现是视图所查询的表的字段值被修改了。所以我们一般不会去修改 视图。

我们可以设置视图为只读。


语法 3:CREATE OR REPLACE VIEW 视图名称 AS 子查询 WITH READ ONLY

create or replace view empvd20 as select * from emp t where t.deptno = 20 with read only



.索引[应用]

索引是用于加速数据存取的数据对象。合理的使用索引可以大大降低 i/o 次数,从而提高数据访问性能。索引有很多种我们主要介绍常用的几种:

为什么添加了索引之后,会加快查询速度呢?

图书馆:如果杂乱地放书的话检索起来就非常困难,所以将书分类,然后再建一个箱子,箱 子里面放卡片,卡片里面可以按类查询,按书名查或者类别查,这样的话速度会快很多很多,

这个就有点像索引。索引的好处就是提高你找到书的速度,但是正是因为你建了索引,就应该有人 专门来维护索引,维护索引是要有时间精力的开销的,也就是说索引是不能乱建的,所以建索引有 个原则:如果有一个字段如果不经常查询,就不要去建索引。现在把书变成我们的表,把卡片变成 我们的索引,就知道为什么索引会快,为什么会有开销。

创建索引的语法: 创建索引:

1. 单列索引

单列索引是基于单个列所建立的索引,比如:


CREATE index 索引名    on 表名(列名)

2. 复合索引

复合索引是基于两个列或多个列的索引。在同一张表上可以有多个索引,但是 要求列的组合必须不同,比如:

Create index emp_idx1 on emp(ename,job); Create index emp_idx1 on emp(job,ename);


范例:给 person 表的name 建立索引

create index pname_index on person(name);

范例:给 person 表创建一个 name 和 gender 的索引

create index pname_gender_index on person(name, gender); 索引的使用原则:

在大表上建立索引才有意义

where 子句后面或者是连接条件上的字段建立索引

表中数据修改频率高时不建议建立索引



.pl/sql 基本语法[了解]


什么是 PL/SQL?

PL/SQL(Procedure Language/SQL)

PLSQL 是 Oracle 对sql 语言的过程化扩展,指在 SQL 命令语言中增加了过程处理语句(如分支、循环等),使 SQL 语言具有过程处理能力。把 SQL 语言的数据操纵能力与过程语言的数据处理能力结合起来,使得 PLSQL 面向过程但比过程语言简单、高效、灵活和实用。

范例 1:为职工涨工资,每人涨 10%的工资。update emp set sal=sal*1.1

范例 2:例 2: 按职工的职称长工资,总裁涨 1000 元,经理涨800 元,其他人员涨 400 元。

这样的需求我们就无法使用一条 SQL 来实现,需要借助其他程序来帮助完成,也可以使用 pl/sql。


1.%2.%3 pl/sql 程序语法



程序语法:

declare begin


说明部分        (变量说明,游标申明,例外说明 〕语句序列    (DML 语句〕…


exception

例外处理语句

End;



2.%2.%3 常量和变量定义


在程序的声明阶段可以来定义常量和变量。

变量的基本类型就是 oracle 中的建表时字段的变量如 char, varchar2, date, number, boolean, long

定义语法:varl    char(15); Psal    number(9,2);

说明变量名、数据类型和长度后用分号结束说明语句。常量定义:married    constant boolean:=true

引用变量

Myname    emp.ename%type;

引用型变量,即my_name 的类型与emp 表中 ename 列的类型一样在 sql 中使用 into 来赋值

declare

emprec emp.ename%type; begin

select t.ename into emprec from emp t where t.empno = 7369; dbms_output.put_line(emprec);

end;

记录型变量

Emprec    emp%rowtype

记录变量分量的引用emp_rec.ename:='ADAMS'; declare

p emp%rowtype;

begin

select * into p from emp t where t.empno = 7369; dbms_output.put_line(p.ename || ' ' || p.sal);

end;


3.%2.%3 if 分支


语法 1:

IF    条件    THEN 语句 1;

语句 2; END IF;

语法 2:

IF 条件    THEN    语句序列 1

ELSE        语句序列 2END    IF

语法 3:

IF    条件    THEN ;

ELSIF 语句    THEN    ;


ELSE        ; END    IF;

范例 1:如果从控制台输入 1 则输出我是 1

declare

pnum number := # begin

if pnum = 1 then

dbms_output.put_line('我是1'); end if;

end;

范例 2:如果从控制台输入 1 则输出我是 1 否则输出我不是 1

declare

mynum number := # begin

if mynum = 1 then

dbms_output.put_line('我是1'); else

dbms_output.put_line('我不是1');

end if; end;

范例 3:判断人的不同年龄段 18 岁以下是未成年人,18 岁以上 40 以下是成年人,40 以上是老年人

declare

mynum number := # begin

if mynum < 18 then

dbms_output.put_line('未成年人'); elsif mynum >= 18 and mynum < 40 then

dbms_output.put_line('中年人'); elsif mynum >= 40 then

dbms_output.put_line('老年人');

end if; end;



4.%2.%3 LOOP 循环语句


语法 1:

WHILE    total    <= 25000    LOOP


.. .

total : = total + salary;

END    LOOP;

语法 2:

Loop

EXIT [when    条件];

…… End loop

语法 3:

FOR    I    IN    1 . . 3    LOOP

语句序列 ;

END    LOOP ;

范例:使用语法 1 输出 1 到10 的数字

declare

step number := 1; begin

while step <= 10 loop dbms_output.put_line(step); step := step + 1;

end loop; end;

范例:使用语法 2 输出 1 到10 的数字

declare

step number := 1; begin

loop

exit when step > 10; dbms_output.put_line(step); step := step + 1;

end loop; end;

范例:使用语法 3 输出 1 到10 的数字

declare

step number := 1; begin

for step in 1 .. 10 loop dbms_output.put_line(step);

end loop; end;


5.%2.%3 游标 Cursor


resultSet


在写 java 程序中有集合的概念,那么在 pl/sql 中也会用到多条记录,这时候我们就要用到游标, 游标可以存储查询返回的多条数据。


语法:

CURSOR    游标名    [ (参数名    数据类型,参数名 数据类型,...)]    IS    SELECT    语句; 例如:cursor c1 is select ename from emp;

游标的使用步骤:

    open c1;    ()

取一行游标的值:fetch c1 into pjob; (取一行到变量中)

    close    c1;()

    exit when c1%notfound

注意: 上面的 pjob 必须与 emp 表中的 job 列类型一致: 定义:pjob emp.empjob%type;

范例 1:使用游标方式输出 emp 表中的员工编号和姓名

declare cursor pc is

select * from emp; pemp emp%rowtype;

begin

open pc; loop

fetch pc into pemp;

exit when pc%notfound;

dbms_output.put_line(pemp.empno || ' ' || pemp.ename); end loop;

close pc; end;

范例 2:按员工的工种涨工资,总裁 1000 元,经理涨 800 元其,他人员涨 400 元。备份出一张新表为 myemp;create table myemp as select * from emp;

declare cursor pc is

select * from myemp; addsal myemp.sal%type; pemp myemp%rowtype;

begin

open pc; loop

fetch pc into pemp;

exit when pc%notfound;

if pemp.job = 'PRESIDENT' then addsal := 1000;

elsif pemp.job = 'MANAGER' then addsal := 800;

else

addsal := 400;


end if;

update myemp t set t.sal = t.sal + addsal where t.empno = pemp.empno;

end loop; close pc;

end;


范例 3:写一段PL/SQL 程序,为部门号为 10 的员工涨工资。

declare

cursor pc(dno myemp.deptno%type) is

select empno from myemp where deptno = dno; pno myemp.empno%type;

begin

open pc(20); loop

fetch pc into pno;

exit when pc%notfound;

update myemp t set t.sal = t.sal + 1000 where t.empno = pno; end loop;

close pc; end;



.存储过程[理解]



存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的 SQL 语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来 执行它。存储过程是数据库中的一个重要对象,任何一个设计良好的数据库应用程序都应该用到存 储过程。


创建存储过程语法:

create [or replace] PROCEDURE 过程名[(参数名 in/out 数据类型)] AS

begin

PLSQL 子程序体;

End;


或者



create [or replace] PROCEDURE 过程名[(参数名 in/out 数据类型)] is

begin

PLSQL 子程序体;

End    过程名;


范例:创建一个输出 helloword 的存储过程

create or replace procedure helloworld is begin

dbms_output.put_line('helloworld'); end helloworld;


调用存储过程

在 plsql 中调用存储过程

begin

-- Call the procedure

helloworld; end;


范例 2:给指定的员工涨 100 工资,并打印出涨前和涨后的工资分析:我们需要使用带有参数的存储过程

create or replace procedure addSal1(eno in number) is pemp myemp%rowtype;

begin

select * into pemp from myemp where empno = eno; update myemp set sal = sal + 100 where empno = eno;

dbms_output.put_line(' 涨工资前' || pemp.sal || ' 涨工资后' || (pemp.sal + 100));

end addSal1;


调用

begin

-- Call the procedure addsal1(eno => 7902); commit;

end;


.存储函数[理解]


自定义函数

Sysdate nvl max sum


create or replace function 函数名(Name in type, Name in type, ...) return 数据类型

is

结果变量 数据类型; begin

return(结果变量);

end 函数名;


存储过程和存储函数的区别

一般来讲,过程和函数的区别在于函数可以有一个返回值;而过程没有返回值。

但过程和函数都可以通过 out 指定一个或多个输出参数。我们可以利用 out 参数,在过程和函数中实现返回多个值。


范例:使用存储函数来查询指定员工的年薪

create or replace function empincome(eno in emp.empno%type) return number

is

psal    emp.sal%type; -- 这两个是变量

pcomm emp.comm%type; -- 计算变量

begin

select t.sal,t.comm into psal,pcomm from emp t where t.empno = eno;

return psal * 12 + nvl(pcomm, 0); -- 这个是返回函数结果,工资*12+奖金;

end;


使用存储过程来替换上面的例子

create or replace procedure empincomep(eno in emp.empno%type, income out number) is

psal emp.sal%type; pcomm emp.comm%type;

begin

select t.sal, t.comm into psal, pcomm from emp t where t.empno

= eno;

income := psal*12+nvl(pcomm,0); end empincomep;


调用:

declare

income number; begin

empincomep(7369, income);


dbms_output.put_line(income); end;


拼音码

CREATE OR REPLACE FUNCTION F_TRANS_PINYIN_CAPITAL(P_NAME IN VARCHAR2)

RETURN VARCHAR2 AS

V_COMPARE VARCHAR2(100);

V_RETURN VARCHAR2(4000);


FUNCTION F_NLSSORT(P_WORD IN VARCHAR2) RETURN VARCHAR2 AS

BEGIN

RETURN NLSSORT(P_WORD, 'NLS_SORT=SCHINESE_PINYIN_M');

END;

BEGIN

FOR I IN 1 .. LENGTH(P_NAME) LOOP

V_COMPARE := F_NLSSORT(SUBSTR(P_NAME, I, 1));

IF V_COMPARE >= F_NLSSORT('吖') AND V_COMPARE <= F_NLSSORT('驁') THEN

V_RETURN := V_RETURN || 'a';

ELSIF V_COMPARE >= F_NLSSORT('八') AND V_COMPARE <= F_NLSSORT('簿') THEN

V_RETURN := V_RETURN || 'b';

ELSIF V_COMPARE >= F_NLSSORT('嚓') AND V_COMPARE <= F_NLSSORT('錯') THEN

V_RETURN := V_RETURN || 'c';

ELSIF V_COMPARE >= F_NLSSORT('咑') AND V_COMPARE <= F_NLSSORT('鵽') THEN

V_RETURN := V_RETURN || 'd';

ELSIF V_COMPARE >= F_NLSSORT('妸') AND V_COMPARE <= F_NLSSORT('樲') THEN

V_RETURN := V_RETURN || 'e';

ELSIF V_COMPARE >= F_NLSSORT('发') AND V_COMPARE <= F_NLSSORT('猤') THEN

V_RETURN := V_RETURN || 'f';

ELSIF V_COMPARE >= F_NLSSORT('旮') AND V_COMPARE <= F_NLSSORT('腂') THEN

V_RETURN := V_RETURN || 'g';

ELSIF V_COMPARE >= F_NLSSORT('妎') AND V_COMPARE <= F_NLSSORT('夻') THEN

V_RETURN := V_RETURN || 'h';

ELSIF V_COMPARE >= F_NLSSORT('丌') AND V_COMPARE <= F_NLSSORT('攈') THEN

V_RETURN := V_RETURN || 'j';

ELSIF V_COMPARE >= F_NLSSORT('咔') AND V_COMPARE <= F_NLSSORT('穒') THEN

V_RETURN := V_RETURN || 'k';

ELSIF V_COMPARE >= F_NLSSORT('垃') AND V_COMPARE <= F_NLSSORT('擽') THEN

V_RETURN := V_RETURN || 'l';

ELSIF V_COMPARE >= F_NLSSORT('嘸') AND V_COMPARE <= F_NLSSORT('椧') THEN

V_RETURN := V_RETURN || 'm';

ELSIF V_COMPARE >= F_NLSSORT('拏') AND V_COMPARE <= F_NLSSORT('瘧') THEN

V_RETURN := V_RETURN || 'n';

ELSIF V_COMPARE >= F_NLSSORT('筽') AND V_COMPARE <= F_NLSSORT('漚') THEN

V_RETURN := V_RETURN || 'o';

ELSIF V_COMPARE >= F_NLSSORT('妑') AND V_COMPARE <= F_NLSSORT('曝') THEN

V_RETURN := V_RETURN || 'p';

ELSIF V_COMPARE >= F_NLSSORT('七') AND V_COMPARE <= F_NLSSORT('裠') THEN

V_RETURN := V_RETURN || 'q';

ELSIF V_COMPARE >= F_NLSSORT('亽') AND V_COMPARE <= F_NLSSORT('鶸') THEN

V_RETURN := V_RETURN || 'r';

ELSIF V_COMPARE >= F_NLSSORT('仨') AND V_COMPARE <= F_NLSSORT('蜶') THEN

V_RETURN := V_RETURN || 's';

ELSIF V_COMPARE >= F_NLSSORT('侤') AND V_COMPARE <= F_NLSSORT('籜') THEN

V_RETURN := V_RETURN || 't';

ELSIF V_COMPARE >= F_NLSSORT('屲') AND V_COMPARE <= F_NLSSORT('鶩') THEN

V_RETURN := V_RETURN || 'w';

ELSIF V_COMPARE >= F_NLSSORT('夕') AND V_COMPARE <= F_NLSSORT('鑂') THEN

V_RETURN := V_RETURN || 'x';

ELSIF V_COMPARE >= F_NLSSORT('丫') AND V_COMPARE <= F_NLSSORT('韻') THEN

V_RETURN := V_RETURN || 'y';

ELSIF V_COMPARE >= F_NLSSORT('帀') AND V_COMPARE <= F_NLSSORT('咗') THEN

V_RETURN := V_RETURN || 'z';

ELSE V_RETURN := V_RETURN || SUBSTR(P_NAME, I, 1);

END IF;

END LOOP;

RETURN UPPER(V_RETURN);

END;

-- 调用

select F_TRANS_PINYIN_CAPITAL('张晨光') from dual



大小写转换:

Create Or Replace Function Money2Chinese(Money In Number) Return Varchar2 Is

strYuan Varchar2(150);

strYuanFen Varchar2(152);

numLenYuan Number;

numLenYuanFen Number;

strRstYuan Varchar2(600);

strRstFen Varchar2(200);

strRst Varchar2(800);

Type typeTabMapping Is Table Of Varchar2(8) Index By Binary_Integer;

tabNumMapping typeTabMapping;

tabUnitMapping typeTabMapping;

numUnitIndex Number;

i Number;

j Number;

charCurrentNum Char(1);

Begin

If Money Is Null Then

Return Null;

End If;

strYuan := TO_CHAR(FLOOR(Money));

If strYuan = '0' Then

numLenYuan := 0;

strYuanFen := lpad(TO_CHAR(FLOOR(Money * 100)), 2, '0');

Else

numLenYuan := length(strYuan);

strYuanFen := TO_CHAR(FLOOR(Money * 100));

End If;

If strYuanFen = '0' Then

numLenYuanFen := 0;

Else

numLenYuanFen := length(strYuanFen);

End If;

If numLenYuan = 0 Or numLenYuanFen = 0 Then

strRst := '零圆整';

Return strRst;

End If;

tabNumMapping(0) := '零';

tabNumMapping(1) := '壹';

tabNumMapping(2) := '贰';

tabNumMapping(3) := '叁';

tabNumMapping(4) := '肆';

tabNumMapping(5) := '伍';

tabNumMapping(6) := '陆';

tabNumMapping(7) := '柒';

tabNumMapping(8) := '捌';

tabNumMapping(9) := '玖';

tabUnitMapping(-2) := '分';

tabUnitMapping(-1) := '角';

tabUnitMapping(1) := '';

tabUnitMapping(2) := '拾';

tabUnitMapping(3) := '佰';

tabUnitMapping(4) := '仟';

tabUnitMapping(5) := '万';

tabUnitMapping(6) := '拾';

tabUnitMapping(7) := '佰';

tabUnitMapping(8) := '仟';

tabUnitMapping(9) := '亿';

For i In 1 .. numLenYuan Loop

j := numLenYuan - i + 1;

numUnitIndex := Mod(i, 8);

If numUnitIndex = 0 Then

numUnitIndex := 8;

End If;

If numUnitIndex = 1 And i > 1 Then

strRstYuan := tabUnitMapping(9) || strRstYuan;

End If;

charCurrentNum := substr(strYuan, j, 1);

If charCurrentNum <> 0 Then

strRstYuan := tabNumMapping(charCurrentNum) ||

tabUnitMapping(numUnitIndex) || strRstYuan;

Else

If (i = 1 Or i = 5) Then

If substr(strYuan, j - 3, 4) <> '0000' Then

strRstYuan := tabUnitMapping(numUnitIndex) || strRstYuan;

End If;

Else

If substr(strYuan, j + 1, 1) <> '0' Then

strRstYuan := tabNumMapping(charCurrentNum) || strRstYuan;

End If;

End If;

End If;

End Loop;

For i In -2 .. -1 Loop

j := numLenYuan - i;

charCurrentNum := substr(strYuanFen, j, 1);

If charCurrentNum <> '0' Then

strRstFen := tabNumMapping(charCurrentNum) || tabUnitMapping(i) ||

strRstFen;

End If;

End Loop;

If strRstYuan Is Not Null Then

strRstYuan := strRstYuan || '圆';

End If;

If strRstFen Is Null Then

strRstYuan := strRstYuan || '整';

Elsif length(strRstFen) = 2 And substr(strRstFen, 2) = '角' Then

strRstFen := strRstFen || '整';

End If;

strRst := strRstYuan || strRstFen;

--strRst := Replace(strRst, '亿零', '亿');

--strRst := Replace(strRst, '万零', '万');

Return strRst;

End Money2Chinese;

-- 调用--

Select Money2Chinese(786.213) From dual;



.触发器[了解]



数据库触发器是一个与表相关联的、存储的 PL/SQL 程序。每当一个特定的数据操作语句

(Insert,update,delete)在指定的表上发出时,Oracle 自动地执行触发器中定义的语句序列。


触发器可用于

数据确认

实施复杂的安全性检查

做审计,跟踪表上所做的数据操作等

数据的备份和同步


触发器的类型

语句级触发器 :在指定的操作语句操作之前或之后执行一次,不管这条语句影响了多少行 。

行级触发器(FOR EACH ROW) :触发语句作用的每一条记录都被触发。在行级触发器中使用 old 和 new 伪记录变量, 识别值的状态。

语法:

CREATE    [or REPLACE] TRIGGER    触发器名

{BEFORE | AFTER}

{DELETE | INSERT | UPDATE [OF 列名]}

ON 表 名

[FOR EACH ROW [WHEN(条件) ] ]

begin

PLSQL

End 触发器名

范例:插入员工后打印一句话“一个新员工插入成功”

create or replace trigger testTrigger after insert on person

declare

-- local variables here

begin

dbms_output.put_line('一个员工被插入'); end testTrigger;


范例:不能在休息时间插入员工

create or replace trigger validInsertPerson before insert on person


declare

weekend varchar2(10); begin

select to_char(sysdate, 'day') into weekend from dual; if weekend in ('星期一') then

raise_application_error(-20001, '不能在非法时间插入员工');

end if;

end validInsertPerson;

当执行插入时会报错



在触发器中触发语句与伪记录变量的值


触发语句

:old

:new

Insert

所有字段都是空(null)

将要插入的数据

Update

更新以前该行的值

更新后的值

delete

删除以前该行的值

所有字段都是空(null)


create or replace trigger addsal4p before update of sal on myemp for each row

begin

if :old.sal >= :new.sal then

raise_application_error(-20002, '涨前的工资不能大于涨后的工资'); end if;

end;



调用

update myemp t set t.sal = t.sal - 1;



七.Java 程序调用存储过程[应用]



6.%2.%3 1.java 连接 oracle jar


可以在虚拟机中 xp 的 oracle 安装目录下找到 jar 包 :ojdbc14.jar



7.%2.%3 2.数据库连接字符串



测试代码:





8.%2.%3 3.实现过程的调用


1.1.8.1 1.调用过程


1.1.8.1.11.过程定义




1.1.8.1.22.过程调用


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。