简介
- Mysql存储过程调试工具:
dbForge Studio for MySQL
Oracle
- PL/SQL 语句结束一定要加分号
;
,如果没加运行会提示下一行出错 - oracle转义字符为
'
,如''
转义后就是'
- sqlplus查看存储过程
select text from all_source where name = 'my_procedure';
- 通过select执行函数
select my_func(select id from user where username='test') mf from dual;
可以到函数返回值 - Oracle内置包/方法
控制语句
- if-else
1 | if ... end if; |
- goto
<<xxx>>
的标记符号,常用来跳出循环,使用goto可以跳到标记的位置
1 | for i in 1..100 loop |
Oracle存储过程示例
call p_up_user_role();
调用存储过程
1 | -- 定义 |
- 示例二(动态游标、异常处理)
1 | -- 创建错误日志表 |
异常
- 异常属性
SQLCODE
出错代码. 如:-1722
SQLERRM
出错信息. 如:ORA-01722: invalid number
DBMS_UTILITY.FORMAT_ERROR_BACKTRACE
报错行号等信息. 如:ORA-06512: at "CRMADM.P_UP_CUSTOMER_LOCK", line 39
- 抛出异常
raise_application_error
该函数是将应用程序专有的错误从服务器端转达到客户端应用程序(其他机器上的sqlplus或者前台开发语言)raise_application_error(error_number_in in number, error_msg_in in varchar2);
如 raise_application_error(-20500, ‘执行出错’);error_number_in
: 自定义的错误码,容许从 -20000 到 -20999 之间,这样就不会与 oracle 的任何错误代码发生冲突。报错对应ORA-20000
至ORA-20099
error_msg_in
: 长度不能超过 2k,否则截取 2k
捕获异常类型参考官方文档:https://docs.oracle.com/cd/B19306_01/appdev.102/b14261/errors.htm
no_data_found
无数据(select…into…语句需要捕获。select count(1) into v_count from ...
无需捕获,无数据则为0)too_many_rows
数据返回行数太多(select…into…语句可以捕获)value_error
值异常(转换异常、字段大小异常)others
所有未捕获的异常(也可捕获自定义异常)结合springboot捕获异常
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18(UncategorizedSQLException.class)
public Result handleUncategorizedSQLException(UncategorizedSQLException e){
Throwable cause = e.getCause();
String errKey = "ORA-20010";
if(cause.getMessage().contains(errKey)) {
String errMsg = Arrays.stream(cause.getMessage().split("\n"))
.filter(x -> x.contains(errKey)).findFirst()
.orElse("")
.replace(errKey + ": ", "");
if(ValidU.isEmpty(errMsg)) {
throw e;
}
logger.error(e.getMessage(), e);
return Result.failure(errMsg);
} else {
throw e;
}
}
防止select into无数据报错情况,可使用
select max(name) into str from ...
在
[for...in...]loop...end loop
循环中捕捉异常,必须用begin...end
包起来。捕获子异常也需要begin...end
包起来1
2
3
4
5
6
7
8
9loop
begin
-- ...
exception
when others then dbms_output.put_line('出错'); -- 捕获异常后继续下一次循环
-- when others then null; -- 捕获异常后继续下一次循环
continue; -- 继续下一个循环
end;
end loop;
Oracle过程语句
1 | set serverout on; --sqlplus执行时可开启服务器输出(通过@my.sql执行文件亦可). PL/SQL则不需要 |
forall与bulk collect语句提高效率
参考:http://blog.aezo.cn/2018/07/27/db/sql-optimize/
自治事务
- 使用
PRAGMA AUTONOMOUS_TRANSACTION
- 参考: https://www.cnblogs.com/it-note/archive/2013/06/14/3136134.html
自定义包
1 | create or replace package IntegrityPackage AS |
- 定义包内容
1 | -- 当使用存储过程/触发器进行嵌套时,可通过此层级判断是否为内嵌执行存储过程稿 |
- 查看自定义包内容
1 | -- 查看自定义包 IntegrityPackage 的内容 |
- 使用包内存储过程或函数
1 | CREATE OR REPLACE TRIGGER TUA_PORTCODE after update |
常用类型
1 | -- 用于 sq_split 函数function |
常用函数
sq_split字符串分割
1 | -- 创建类型 |
sql_pivot_dynamic_col动态行转列
- 前提
- 创建sq_type_big_table_row、sq_type_big_table类型(参考上文)
- 调用自定义函数sq_split(参考上文)
1 | /** |
- 使用
1 | -- 获取每个提单对应的费目和金额(将费目行转列) |
常用存储过程
定时清理数据库业务日志表
1 | -- 创建存储过程 |
Mysql
- 打印日志:
select 1
存储过程示例
示例(简单)
1 | /*delimiter指分割符,Mysql默认的分割符是分号';',如果没有声明分割符,那么编译器会把存储过程当成SQL语句来处理,容易报错,声明之后则把';'当成过程中的代码*/ |
示例(高级)
1 | -- 从用户表中提取某省份的区县字典表(已存在省份城市表) |
示例(执行SQL语句)
1 | create procedure my_proc(in id int, in name varchar(50), in age int) |
示例(动态游标)
1 | -- 基于视图方式 |
示例(使用map数据结构)
- MySQL存储过程并不直接支持map数据结构,但可以通过以下方法使用
- 基于json实现
1 | -- 声明一个变量用来存储JSON格式的数据 |
- 基于表/临时表/视图实现(视图可以支持变量的方式)
- 将map中的键作为表的主键(Primary Key),将值存储在对应的列中
自定义函数
- handler错误处理时的辅助函数
1 | -- 如果开启了bin-log,则需要设置 `set global log_bin_trust_function_creators=TRUE;`,或者my.cnf配置文件中添加 `log_bin_trust_function_creators=1` |
存储过程调试
- Mysql存储过程调试工具:
dbForge Studio for MySQL
异常
select into
无数据不会报错,而是返回NULL,如果数据条数大于1则会报错
常用存储过程
基于天数进行循环处理
1 | create procedure p_sum_test_sync( |
基于月份进行循环处理
- 结合mysql事件(定时任务)参考:定时任务(事件))为例
1 | create procedure p_sum_test_month ( |
SQLServer
1 | --分页查询 |
Oracle的PL/SQL语言(笔记)
- PL/SQL和C、C++、Java一样是第三代语言,是一种注重过程的语言,可以解决复杂的事物关系。PL/SQL能处理的Java一般也能处理
- 函数和存储过程的区别:函数只能返回一个变量的限制。而存储过程可以返回多个。而函数是可以嵌入在sql中使用的,可以在select中调用,而存储过程不行。执行的本质都一样。
- 函数限制比较多,比如不能用临时表,只能用表变量.还有一些函数都不可用等等.而存储过程的限制相对就比较少
- 变量声明的规则:
- 每一行只能声明一个变量
- 不要与数据库的表或者列同名
- 变量名不能使用保留关键字,如from、select等
- 第一个字符必须是字母
- 变量名最多包含30个字符
- 数据类型
char
定长字符串;存取时效率高,空间可能会浪费varchar2
变长字符串,大小可达4Kb(4096个字节);存取时效率高;varchar2支持世界所有的文字,varchar不支持long
变长字符串,大小可达到2Gnumber
数字;number(5, 2)表示此数字有5位,其中小数含有2位date
日期binary_integer
整数,主要用来计数而不是用来表示字段类型boolean
布尔类型,可以取值为true、false和null值。最好给出默认值
- 零散语句
set serveroutput on;
此时设置了在服务器端输出数据,默认不在服务器端做输出show error
显示详细错误信息。当PL/SQL存在语法错误时,程序只提示有编译错误,如果想了解哪一行出错,需使用语句show error
- 示例
1 | -- 1.输出Hello World! |