PL/SQL编程

pl/sql(procedural language/sql)是Oracle在标准的sql语言上的扩展。pl/sql不仅允许嵌入式sql语言,还可以定义变量和常量,允许使用条件语句和循环语句,允许使用例外处理各种错误。这样使得他的功能变的更强大。缺点是移植性不好。

编写一个存储过程,向表中添加数据。

  1. create table mytest (name varchar2(30),passwd varchar2(30));
  2. create or replace procedure xxc_pro1 is

begin

insert into mytest values ('小红','m123');

end;

  1. 调用过程  exec  过程名(参数1,参数2…)或call 过程名参数1,参数2…)

①    exec xxc_pro1;   或者是

②    call xxc_pro1;

pl/sql可以做什么?

块:包括过程、函数、触发器、包。

编写规范:

  1. 注释  --:单行注释

eg:select * from emp where empno=7788;--取得员工信息

/*……*/多行注释

  1. 表示符号(变量)的命名规范:

①    当定义变量时,建议用v_作为前缀:v_ename

②    当定义常量时,建议用c_作为前缀:c_rate

③    当定义游标时,建议用_cursor作为后缀:emp_cursor

④    当定义例外时,建议用e_作为前缀:e_error

块(block)是pl/sql的今本程序单元,编写pl/sql程序实际上就是在编写pl/sql块;pl/sql块由三部分组成:定义部分,执行部分,例外处理部分。

declare  --可选部分

/*定义部分:定义常量,变量,游标,例外,复杂数据类型*/

begin   --必选部分

/*执行部分:要执行的pl/sql语句和sql语句*/

exception  --可选部分

/*例外处理部分:处理运行的各种错误*/

实例1:只包含执行部分的pl/sql块

SQL> set serveroutput on  --打开输出

SQL> begin

2  dbms_output.put_line('hello');

3  end;

4  /

说明:dbms_output是oracle提供的包,该包包含一些过程,put_line就是其中之一。

实例2:包含定义部分和执行部分

SQL> declare

2  v_ename varchar2(5);

3  begin

4  select ename into v_ename from emp where empno = &no;

5  dbms_output.put_line('雇员名'||v_ename);

6  end;

7  /

说明:&:从控制台输入变量,会弹出一个对话框。

实例3.同时输出雇员名和工资

SQL> declare

2  v_ename varchar2(20);

3  v_sal number(10,2);

4  begin

5  select ename,sal into v_ename,v_sal from emp where empno=&no;

6  dbms_output.put_line('雇员名:'||v_ename||' 工资:'||v_sal);

7  end;

8  /

包含定义,执行,和例外处理的pl/sql块。

实例4.当输入的员工号不存在时

SQL> declare

2  v_ename varchar2(20);

3  v_sal number(10,2);

4  begin

5  select ename,sal into v_ename,v_sal from emp where empno =&no;

6  dbms_output.put_line('雇员名:'||v_ename||' 工资:'||v_sal);

7  exception   --异常处理部分

8  when no_data_found then

9  dbms_output.put_line('请输入正确的员工号!');

10  end;

11  /

以上为块的基础,下面来介绍块的各个组成:过程,函数,触发器,包。

过程

过程用于执行特定的操作,当执行过程的时候,可以指定输入参数(in),也可以指定输出参数(out)。通过在过程中使用输入参数,可以讲数据输入到执行部分,通过使用输出参数,可以将执行部分的数据输出到应用环境,在pl/sql中可以使用create procedure命令来创建过程。

编写一个存储过程,可以输入雇员名和新工资来改变员工工资。

--案例

create or replace procedure xxc_pro3(newname in varchar2,newsal in number) is

begin

update emp set sal=newsal where ename=newname;

end;

调用   exec xxc_pro3(‘SCOTT’,2900);[A1]

--in表示是输入参数,可以不写,默认是in,但out必须写。

在java程序中调用存储过程来修改工资;

//演示java程序调用oracle中的存储过程

package TestOraPro;//根据不同的包,包名不同

import java.sql.*;

