Oracle数据库PL/SQL块-存储函数和过程

PL/SQL块

PL/SQL程序由三个块组成,即声明部分、执行部分、异常处理部分

结构如下:

declare

​	/*声明部分,在此声明变量,类型及游标*/

begin

​	/*执行部分,过程及sql语句,程序主要部分*/

exception

​	/*执行异常部分,错误处理*/

end;

变量赋值

variable :=expression

字符连接

<字符串>||<字符串>

注意:空值加数字仍是空值

可转换类型赋值

char转number

v_total :=to_number('100.0')+sal;

number转char

v_comm :=to_char('123.45')||'元';

字符转日期

v_date :=to_date('2001.07.03','yyyy.mm.dd');

日期转字符

v_to_day :=to_char(sysdate,'yyyy.mm.dd hh24:mi:ss');

使用%type 定义表字段相同类型的变量

变量名 表名.字段名%type;
v_va11 emp.column1%type

使用%rowtype定义表行相同类型的变量

变量名 表名%rowtype;
v_row emp%rowtype;

ORACLE定义符合型的类型

delcare
--声明一个记录类型
type  emp_record is record(
v_val1 emp.column1%type;
v_val3 emp.column2%type;
v_val3 emp.column3%type;
);
--定义一个记录类型的成员变量、
v_emp_record emp_record;
begin
  select column1,column2,columb3 into v_emp_record from emp where emp_id = 100;
end;

流程控制

条件判断

方式一

if...then...elsif...than...else...end if;
-----------------1
if<布尔>then
	--logic
end if;
-----------------2
if<布尔>then
	--logic
else
	--logic
end if;
-----------------3

方式二

case... when... then... end;

循环结构

方式一

loop...exit...when...end loop;

方式二

while...loop...end...loop;

方式三

for i in ...loop...end loop;

显示游标处理

定义游标

打开游标

提取游标数据

关闭游标

declare
--1.定义游标
	cursor my_cursor is select * from test;
	v_row test%rowtype;
begin
--2.打开游标
			open my_cursor;
--3.提取游标
			fetch my_cursor into v_row;
--4.对游标进行循环操作,判断是否有下一条记录
			while my_cursor%found loop
				dbms_output.put_line('name:'||v_row.name);
				fetch my_cursor into v_row;
			end loop;
--关闭游标
			close my_cursor;
end;

游标属性

%FOUND 布尔型属性 当前最近一次读记录成功返回,则为true

%NOTFOUND 布尔型属性 相反

%ISOPEN 布尔型属性 当游标已打开时返回true

%ROWCOUNT 数字型属性 返回已从游标中读取的记录数

隐式游标处理

游标for循环,自动执行游标循环功能,自动打开游标,并提取第一行游标数据...

DECLARE
        CURSOR c_dl IS   SELECT * FROM test;
        c_row c_dl%ROWTYPE;
    BEGIN
        FOR c_row IN c_dl LOOP
						dbms_output.put_line ( 'SQL=' || c_row.name );
        END LOOP;
    END;

带参数游标

DECLARE
        CURSOR c_dl( x_id number) IS   SELECT * FROM test where id= x_id;
        c_row c_dl%ROWTYPE;
    BEGIN
        FOR c_row IN c_dl( x_id =>4000 ) LOOP
						dbms_output.put_line ( 'SQL=' || c_row.name );
        END LOOP;
    END;

异常处理

异常情况处理使用于处理正常执行过程中未预料的事件,程序块的异常处理

exception
	when first_exception then <code to handle>
		when second_exception then <code to handle>
			when third_exception then <code to handle>
end;
--异常处理注意次序排列,但others 必须放在最后
DECLARE
        CURSOR c_dl IS   SELECT * FROM norm;
        c_row c_dl%ROWTYPE;
    BEGIN
        FOR c_row IN c_dl LOOP
            BEGIN

						dbms_output.put_line ( 'SQL=' || c_row.name );

                --当出现异常时,将异常插入日志表,并继续下一次循环
            EXCEPTION
                WHEN OTHERS THEN
                    BEGIN
										dbms_output.put_line ( 'eerrrrr');
                    END;
            END;
        END LOOP;
    END;

三种类型异常错误

1.预定义错误 -大约有24个,无需在程序定义,由oracle自动

2.非预定义错误

DECLARE
--1.定义异常
	temp_exception exception;
--2.将定义好的异常情况,与标准oracle错误联系起来
	PRAGMA EXCEPTION_INIT(temp_exception,-2292);
 BEGIN
		delete from test where id=2;