public class TestOraPro {

/**

* @param args

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

try{

//加载驱动

Class.forName("oracle.jdbc.driver.OracleDriver");

//得到连接   1521为端口号

Connection ct = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:CUIXIAO2","scott","xxc");

//创建callablestatement

CallableStatement cs=ct.prepareCall("{call xxc_pro3(?,?)}");

//给?赋值

cs.setString(1, "SMITH");

cs.setInt(2,2600);

//执行

cs.execute();

}catch(Exception e){

e.printStackTrace();

} finally{

//关闭资源

cs.close();

ct.close();

}

}

}

以上为过程基础,后会详细讲。

函数

函数用于返回特定的数据,当建立函数时,在函数头部必须包含return子句,而在函数体内必须包含return语句来返回数据,可以使用create function来建立函数。

案例1.返回工人年工资。

--函数案例

create or replace function xxc_fun1(newname varchar2)

return number is yearSal number(10,2);

begin

select sal*12+nvl(comm,0)*12 into yearSal from emp where ename=newname;

return yearSal;

end;

在sqlplus中调用函数

sql>var income number;

sql>call xxc_fun1(‘SCOTT’) into: income;

sql>print income;

在java中调用函数

select xxc_fun1(‘SCOTT’) from dual;

这样可以通过rs.setInt(1)得到返回结果。

包用于在逻辑上组合过程和函数,它由包规范和包体两部分组成。

1.我们可以用create(or replace) package命令来建包;

实例:create package xxc_package is

Procedure update_sal (name varchar2,newsal number);

Function annual_sal(name varchar2) return number;

End;

包规只包含过程和函数的说明,但是没有函数和过程的实现代码。[A2]

包体用于实现包规范中的过程和函数。

2.建立包体可以用create package body命令。

create package body xxc_package is

Procedure update_sal(name varchar2,newsal number) is

begin

update emp set sal=newsal where ename=name;

end;

function annual_sal(name varchar2) return number is

annual_salary number;

begin

select sal*12+nvl(comm,0)*12 into annual_salary from emp    where ename=name;

return;

end;

end;

[A3] 3.如何调用包中的过程和函数。

在过程和函数前加上包名。

exec xxc_package.update_sal(‘SCOTT’,120);

触发器

触发器是指隐含的存储过程,当定义触发器是,必须指定触发事件和触发的操作,常用的触发操作有insert、update和delete。触发器操作实际上是一个pl/sql块,可以使用create trigger命令来创建触发器。因为触发器内容很多,会在后面详细介绍,触发器是非常有用的,可以用来维护数据库的安全和一致性。

在编写pl/sql块时可以定义的变量和常量;

  1. 标量类型(scalar);
  2. 复合类型(composite);
  3. 参照类型(reference);
  4. lob(large ofject);

标量类型(scalar)—常用类型

语法格式(即前边最常见的格式)

变量名 [constant] datatype [not null] [:=/default expr]

expr:指定初始值的pl/sql表达式,可以是文本,其他变量,函数等。

定义标量案例

①    定义一个变长字符串

V_ename varchar2(10);

②    定义一个小数,范围在-9999.99~9999.99

v_sal number(6,2);

③    定义一个小数并赋初值  :=是pl/sql的赋值符号;

v_sal number(6,2):=12.3;

④    定义一个日期类型数

v_birthday date;

⑤    定义一个布尔类型变量,不能为空,默认是false;

v_valid boolen not null default false;

[A4] 下面以输入员工号,显示员工姓名,工资,个人所得税(税率为0.03)为例,说明变量的使用。

declare

c_tax_rate number(3,2):=0.03;

v_ename varchar2(5);

v_sal number(10,2);

v_tax_sal number(10,2);

begin

select ename,sal into v_ename,v_sal from emp where empno=&no;

v_tax_sal:=v_sal*c_tax_rate;

dbms_output.put_line(‘员工名:’||v_ename||’工资:’||v_sal||’缴税:’||v_tax_sal);

end;

对于上边的pl/sql块,有一个问题。

如果员工的名字长于5个字符,就会出现错误,为了降低pl/sql的维护工作量,可以使用%type属性来定义变量,这样它会按照数据库列来确定你定义的变量的类型和长度。

变量名  表名.列名%type

对于上例的改动

v_ename emp.ename%type;

v_sal emp.sal%type;

复合类型(composite)-介绍

用于存放多个值的变量,主要包括这几种:

① pl/sql记录;

② pl/sql表;

③ 嵌套表;

④ varray;

其中① ② 用的多,③ ④ 用的少。

1.pl/sql的记录。

类似于高级语言的结构体,当引用pl/sql记录成员的时候,必须要加记录变量作为前缀(记录变量.记录成员)。

如:declare

type emp_record_type is record(name emp.ename%type, salary emp.sal%type,title emp.job%type);[A5]

xxc_record emp_record_type;

begin

select ename,sal,job into xxc_record from emp where empno=&no;

dbms_output.put_line(‘员工名:’||xxc_record.name||’工资:’||xxc_record.salary);

end;

2.pl/sql

相当于高级语言中的数组,需要注意的是高级语言中的数组的下标不能为负,但表的下标没有限制,可以为负。[A6]

例如:declare           -- binary_integer表示下标是整数

type xxc_table_type is table of emp.ename%type index by binary_integer;

xxc_table xxc_table_type;

begin        --下标0可以是任何整数,-1,-2,23都可以,但输出的时候也要是同一个数,不然会出错。

select ename into xxc_table(0) from emp where empno=7788;

dbms_output.put_line(‘员工名:’||xxc_table(0));

end;

在这个实例中,如果把where子句去掉,就会出错,因为你只请求了一个数据,而返回了多行数据。解决办法是使用参照变量。

参照变量

参照变量是指用于存放数据指针的变量,通过使用参照变量可以使得应用程序共享相同的对象,从而降低占用的空间。在编写pl/sql程序时,可以使用游标变量(ref cursor)和对象类型变量(ref obj_type)这两种参照变量,用得多的是游标变量。

游标变量

定义游标是,不需要指定select语句,但当使用游标(open)时,需要指定select语句,这样一个游标就与一个游标就与一个select语句结合了。

实例:① 编写一个pl/sql块,输入部门号,显示所有员工名和工资。

declare

type xxc_emp_cursor is ref cursor;

test_cursor xxc_emp_cursor;

v_ename emp.ename%type;

v_sal emp.sal%type;

begin

open test_cursor for select ename,sal from emp where deptno=&no;

loop

fetch test_cursor into v_ename,v_sal;

exit when test_cursor%notfound;

dbms_output.put_line(‘名字:’||v_ename||’工资:’||v_sal);

end loop;

close test_cursor;

[A7] end;

②  在① 的基础上,如果员工的工资低于2000,加100

declare

type xxc_emp_cursor is ref cursor;

test_cursor xxc_emp_cursor;

v_ename emp.ename%type;

v_sal emp.sal%type;

begin

open test_cursor for select ename,sal from emp where deptno=&no;

loop

fetch test_cursor into v_ename,v_sal;

exit when test_cursor%notfound;

if v_sal<2000 then

update emp set sal=sal+100 where ename=v_ename;

v_sal=v_sal+100;

end if;

dbms_output.put_line(‘名字:’||v_ename||’工资:’||v_sal);

end loop;

close test_cursor;

end;

[A8] Pl/sql分支控制语句

1.条件分支语句

if…then   if…then…else   if…then…eslif…then…else…

当if语句结束时要有end if。

不等于号是<>,不是!=,

if job=’MANAGER’,是单引号,不是双引号。

2.循环语句 

--loop是pl/sql中最简单的循环语句,这种循环以loop开始,以end loop结束,此循环至少会被执行一次。

例:编写一个循环过程,可输入用户名,并循环添加10个用户到user表中,用户编号从1开始。

Sql>create table user(userid number(10),username varchar2(20));

Sql>create procedure xxc_insert_user1(name varchar2) is

declare

v_Num number:=1;  --不用指定大小吗?

begin

loop

insert into user values(v_num,name);

exit when v_num=10;[A9]

v_num:=v_num+1;  --Oracle中没有++符号

end loop;

end;

--while循环

当while条件为真时,执行循环体。

以while…loop开头,以end loop结尾。

例:上题,用户号从11开始,添加10名用户。

create procedure xxc_insert_user2(name varchar2) is

declare

v_Num number:=11;  --不用指定大小吗?

begin

while v_num<=20 loop

insert into user values(v_num,name);

v_num:=v_num+1;

end loop;

end;

--for循环

循环基本结构如下:

begin

for i in reverse 1..10 loop

insert into users(I,’小红’);

end loop;

end;

顺序控制语句   --goto,null

Goto语句会增加程序的复杂性,降低可读性,一般不使用,但有时会很方便。

基本语法     goto lable ,lable是定义好了的标签。

例:declare

i int:=1;

begin

loop

dbms_output.put_line(‘i=’||i);

if i=10 then

goto end_loop;

end if;

end loop;

<<end_loop>>    --此为标签,注意格式

dbms_output.put_line(‘循环结束’);

end;

null语句不执行任何操作,好处是可以提高程序的可读性。

例:if sal<2000 then

update emp set sal=sal+100 where ename=name;

else

null;

编写分页过程

从易到难,先写简单的过程。

写无返回值的过程,并被Java程序调用,前边已写过,不再重写。现在写一个有返回值的过程,并用Java程序调用。

例:输入员工号,输出员工姓名。

Create procedure xxc_pro4 (empid in number,empname out varchar2) is

Begin

Select ename into empname from emp where empno = empid;

End;

Java程序调用。

import java.sql.*;

public class TestOraPro1 {

/**

* @param args

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

try{

//加载驱动

Class.forName("oracle.jdbc.driver.OracleDriver");

//得到连接   1521为端口号

Connection ct = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:CUIXIAO2","scott","xxc");

//创建callablestatement

CallableStatement cs=ct.prepareCall("{call xxc_pro4(?,?)}");

//给第一个?赋值

cs.setInt(1,7788);

//给第二个?赋值

cs.registerOutParameter(2,oracle.jdbc.OracleTypes.VARCHAR);

//执行

cs.execute();

//取出返回值,要注意?的顺序,第几个?是返回值就写几。

String name = cs.getString(2);

System.out.println(“7788的名字是”+name);

}catch(Exception e){

e.printStackTrace();

}finally{

//关闭资源

cs.close();

ct.close();

}

}

}

案例扩展:输入一个员工号,输出该员工的名字,工资和岗位。

create procedure xxc_pro5(empid in number,empname out varchar2,empsal out number,empjob out varchar2) is

begin

select ename,sal,job into empname,empsal,empjob from emp where empno=empid;

end;

Java调用

import java.sql.*;

public class TestOraPro1 {

/**

* @param args

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

try{

//加载驱动

Class.forName("oracle.jdbc.driver.OracleDriver");

//得到连接   1521为端口号

Connection ct = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:CUIXIAO2","scott","xxc");

//创建callablestatement

CallableStatement cs=ct.prepareCall("{call xxc_pro4(?,?,?,?)}");

//给第一个?赋值

cs.setInt(1,7788);

//给后3个?赋值

cs.registerOutParameter(2,oracle.jdbc.OracleTypes.VARCHAR);

cs.registerOutParameter(3,oracle.jdbc.OracleTypes.DOUBLE);

cs.registerOutParameter(4,oracle.jdbc.OracleTypes.VARCHAR);

//执行

cs.execute();

//取出返回值,要注意?的顺序,第几个?是返回值就写几。

String name = cs.getString(2);

String job = cs.getString(4);

System.out.println(“7788的名字是”+name+” 工作是”+job);

}catch(Exception e){

e.printStackTrace();

}finally{

//关闭资源

cs.close();

ct.close();

}

}

}

带有返回值的存储过程(结果集是个列表)。

案例:编写个存储过程,输入部门号,输出该部门的所有员工的信息。

分析如下:

由于Oracle的存储过程没有返回值,它的所有返回值都是通过out参数来替代的,列表同样也不例外,但由于是个集合,所以不能用一般参数,必须要用package。所以分为两部分。

① 创建一个包,在包中定义一个test_package,是个游标;

create package test_package as type test_cursor is ref cursor;

End test_package;

②    创建存储过程

create procedure xxc_pro6(xxcno in number,xxc_cursor out test_package.test_cursor) is

begin

open xxc_cursor for select * from emp where deptno=xxcno;

end;

在Java中调用此存储过程

import java.sql.*;

public class TestOraPro1 {

/**

* @param args

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

try{

//加载驱动

Class.forName("oracle.jdbc.driver.OracleDriver");

//得到连接   1521为oracle端口号

Connection ct = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:CUIXIAO2","scott","xxc");

//创建callablestatement

CallableStatement cs=ct.prepareCall("{call xxc_pro6(?,?)}");

//给第一个?赋值

cs.setInt(1,10);

//给第二个?赋值

cs.registerOutParameter(2,oracle.jdbc.OracleTypes.CURSOR);

//执行

cs.execute();

//得到结果集

ResultSet rs = (ResustSet)cs.getObject(2);

While(rs.next()){

System.out.println(rs.getInt(1)+” ”+rs.getString(2)+” ”+rs.getString(3));

}

}catch(Exception e){

e.printStackTrace();

}finally{

//关闭资源

cs.close();

ct.close();

}

}

}

开始编写分页过程。

例:请编写一个存储过程,要求可以输入表名、每页显示记录数、当前页,返回总记录数、总页数和返回的结果集。

现在先回顾一下分页的语句,这是个模板。

select * from (select t1.*,rownum rn from (select * from emp)  t1 where rownum<=10) where rn>=6;

① 创建一个包,在包中定义一个test_package2,是个游标;

create package test_package2 as type test_cursor2 is ref cursor;

End test_package2;

② 创建存储过程;

create procedure fenye is

(tablename in varchar2,  --表名

rowsize in number,  --每页记录数

pagenow in number,  --当前页

recordnum out number,  --总记录数

pagenum out number,    --总页数

set_cursor out test_package2.test_cursor2  --结果集的游标

) is

v_sql varchar2(1000);

v_begin nuber:=(pagenow-1)*rowsize+1;

v_end nuber:=pagenow*rowsize;

begin

--v_sql是连接字符串,有点绕,看仔细

v_sql := 'SELECT * FROM (SELECT T.*,ROWNUM rn FROM (SELECT * FROM ' ||

TABLENAME || ' ) T WHERE ROWNUM <= ' || V_END ||

' ) WHERE rn >= ' || V_BEGIN;

--打开游标,把游标和sql语句结合起来

open set_cursor for v_sql;

--计算recordnum和pagenum

v_sql:= 'SELECT COUNT(*) FROM ' || TABLENAME;

execute immediate v_sql into recordnum;

if mod(recordnum,rowsize)=0 then

pagenum:=recordnum/rowsize;

else

pagenum:=recordnum/rowsize+1;

end if;

close set_cursor;

end;

用Java程序调用:

import java.sql.*;

public class TestOraPro1 {

/**

* @param args

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

try{

//加载驱动

Class.forName("oracle.jdbc.driver.OracleDriver");

//得到连接   1521为端口号

Connection ct = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:CUIXIAO2","scott","xxc");

//创建callablestatement

CallableStatement cs=ct.prepareCall("{call fenye(?,?,?,?,?,?)}");

//给?赋值

cs.setString(1,”emp”);

cs.setInt(2,5);

cs.setInt(3,1);

//注册总记录数

cs.registerOutParameter(4,oracle.jdbc.OracleTypes.INTEGER);

//注册总页数

cs.registerOutParameter(5,oracle.jdbc.OracleTypes.INTEGER);

//注册结果集

cs.registerOutParameter(6,oracle.jdbc.OracleTypes.CURSOR);

//执行

cs.execute();

//取出返回值,要注意?的顺序,第几个?是返回值就写几。

int rnum=cs.getInt(4);

int pnum=cs.getInt(5);

ResultSet rs=(ResultSet)cs.getObject(6);

System.out.println(”记录数是:”+rnum+” 总页数是:”+pnum);

while(rs.next()){

System.out.println(”编号:”+rs.getInt(1)+”姓名:”+rs.getString(2));

}

}catch(Exception e){

e.printStackTrace();

}finally{

//关闭资源

cs.close();

ct.close();

}

}

}

例外处理

例外处理分为预定义例外,其他预定义例外和自定义例外。

案例:当输入的雇员编号不存在时

declare

v_ename emp.ename%type;

begin

select ename into v_name from emp where empno=&no;

dbms_output.putline(’名字是:’||v_name);

exception

when no_data_found then

dbms_output.putline(’编号不存在!’);

end;

no_data_found就是一个预定义例外,在执行select语句时会出异常,但在执行update等语句时不会触发该例外。

预定义例外是由pl/sql所提供的系统例外。当pl/sql违反Oracle的规定时就会隐含触发一个内部例外。

常用的例外:

  1. case_no_found 当编写pl/sql块中编写case语句时,如果在when子句中没有包含必须的条件分支,就会触发case_no_found例外。

例:create or replace procedure xxc_pro7(no number) is

v_sal emp.sal%type;

begin

select sal into v_sal from emp where empno=no;

case

when v_sal<1000 then

update emp set sal=sal+200 where empno=no;

when 1000<=v_sal<2000 then

update emp set sal=sal+300 where empno=no;

end case;

exception

when case_no_found then

dbms_output.putline(’case中没有和’||v_sal||’相匹配的条件’);

end;

  1. 2.       cursor_already_open例外:

declare

cursor emp_cursor is select ename,sal from emp;

begin

open emp_cursor;

for emp_record1 in emp_cursor loop

dbms_output.putline(emp_cursor.ename);

end loop;

exception

when cursor_already_open then

dbms_output.putline(’游标已打开!’);

end;

3.dup_val_on_index例外

在唯一索引所对应的列上插入重复的值时,会隐含的触发此例外。

begin

insert into dept values(10,’公关部’,’北京’);

exception

when dup_val_on_index then

dbms_output.putline(’在deptno列上不能有重复值!’);

end;

4.invaild_cursor

当试图在不合法的游标上执行操作时,就会触发该例外。例如当试图从没有打开的游标提取数据或是关闭没有打开的游标时,就会触发。

declare

cursor emp_cursor is select ename,sal from emp;

emp_record emp_cursor%rowtype;

begin

--open emp_cursor; --打开游标(但被注释掉了)

fetch emp_cursor into emp_record;

dbms_output.putline(emp_cursor.ename);

close emp_cursor;

exception

when invalid_cursor then

dbms_output.putline(’请检查游标是否打开’);

end;

5.invalid_number例外

当输入的数据有误时,会触发该例外。比如把100写成1oo就会触发。

begin

update emp set sal=sal+’1oo’;

exception

when invalid_number then

dbms_output.putline(’输入的数字不正确!’);

end;

6.too_many_rows例外

当执行select into语句时,如果返回超过了一行,则会触发该例外。

declare

v_ename emp.ename%type;

begin

select ename into v_ename from emp;

exception

when too_many_rows then

dbms_output.putline(’返回了多行!’);

end;

7.zero_divide例外    2/0,即0做分母的时候触发。

8.value_error例外

当在执行赋值操作时,如果变量的长度不足以容纳实际数据,就会触发该例外。

declare

v_ename varchar2(5);

begin

select ename into v_ename from emp where empno=&no;

dbms_output.putline(’名字是:’||v_ename);

exception

when value_error then

dbms_output.putline(’数据超出变量长度!’);

end;

其他预定义例外。

  1. login_denide  当用户非法登录时,会触发该例外。
  2. not_logged_on  如果用户没有登录就执行dml操作,就会触发。
  3. storage_error  如果超过了内存空间或内存被破坏,就会触发。
  4. timeout_on_resoure  如果oracle在等待资源是出现了超时,触发。

自定义例外

预定义例外是和oracle的错误相关的,而自定义例外于oracle错误没有任何关系,它是由开发人员为特定的情况所定义的例外。

例:编写一个pl/sql块,接收一个雇员号,并给该雇员的工资增加1000元,如果该雇员不存在,请提示。

create or replace procedure test_ex(no number) is

declare

myex exception; --定义一个例外

begin

update emp set sal=sal+1000 where empno=no;

if sql%notfound then  -- sql%notfound表示没有更新数据

raise myex;   --触发myex

end if;

exception

when myex then

dbms_output.putline(’未更新成功!’);

end;

视图

视图与表的区别

  1. 表需要占用磁盘空间,视图不需要;
  2. 视图不能添加索引;
  3. 使用视图可以简化复杂查询;
  4. 视图可以提高安全性

创建视图

create view 视图名 as select语句 [with read only];

例:创建视图,把emp表的sal<1000的雇员映射到该视图;

create view myview as select * from emp where sal<1000;

为简化操作,用视图显示员工编号,姓名和所在部门

create view myview2 as select emp.empno,emp.ename,dept.dname from emp,dept where emp.deptno=dept.deptno;

创建或修改视图

create or replace view 视图名 as select语句 [with read only];

删除视图

drop view 视图名;


[A1]

调用过程,必须这么写

begin

xxc_pro3('SCOTT',2900);

end;

[A2]

类似Java的Interface接口

[A3]报错

[A4]如何定义变量

[A5]相当于Java的POJO

实体类

[A6]相当于Java的数组

[A7]游标就是C的指针

这里面用的循环,相当于while循环

[A8]展示了循环集合,然后修改集合对象的属性

[A9]Java中的break

OraclePLSQL编程的更多相关文章

  1. 2018.5.27 OraclePLSQL编程 if-else练习和循环结构练习

    if-else运用 declare v_num number(8); begin v_num :=&n; if v_num>0 and v_num<100 then dbms_ou ...

  2. SQL编程篇 (二) 定义与流程控制

    分类: sql编程:标准的sql 编程 * 纯sql 在标准的编程中又分为 sqlserver-->T-sql oracle-->pl-sql(扩展) 变量:在使用变量之前先定义 声明变量 ...

  3. 从直播编程到直播教育:LiveEdu.tv开启多元化的在线学习直播时代

    2015年9月,一个叫Livecoding.tv的网站在互联网上引起了编程界的注意.缘于Pingwest品玩的一位编辑在上网时无意中发现了这个网站,并写了一篇文章<一个比直播睡觉更奇怪的网站:直 ...

  4. JavaScript之父Brendan Eich,Clojure 创建者Rich Hickey,Python创建者Van Rossum等编程大牛对程序员的职业建议

    软件开发是现时很火的职业.据美国劳动局发布的一项统计数据显示,从2014年至2024年,美国就业市场对开发人员的需求量将增长17%,而这个增长率比起所有职业的平均需求量高出了7%.很多人年轻人会选择编 ...

  5. 读书笔记:JavaScript DOM 编程艺术(第二版)

    读完还是能学到很多的基础知识,这里记录下,方便回顾与及时查阅. 内容也有自己的一些补充. JavaScript DOM 编程艺术(第二版) 1.JavaScript简史 JavaScript由Nets ...

  6. [ 高并发]Java高并发编程系列第二篇--线程同步

    高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...

  7. C#异步编程(一)

    异步编程简介 前言 本人学习.Net两年有余,是第一次写博客,虽然写的很认真,当毕竟是第一次,肯定会有很多不足之处, 希望大家照顾照顾新人,有错误之处可以指出来,我会虚心接受的. 何谓异步 与同步相对 ...

  8. UE4新手之编程指南

    虚幻引擎4为程序员提供了两套工具集,可共同使用来加速开发的工作流程. 新的游戏类.Slate和Canvas用户接口元素以及编辑器功能可以使用C++语言来编写,并且在使用Visual Studio 或 ...

  9. C#与C++的发展历程第三 - C#5.0异步编程巅峰

    系列文章目录 1. C#与C++的发展历程第一 - 由C#3.0起 2. C#与C++的发展历程第二 - C#4.0再接再厉 3. C#与C++的发展历程第三 - C#5.0异步编程的巅峰 C#5.0 ...

随机推荐

  1. Java笔记(十九) 反射

    反射 反射是在运行时获取类型的信息,再根据这些信息进行操作. 一.Class类 每个已加载的类在内存中都有一份类信息,每个对象都有指向它的类信息的引用. 在Java中,类信息对应的类就是java.la ...

  2. 2546 ACM 01背包

    题目http://acm.hdu.edu.cn/showproblem.php?pid=2546 思路:再01背包的问题上稍作修改 如何满足 :卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购 ...

  3. [CSAcademy]Or Problem

    [CSAcademy]Or Problem 题目大意: 一个长度为\(n(n\le2\times10^5)\)的序列\(A(0\le A_i<2^{20})\),将其分为恰好\(m\)个连续段, ...

  4. SpringMVC的请求处理流程

  5. 考前停课集训 Day6 垒

    Day 6 今天在家里的 家里蹲 其实是day7的时候想到要写day6了 草率补充一下 NOIP考前棕名退不掉咯 你觉得我还会打洛谷的题目吗? 依然退步 没用心 T1 分火腿 数论题 我感觉挺难的 T ...

  6. 什么是OKR?

    什么是OKR OKR全称是Objectives and Key Results,即目标与关键成果法.OKR是一套定义和跟踪目标及其完成情况的管理工具和方法.1999年 Intel公司发明了这种方法,后 ...

  7. Helm: Error: no available release name found

    如题,helm报这个错误 Helm: Error: no available release name found 错误的原因大概是因为 tiller没有正确的角色权限. 执行以下命令可解决这个问题. ...

  8. oracle增删改字段

    添加字段的语法:alter table tablename add (column datatype [default value][null/not null],….); 修改字段的语法:alter ...

  9. django之ajax补充

    之前的ajax使用都是依据jquery来使用的,本篇会先分析ajax的原生的js代码实现,还有jsonp的介绍和最终使用. 本篇导航: js实现的ajax 同源策略与Jsonp 一.js实现的ajax ...

  10. sublime项目的添加删除

    方便多个项目之间切换修改代码