exception
--3.处理异常
	when temp_exception then dbms_output.put_line ( '违反完整性约束' );
END;

3.用户定义错误

DECLARE
	e_too_high_excep exception;
	v_val test.ID%type;
 BEGIN
		select id into v_val from test where id=2;
		if v_val>1 then
		raise e_too_high_excep;
		end if;
exception
	when e_too_high_excep then dbms_output.put_line ( 'to high' );
END;

存储函数和过程

过程和函数的唯一区别是函数总向调用者返回数据,而过程则不返回数据

--创建存储过程调用
--输入参数 IN OR OUT
CREATE OR REPLACE PROCEDURE BAK_TEST(table_name in varchar)
return number

AS

BEGIN

END;

--需要单独选中执行存储过程调用(下面只是调用存储过程语法)
--参数为 需要备份的表名
BEGIN
    BAK_TEST('norm');
END;

利用存储函数备份表案例

--创建存储过程调用
CREATE OR REPLACE PROCEDURE BAK_TEST(table_name in varchar)
AS
        s_table_name VARCHAR(100);
        s_date VARCHAR(20);
				str_sql VARCHAR2(500);
BEGIN

				for cryptic_rec in (
					SELECT * FROM norm
				)
				loop
						BEGIN
							select to_char(sysdate,'yyyymmdd') INTO s_date from dual;
							s_table_name := cryptic_rec.name ||  '_' ||s_date;
							
							dbms_output.put_line ( '-- s_table_name=' || s_table_name );
							
							str_sql :='CREATE TABLE '|| s_table_name || ' AS SELECT * FROM '|| cryptic_rec.name;
							EXECUTE IMMEDIATE str_sql;
							
							dbms_output.put_line ( '--SQL=' || str_sql );
									--当出现异常时,将异常插入日志表,并继续下一次循环
							EXCEPTION
									WHEN OTHERS THEN
											BEGIN
											dbms_output.put_line ( 'error-SQL=' || str_sql );
											END;
            END;

				end loop;
END;

--需要单独选中执行存储过程调用(下面只是调用存储过程语法)
--参数为 需要备份的表名
BEGIN
    BAK_TEST('norm');
END;

触发器

create [or replace] trigger trigger_name
{before|after}
{insert|delete|update [of column]}
on [schema.]table_name
[for each row]
[when condition]
trigger_body;
--分为行触发和语句触发

案例

create or replace trigger hell_trigger
after
update on employees
--for each row
begin 
  dbms_output.put_line('hello');
end;
-- old,new
create or replace trigger del_trigger
after
delete on employees
for each row
begin 
	insert into my_emp_bak
	values(:old.emp_id,:old.salary);
end;

Oracle常用函数

大写小写函数

Oracle 大小写转换函数

转大写UPPER

转小写LOWER

测试:

select UPPER('Test') as u from dual;--TEST
select LOWER('Test') as l from dual;--test

注意:

1.sys用数据库的超级用户,数据库内很多重要的东西(数据字典表、内置包、静态数据字典视图等)都属于这个用户,sys用户必须以sysdba身份登录。

2.提示 ORA-01031: 权限不足

执行DDL报错
在oracle存储过程中,默认是可以直接执行DML和DQL的,但是执行CREATE这种的DDL则需要借助EXECUTE IMMEDIATE ···了,如下备份表语句

  --抄表表备份
  SELECT TO_CHAR(SYSDATE,'YYMMDD') INTO V_DQRQ FROM DUAL;
  V_CREATESQL := 'CREATE TABLE SF_EBZCB'||V_DQRQ||'_T AS SELECT * FROM SF_EBZCB_T'; 
  EXECUTE IMMEDIATE V_CREATESQL;
当执行该语句时,提示 ORA-01031: 权限不足。该用户已赋予DBA权限。

原因:CREATE TABLE想使用CREATE ANY TABLE权限,而CREATE ANY TABLE权限来自DBA角色,默认情况下,虽然在会话环境中可见,但在存储过程中不可见(无效)。

即:ORACLE默认为定义者权限,定义者权限在存储过程中ROLE无效,需要显式授权。

GRANT CREATE ANY TABLE TO charge_liny;
执行上面sql显式授权后,在该用户下通过 EXECUTE IMMEDIATE 执行CREATE语句即可成功创建表。
授权其他DML权限

GRANT INSERT ANY TABLE TO CHARGE_LINY;
GRANT UPDATE ANY TABLE TO CHARGE_LINY;
GRANT DELETE ANY TABLE TO CHARGE_LINY;

版权声明:本文为weixin_42477252原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>