Oracle

基础知识

1.1 数据类型

数据类型 描述 单位
char(n) 定长字符串,默认n为1,max为2000字节 字节
varchar2(n) 变长字符串,max为4000字节
nchar 字符集定长字符串,max为为2000字节 字符
nvarchar2 字符集变长字符串,max为4000字节
long 变长字符串,0-2GB
number(m,n) 可变长数值列,m为所有有效数字的位数,n为小数点后的位数,m=[1,38],n=[-84,127]
float 存储126位数据,1-126 二进制
date 7个字节存储日期数据,DD-MON-YY 精确到秒
timestamp 存储日期、时间,精确到小数秒,pm、fm

1.2 创建表

create table table_name(//           约束名     约束映射名         默认值     判空column type constraint constrain_def default default_value NOT NULL,...
);
TABLESPACE TBSONE
PCTFREE 20
PCTUSED 40
INSTRANS 10
MAXTRANS 200;

相关参数说明

参数名 描述
tablespace 指定创建表所在表空间
pctfree 、patused 控制数据块空闲空间的方法。两者之和越接近100%,利用率越高,执行update多,pctfree设置可越大,推荐值:pctfree:20%,patused:40%。执行insert、delete越多,且update不会增加记录大小,pctfree设置可越小,推荐值:pctfree:5%,pctused:60%。
initrans、maxtrans 控制数据块上的并发事务数量,initrans为初始数量,maxtrans为最大数量。
cache 设置表存放数据库高速缓存中的时间
logging 日志类型,是否进行日志操作,关闭日志可提高写入效率,导致无法恢复数据
compress 相同数据自动压缩,减少占用率,提高查询速度

1.3 修改表结构

alter table <username.> table_name add | modify | drop column column_name

<username.> 为创建表所用的用户

1.3.1 添加字段

alter table sys_user add username varchar2(15);

1.3.2 修改字段

alter table sys_user modify username varchar(20) not null;

1.3.3 删除字段

alter table sys_user drop column username;

1.3.4 设置无用字段列

alter table sys_user set unused (username);  //设置无用字段列

1.3.5 删除所有无用列

alter table sys_user drop unused columns;

1.3.6 修改列名

alter table <username.> tabel_name rename column old_name to new_name;

1.3.7 重命名表

alter table sys_user **rename** **to** new_name;

1.3.8 删除表

drop table table_name;

1.4 约束

1.4.1 数据完整性

名称 描述
实体完整性 中每一行要求是唯一的实体,不能为空,不能重复
域完整性 字段满足特定的数据类型和约束
参照完整性 保证关联表数据的正确性
用户定义完整性 用户自定义字段约束

1.4.2 约束类型

名称 描述
主键约束(PRIMARY KEY) 数据表中有且仅有一个,多个列组成的主键成为复合主键,保证数据不重复不为空
外键约束(FOREIGN KEY) 使得表与表之间产生联系
唯一约束(UNIQUE) 一个表可又多个唯一约束,不能重复
非空约束(NOT NULL) 不允许取空值(列级)
检查约束(CHECK) 数据筛选作用,保证输入数据的正确性
默认值约束(DEFAULT) 指定字段默认值
1.4.2.1 主键约束
alter table table_name add constraint constraint_name primary key (column_name);
1.4.2.2 唯一约束
alter table table_name add constraint  constraint_name unique (column_name);
1.4.2.3 非空约束
alter table table_name add constraint constraint_name modify (column_name )not null;
1.4.2.4 检查约束
alter table table_name add constraint constraint_name check (condition);

condition 检查条件 (grade>0 and grade <100)

1.4.2.5 外键约束
alter table table_name1 add constraint constraint_name foreign key (column_name)
reference table_name2 (column_name) on delete cascade;

reference 引用(关系)

on delete cascade 级联删除

1.4.2.6 删除约束
alter table table_name drop constraint constraint_name;

1.5 表数据操作

1.5.1 插入数据

insert into table_name (column_name1,column_name2,column_name3,column_namen)
values (value1,vaule2,value3,valuen)

1.5.2 更行数据

update table_name set column_name1 = value1,column_name2 = value2 where search_condition;

1.5.3 删除数据

delete from table_name where search_condition;

1.6 查询

1.6.1 简单查询

select
distinct     //去重 *
from table_name
where search_condition  //筛选条件
group by group_condition //排序条件
having having_condition    //进一步筛选条件
order by order_condition asc|desc(升|降序); //升降序排列

1.6.2 模糊查询

select * from table_name like '李%'

若条件中有特殊字符,需加上 ‘/’ 转义

1.6.3 控制判断查询

select * from table_name where column IS NULL | IS NOT NULL

1.6.4 结果统计查询

selectid,count(username),avg(score)
from table_name
where search_condition
group by roolup(column_name);

ROOLUP 用来对数据进行进一步的统计(求和、平均数、最大值。。。)

1.6.5 连接查询

1.6.5.1 交叉查询
select column_name from table_name1 cross join table_name2;
1.6.5.2 内连接(简单连接)

只能查询出两个或多个表连接时匹配的记录(多表联查显示符合筛选条件的数据)

1.6.5.2.1 等值连接
select * from table_name1 a inner join table_name2 b on a.id = b.id

筛选条件为等值条件

1.6.5.2.2 非等职连接

筛选条件为非等值条件

1.6.5.2.3 自连接

多个查询表为同一个表

1.6.5.3 外连接
select * from table_name1 a left | right | full outer join table_name2 b on a.id = b.id

联合查询出两个表中的所有数据,数据不匹配时主表显示数据,副表显示数据为空。

1.6.5.3.1 左外连接

联合查询时,左表数据全显示,右表仅显示匹配数据

1.6.5.3.2 右外连接

联合查询时,左表数据仅显示匹配数据,右表数据全显示

1.6.5.3.3 完全外连接

无论数据是否匹配,所有表中数据全显示

1.6.5.3.4 左、右连接特殊方式
select * from table_name1 a,table_name2 b where a.id = b.id(+);

(*) 在哪个表后面有 星号 ,则将该表设为主表

1.6.5 子查询

1.6.5.1 in 子查询
select * from table_name where id [NOT] in (子查询)

in 用来获取一个集合(子查询返回结果)

not in 取非

1.6.5.2 比较运算符子查询
select * from table_name wherer id = (子查询)

’ = ’ ‘<’ ‘>’ ‘<=’ '>= ’ ‘!=’ 只能用来获取单值,多值会发生错误

1.6.5.3 Any 、All 子查询
名称 描述
ANY 满足子查询结果的任何一个(极值)
SOME 与Any含义相同
ALL 满足子查询结果的所有结果(所有值)

用来解决运算符子查询只能用于获取单值问题。

1.6.5.4 Exists子查询
select * from table_name where exists(子查询) and name != 'xiaoye'

Exist用于判断是否存在条件数据,子查询返回的结果为逻辑值,查询结果为空,则exists(子查询)就返回true,否则,返回false,从而子查询中给出列名无实际意义。

1.6.6 集合操作

操作符 说明
UNION[ALL] 返回各个查询检索出的所有行,有All则包括重复值,没All则不包括
INTERSECT 返回两个查询检索出的共有行
MINUS 返回第一个查询的结果减去第二个查询的结果的剩余行数据
select * from table_name1 where search_condition1
union
select * from table_name2 where search_condition2;

1.6.7 sql plus

1.6.7.1 sql plus命令
命令 说明
A[ppend] text 追加文本,将text附加到当前行之后
C[hange] / old text /new text 替换文本,将当前行中的old text 替换成new text
CL[ear] BUFF[ER] 清除文本,清除缓冲区中的所有行
DEL n 删除命令,删除第n行,省略n表示删除当前行(行号从1开始)
L[IST] N 列出第n行sql语句,省略n时,表示列出缓冲区中所有行
R[UN] 或 / 运行缓冲区中保存的语句。也可以用 / 来运行缓冲区中保存的语句
n 将第n行作为当前行

**[]**中为省略部分,实际操作时省略即可

1.6.7.2 追加语句
select * from table_name ;
append where search_condition;
1.6.7.3 替换语句
change /name like '李%'  /name like '王%'
1.6.7.4 保存、检索并运行文件
命令 说明
SAV[E] file_name [{REPLACE|APPEND}] 将sql*plus缓冲区的内容保存到由file_name指定的文件中。APPEND是将缓冲区中内容追加到现有文件之后;REPLACE是直接覆盖现有文件。注意:file_name可以只写一个文件名,也可以写一个具体保存路径,如果只写一个文件名,就表示把当前缓冲区的内容保存到默认文件夹中。
GET file_name 将file_name指定文件的内容读入Sql*plus
STA[RT] file_name 将file_name指定文件内容读入sql*plus并运行,扩展名可写成.sql
@file_name 与start命令相同
ED[IT] 将缓冲区内容复制到afiedt.buf的文件中,然后启动操作系统中默认编译器,在推出编译器是,编辑的文件将会被复制到缓冲区中
ED[IT] file_name 与edit命令相同,但可以指定编辑的文件,文件名可以使用file_name 参数指定
SPO[OL] file_name 将sql*plus中的输出结果复制到file_name指定的文件中,扩展名可写成.sql
SPO[OL] OFF 停止将sql*plus中的输出结果复制到file_name指定的文件中,并关闭该文件,执行语句后,才把查询结果写入到指定文件中。

具体命令操作如下

select * from table_name where search_condiion
// 保存缓冲区内容至demo.sql中
save demo.sql// 获取缓冲区内容
get demo.sql// 加载并运行demo.sql
start demo.sql// 编辑缓冲区 输入命令后windows会默认打开记事本并展示缓冲区中的内容
edit // 将sql*plus的输出结果复制到out.tex中
sql> spool out.txt
sql> /
sql> spool off// 若想将输出结果文件保存到其他位置(加上绝对路径即可)
spool e:\out.txt
1.6.7.5 格式化输出列
1.6.7.5.1 用法
COL[UMN]{ column_name | alias }[options]

column_name 指定列名

alias 指定要格式化的列别名

options 指定用于格式化列或别名的一个或多个选项

1.6.7.5.2 格式化选项
选项 说明
FORP[MAT] format 将列或别名的显示格式设置为由format字符串指定的格式
HEA[DING] heading 将列或别名的变体中的文本设置为由heading字符串指定的格式
JUS[TIFY] [{LEFT | CNETER | RIGHT}] 将列输出设置为左对齐、居中、右对齐
WAR[PPED] 在输出结果中将一个字符串的末尾换行显示。该选项可能导致单个单词跨越多行
WOR[D_WRAPPED] 与WRAPPED选项类似,不同之处在于单个单词不会跨越两行
CLE[AR] 清除列的任何格式化(将格式设置回默认值)
1.6.7.5.3 示例

1、设置输出格式

column student_id format all  --直接对列格式化输出
column sname format A6
column ssex format A4
column 出生日期 foramat A11   --对列别名进行格式化输出
column nationality format A11
column dept_id heading 系部代码 format A8  --指定列标题并格式化输出

2、输出语句

select student_id,sname,ssex,to_char(sbirth,'yyyy-mm') as 出生日期,nationality,dept_id
from students
where sname like '王%'
1.6.7.6 设置页面大小和行大小
set PAGESIZE m  // 设置行数set NEWPAGE n  // 设置页间隔set LINESIZE h // 设置行字符数show PAGESIZE  // 显示行数show NEWPAGE  // 显示页间隔数show LINESIZE // 显示行字符数

m 每页显示的行数 默认值24

n 每页之间间隔的空格数

h 每行展示的字符数 默认值80

set pagesize 100
cloumn course_id format A10
select * from students left outer join sc
on students.student_id = sc.student_id;
1.6.7.7 清除格式
column dep_id clear  // 清除列格式
clear columns      // 清除所有列格式

PL/SQL

1 基础知识

1.1 简介

  • 一种应用在数据库中的程序设计语言。

  • 可以定义常量、变量、赋值语句、表达式、分支、循环

  • 可以在程序中嵌入sql语句

  • 数据操作和查询语句定义在程序块中

  • 是面向过程语言和sql语言的结合,在sql中扩充了面向过程的程序结构

  • 块是程序中最基本的结构

1.2 结构体

命令 名称 描述
[DECLEAR] 声明部分 声明 pl/sql 用到的常量、变量、类型、游标、用户定义异常
BEGIN 执行部分 sql语句、pl/sql语句构成的程序
[EXCEPTION] 异常部门 当程序出现异常时,捕捉异常并处理
END 标记程序体结束

1.3 程序块

declarec_name varchar2(20);
begin select cname info c_namefrom courseswhere course_id = '0019';dbms_output.put_line('代码是0019的课程名称是:'||c_name);
exceptionwhere no_data_found thendbms_output_put_line('没有这门课程!');where too_many_rows thendbms_output.putline('有多门课程的代码重复,均为0019')
end;

2 基本语法

2.1 常量、变量

2.1.1 常量的定义

column_name constant datatype : = value;id constant integer : = 100;

2.1.2 变量的定义

column_name datatype (宽度) : = <初始值>;address varchar2(50);

变量定义时需要进行初始化,若未初始化,则会被赋值为NULL

2.2 表达式、运算符

2.2.1 表达式

  • 由运算符串起来的一组数
  • 表达式数值由组成它的变量、文字的取值和运算符决定
  • 运算符的优先级决定了表达式求值的顺序

2.2.2 运算符

运算符 意义
+、- 正负
+ 加法
- 减法
* 乘法
/ 除法
**

优先级 幂 > 正负 > 乘除 > 加减

2.2.2.1 关系运算符
运算符 意义
<> 不等于
!= 不等于
^= 不等于
< 小于
> 大于
= 等于
2.2.2.2 逻辑运算符
运算符 意义
NOT 逻辑非
AND 逻辑与
OR 逻辑或
2.2.2.3 其他符号
运算符 意义 样例
/ / 多行注释 /* this is a comment*/
单行注释 – this is a comment
|| 并置(+) full_name : = ‘this is a’ || ‘’|| ‘name’
: = 赋值 id : = id +1
字符串界定符(字符串包裹) if vall = ’sandra‘
. 项分隔 select * from student.table_name;
; 语句结束符 select * from student.table_name;
() 列表分割 (‘tom’,‘mary’,‘sam’)

2.3 条件语句

2.3.1 if 语句

declare score number;
begin select grade into scorefrom scwhere course_id = '0001' and student_id ='2330170424';dbms_output.put_line('课程0001号成绩是:'|| score);if score >= 90 thendbms_output.put_line('成绩优秀~');elseif score >= 80 thendbms_output.put_line('成绩良好~');elseif score >= 70 thendbmn_output.put_line('成绩一般~');elseif score >= 60 thendbms_output.put_line('及格~');else dbms_output.putline('不及格');end if
end;

2.3.2 case 语句

declare score number;
begin select grade into scorefrom scwhere course_id = '0001' and student_id ='2330170424';dbms_output.put_line('课程0001号成绩是:'|| score);casewhen score >= 90 thendbms_output.put_line('成绩优秀~');when score >= 80 thendbms_output.put_line('成绩良好~');when score >= 70 thendbmn_output.put_line('成绩一般~');when score >= 60 thendbms_output.put_line('及格~');else dbms_output.putline('不及格');end case;dbms_output.putline('搜索case结构验证完成!');
end;

2.4 循环语句

2.4.1 简单循环

declarei integer :=1;
beginloopinsert into temp values(i);exit when  i = 5;i := i+1;end loop;commit;
end;

2.4.2 for 循环

beginfor v_counter in 1 ... 10 loopinsert into temp values(v_counter);end loop;commit;
end;

for v_conter in reverse 1…10 loop

reverse => 10…1

2.4.3 while 循环

delcarei int := 1;
beginwhen i<10 loopinsert into temp values(1);i := i+1;end loop;commit;
end;

2.4.4 嵌套循环

declarei integer;j integer;
begin<<outer>>for i in 1...5 loopdbms_output.put_line('外层循环:i的值是:' || i);<<inner>>for j in 1...5 loopdbms_output.put_line('内层循环:j的值是:'||j);if j = 3 thenexit outer;end if;end loop inner;end loop outer;dbms_output.put_line('嵌套循环语句块结束~')
end;

outer 和 inner 标签,循环体外层标记

2.5 常用函数

2.5.1 数值型函数

函数 用途
ABS(-8) 取绝对值
CEIL(116.24) 向下取整
FLOOR(116.24) 向上取整
POWER(15,4) 幂函数(次方)
ROUND(123.456,2) = 123.46 四舍五入(小数点后)

2.5.2 字符型函数

函数 用途
ASCLL(‘a’) 将字母转换成ASCLL码值
CHR(‘97’) 将ASCLL值转换成字母
LENGTH(‘hello’) 字符串长度
UPPER(‘hello’) 将字符串转换成大写形式
LOWER(‘HELLO’) 将字符串转换成小写形式
REPLACE(‘计算机专业考试’,‘专业’,‘等级’) 替换字符串
RPAD(‘计算机’,15,‘等级考试’) 右加操作,中间数字为字符串总长度 (’+’)
LPAD(‘计算机’,15,‘等级考试’) 左加操作,中间数字为字符串总长度(’+’)
TRIM(’ oracle database 12c ') 去掉字符串前后空格
LTRIM(’ oracle database 12c’) 去掉字符串前前空格
RTRIM('oracle database 12c ') 去掉字符串后空格

2.5.3 日期型函数

函数 用途
SYSDATE() 系统当前日期和时间 (‘11-06月 -21’)
SYSTIMESTAMP() 系统时间(时区、精确到微秒)(‘11-06月 -21 18.46.00.00001’ 下午 + 08:00)
LAST_DAY(date) 指定日期,对应月份最后一天对应日期
NEXT_DAY(date,char) 指定日期,下个星期’’对应日期,char指定星期全称、缩写都可
MONTHS_BETWEEN(date1,date2) 指定日期间,月的个数
EXTRACT() 指定日期,提取年、月、日、时、分、秒

EXTRACT(YEAR FROM SYSDATE);

EXTRACT(YEAR FROM TIMESTAMP ‘2021-6-11 18:46:00’);

2.5.4 统计函数

函数 用途
COUNT(column_name) 记录某列数据的数量
MAX(column_name) 最大值
MIN(column_name) 最小值
SUM((column_name) 求和值
AVG(column_name) 平均值

2.5.5 转换函数

函数
TO_CHAR() 函数转换成数值、日期转换成字符串
TO_DATE() 字符串转换成日期
CAST 数字转字符、字符转数字、字符转日期、日期转字符

2.6 游标

2.6.1 基本原理

  • 为了协调pl/sql为变量只能存放一条记录和查询结果记录数不确定的,且不知道要声明变量的个数而设立。
  • 是指向内存区域(工作区)的指针
  • 是一种结构化数据类型为应用程序提供对具有多行数据查询结果集中的每一行数据分别进行处理的方法。

2.6.2 显式游标

​ **用途:**暂存查询取出的多行数据,然后一条一条的进行处理。

2.6.2.1、声明游标

将游标与一个select语句进行关联,语句对应记录结果集返回给游标

cursor cursor_name is select_statement;

**注意:**select_statemen : select 语句

2.6.2.2、打开游标

执行游标定义的查询语句,并将数据暂存在游标区域中,游标指针指向游标中第一条记录。

open cursor_name;

打开游标后:

  • 检查联编变量的取值
  • 根据联编变量的取值,确定活动集
  • 活动集的指针指向第一行
2.6.2.3、提取游标
fetch cursor_name into value1,value2,...;
fetch cursor_name into pl/sql 记录

cursor_name为声明且打开的游标

into 后 变量数量应与游标中字段相匹配,且一一对应。

2.6.2.4、关闭游标
close cursor_name

所有记录处理完后需关闭游标,关闭后释放游标区域,占用内存空间回收,后续无法再提取数据。

2.6.2.5、代码示例
declare id varchar2(12);  -- 声明变量存储游标中的学生编号name varchar2(20) -- 声明变量存储游标中的学生姓名-- 定义游标 sid 参数名 指定用户编号cursor cur(sid number) isselect student_id,snamefrom students where student_id = sid;
begin open cur('001'); -- 打开游标,读取编号为001的学生信息fetch cur into id,name; -- 读取当前有标位置的记录close cur; -- 关闭游标dbms_output.put_line('学生学号:'||id|| ',学生姓名:' || 'name');  -- 打印获取记录
end;

2.6.3 隐式游标

  • 非pl/sql程序中定义
  • 一般来说,执行所有sql语句时,Oracle系统自动分配的游标(实则仅限于update、delete)
  • 不需要打开、关闭操作(全自动)

2.6.4 游标属性

  • %isopen、%found、%notfound、%rowcount四种属性
  • 描述与游标相关操作的dml语句执行情况
  • 只能用于pl/sql流程控制语句中,不能用于sql语句中
属性名 用途
%isopen 判断游标是否处于打开状态,若未打开,需打开游标再向下操作
%found 判断当前游标是否指向有效行
%notfound 判断当前游标是否指向无效行
%rowcount 记录游标提取记录的行数,当前游标所在行号

2.6.5 游标变量

  • 动态变量
  • 存放多行记录的结果集
  • 不用于特定的查询绑定,再打开游标后才能确定所对应的查询。
  • 可以依次对应多个查询
2.6.5.1 游标变量的声明
ref type  -- ref : 变量名 type :  已定义类型
TYPE<类型名> is ref cursor  -- <类型名> 新的引用类型名
return <返回类型>;       -- <返回类型> 记录类型,指名最终由游标变量返回的选择列表类型

游标变量返回类型必须是一个记录类型。可以被用户显示声明,也可以通过%rowtype隐式声明。

2.6.5.2 游标变量的打开
  • 如果要将游标变量和特定select语句相关联,需使用open for 语句
  • 如果游标受限,select语句的返回类型必须与游标所限的记录类型相匹配,不匹配会报 ORA_6504
open <游标变量> for <select 语句>
2.6.5.3 游标变量的关闭
  • 对已经关闭的游标变量再次关闭时是非法的。

2.6.6 代码示例

declare rec_dept dept%rowtype;  -- 声明变量存储游标中的学生-- 定义游标 sid 参数名 指定用户编号cursor cur isselect *from dept
begin if cur%isopen = false thenopen cur; -- 打开游标end if;fetch cur into rec_dept; -- 读取当前有标位置的记录while cur%foundloopdbms_output.put_line('系统部编号:'|| rec_dept.dep_id || ',系部名称:' || 'rec_dept.dept_name' || ',系主任:' || ',rec_dept.director'); -- 打印读取数据if cur%rowcount = 4 then -- 只读取4条数据exit;end if;fetch cur into rec_dept; -- 读取当前游标位置数据exit when cur%notfound;end loop;close cur; -- 关闭游标
end;

2.6.7 游标for循环

  • 显示游标快捷使用方式
  • 不需要手动open、fetch、close
2.6.7.1 常规循环
declare-- 声明游标cursor cur isselect * from dept;
begin-- for循环提取游标数据for rec_dep in cur loopdbms_output.put_line('系统部编号:'|| rec_dept.dep_id || ',系部名称:' || 'rec_dept.dept_name' || ',系主任:' || ',rec_dept.director'); -- 打印读取数据end loop;
end;
2.6.7.2 简易写法
begin-- for循环提取游标数据for rec_dep in (select * from dept) loopdbms_output.put_line('系统部编号:'|| rec_dept.dep_id || ',系部名称:' || 'rec_dept.dept_name' || ',系主任:' || ',rec_dept.director'); -- 打印读取数据end loop;
end;

2.6.8 游标的更新(for update)

  • 对游标中数据需要进行修改和删除时,使用for update以便于打开游标时锁定游标结果集在数据库表中对应的数据行
  • 游标可带参,也可不带参
  • 游标打开后为其加锁,关闭后释放锁,保证用户数据访问的正确性和一致性
declarerec_dept dept%rowtype;cursor cur isselect * from deptfor update;
beginopen cur;loopexit when cur%notfound;fetch cur into rec_dept;if rec_dept.dept_id = '001' then  -- 更新表update dept set director = '测试数据'where current of cur;  -- 修改游标当前行end if;end loop;commit;close cur;
end;

2.7 异常处理

名称 描述
预定义异常 Oracle标准错误,无需用户自定义程序解决,用于用户查找代码错误
非预定义异常 其他标准的Oracle错误,需用户自定义程序解决
自定义异常 程序员自定义异常,特定条件下抛出异常
declarev_sid integer :='&学生学号'; -- 声明变量,其值由替换变量'&学生学号'决定v_cid integer :='&课程号';v_grade integer;-- 自定义异常Student_Grade Exception;
beginselect grade into v_grade from studentswhere sid = v_sid and course_id = v_cid;if v_grade <= 0 thenraise Student_Grade;end if;dbms_ouput.put_line('学号为:'||v_sid ||'的同学选修的'||v_cid||'号课程的成绩为:'||v_grade');-- 异常处理部分exceptionwhen Student_Grade thendbms_output.put_line('课程成绩为0或不存在~');rollback;when NO_DATA_FOUND thendbms_output.put_line('没有对应数据~');when TOO_MANY_ROWS thendbms_output.put_line('对应的数据过多~');when OTHERS thendbms_output.put_line('错误情况不明~');
end;

3 存储过程、函数、触发器、程序包

3.1 存储过程

3.1.1 用途

  • 用于Oracle开发者数据转换或查询报表
  • 用于执行某些特定的操作或任务,将经常需要执行的特定操作写成过程
  • 通过过程名可以多次调用过程,实现程序的模块化设计,节省用户时间,提高程序效率

3.1.2 描述

  • 在数据库中定义子程序,将固定操作集中起来放在子程序中,然后统一交给Oracle数据服务器完成,以完成某特定的功能,这种子程序称之为存储过程。
  • 存储在数据库服务器中的封装了一段或多段sql语句的pl/sql代码块。

3.1.3 好处

  • 存储过程在服务器端运行,执行速度快
  • 存储过程执行一次后驻留在Oracle数据库服务器的高速缓存中,方便二次调用,提高系统性能
  • 保证了数据库的安全,在禁止用户直接访问应用程序中的某些数据表的情况下,授权执行访问这些数据表的存储过程
  • 自动完成需要预先执行的任务,可以设置为系统启动时自动执行,方便用户使用。

3.1.4 创建和执行存储过程

1、创建存储过程(示例请看执行存储过程

create or replace procedure procedure_name
{parameter_name1  in | out | inout date_type1,parameter_name2  in | out | inout date_type2,
}
is | asparameter_name3 datatype  //申明部分
begin执行部分
exception异常处理部分
end procedure_name;

or replace : 表示制定过程已存在,则覆盖同名存储过程

procedure_name : 存储过程名称

parameter_name1: 存储过程参数(接收外界传参)

in : 向存储过程传递参数

out : 从存储过程返回参数

data_type : 传入参数类型,可带默认值

as | is : 在之后声明的变量主要用于过程体内,不能加declare

2、执行存储过程

存储过程创建后,通过授权后,存储过程即可被调用执行。

-- 创建存储过程
create or replace procedure insert_student is
begininsert into studentsvalues('001','liushun','男',to_date('1999-10-21','yyyy-MM-dd'),'汉族','0101','010101');exceptionwhen dup_val_on_index thendbms_output.put_line('重复学生Id');when others thendbms_output.put+line('未知错误~');
end insert_student;-- 执行存储过程
set serveroutput on -- 保证了dbms_output.put_line成功输出~
begininser_student;
end;

3、查看存储过程

存储过程一旦创建就会存储到数据库服务器上,orcale通过使用试图user_source查看已存在的存储过程。

select * from user_source where name = 'insert_student' order by line

user_procedures视图部分列

类型 说明
object_name varchar2(30) 对象名,可以是过程、函数、包名
procedure_name varchar2(30) 过程名
aggregate varhcar2(3) 过程是否是聚合函数,Yes、No
impltypeowner varchar2(30) 实现类型的所有者名称(如果有)
impltypename varchar2(30) 实现类型名(如果有)
parallel varchar2(3) 过程是否支持并行查询,Yes、No

3.1.5 带参数的存储过程

  • 允许带参数,增加存储过程灵活性
  • 如果存储过程使用了存储,执行存储过程时必须为其指定参数
3.1.5.1 IN 参数(默认)

参数由调入者传入,只能够被存储过程读取

-- 创建存储过程
create or replace procedure insert_student(p_id in varchar2,p_name in varchar2,p_sex in varchar2,p_birthday in date,p_nat in varchar2,p_did in varchar2,p_cid in varhcar2)is begininsert into studentsvalues(p_id,p_name,p_sex,p_birthday,p_nat,p_did,p_cid);exception whene dup_val_on index then dbms_output.put_line('重复学生id');when others then dbms_output.put_line('未知错误~');end insert_student;-- 执行过程方式1 名称传递execute insert_student(p_id => '001',p_name => 'liushun',p_Sex => '男',p_birthday => to_date('1999-10-21','yyyy-MM-dd'),p_nat => '汉族',p_did => '0101',p_cid => '010101');-- 执行过程方式2 位置传递
execute insert_student('001','liushun','男',to_date('1999-10-21','yyyy-MM-dd'),'汉族','0101','010101');-- 执行过程方式3 组合传递
execcute insert_student('001','liushun','男',to_date('1999-10-21','yyyy-MM-dd'),o_nat => '汉族',p_did =>'0101',p_cid => '010101');
3.1.5.2 OUT 参数

参数由存储过程写入

-- 创建存储过程 (获取输入学生姓名对应的所有学科名称)
create or replace procedure p_coursename(p_sname in varchar2,coursename out varchar2)
is
v_coursename varchar2(50);
beginfor student in (select c.cname from students s,sc,courses cwhere s.student_id = sc.student_idand sc.courese_id = c.course_idand s.name = p_sname) loopv_coursename := v_coursename || student.cname;end loop;coursename := v_coursename;
end p_coursename;-- 创建执行过程
variabel c_name varchar2(20)
exec p_coursename('刘顺',:c_name);
print c_name;
3.1.5.3 INOUT 参数

​ 同时具有in和out参数特性,过程中可以读取和写入参数

-- 创建存储过程 (交换值)
create or replace procedure p_swap(p_v1 in out number,p_v2 in out number)
isv_temp number;
begin v_temp := p_v2;p_v1 := p_v2;p_v2 := v_temp;
end p_swap;-- 执行存储过程
declare var_1 number := 10;var_2 number := 20;
begin   p_swap(var_!,var_2);dbms_output.put_line('var_1=' || var_1);dbms_output.put_line('var_2=' || var_2);
end;
3.1.5.4 默认值

​ 创建存储过程同时给输入参数提供默认值,out、inout参数不具有默认值

-- 创建存储过程
set serveroutput on
create or replace proceduce sum_course_credit(stu_id in varchar2 defalut '2330170424'
)
as
sum_credit number;
beginselect sum(credits) into sum_credit from courseswhere course_id in (select course_id from sc where student_id = stud_id);dbms_ouput.put_line(sum_credit);
end sum_course_credit;-- 执行存储过程
begin sum_course_credit('2330170424');sum_course_credit();
end;

3.1.6 为过程添加局部变量和子过程

过程可以定义局部变量和子过程,局部变量可以在本过程内的任何地方使用,子过程只能被其父过程调用。

-- 修改教师表,添加工资列
alter table teacher
add t_sal number default 2000;
-- 创建存储过程
create or replace proceduce insert_teacher(id in varchar2,name in varchar2,sex in varchar2 default '男',birthday in date,eduction in varchar2 default '研究生',profess in varchar2 default '讲师',dept_id in varchar2,sal in number default '2000'
) istsal in teacher.sal%type;
procedure check_sal(salary in out number) isbegin if salary<2000 then salary:=2000;end if;
end check_sal;begin tsal := sal;check_sak(tsal);insert into teacher(teacher_id,t_name,t_sex,t_birthday,t_education,t_profess,t_dept_id,t_sal)values(id,name,sex,birthday,eduction,profess,dept_id,sal);
end insert_teacher;
-- 执行过程
begininsert_teache('001','liushun',to_date('1999-10-21','yyyy-MM-dd'),'0101','010101');
end;

1、传入sal = 1500,子过程调用check_sal,最终sal = 2000

2、需先定义局部变量,后定义子过程

3、%type变量声明:查看数据库列的数据类型,将数据库类型用于所声明对的变量

​ 好处:

​ 1、用户无需检查数据类就可确保定义的变量能够存储检索的数据

​ 2、后续对数据库结构进行修改,用户不需要考虑对变量进行二次修改,

​ 缺点:

​ 系统每次都需v要查看数据字典来确定变量数据类型,降低了程序的性能

3.1.7 修改和删除存储过程

3.1.7.1 修改
通过 or replace 关键字即可完成过程的修改,覆盖原有定义
3.1.7.2 删除
drop proceduce procedure_name;

3.2 函数

3.2.1 创建函数

  • 函数由return 数据类型自居,用于指定函数返回值的数据类型
  • 在函数体内,用户可以在任何地方使用return,返回值类型必须和函数头中声明的类型保持一致
create or replace function function_name(parameter1 in | out | in out data_type1,parameter2 in | out | in out data_type2,...
)
return data_type;
is | as...声明部分
begin...执行部分
exception...异常处理部分
end function_name;

3.2.2 调用函数

调用函数和调用过程不同,调用函数需要定义一个变量来保存返回的值

declaresum number := 0;
beginsum := function_name(parameter1);dbms_output.put_line(sum);
end;

3.2.3 删除函数

drop function <function_name>;

3.2.4 示例

-- 创建函数
create or replace function count_stu(f_cname in varchar2)
return number;
as
result number := 1;
beginselect count(distinct student_id) into resultfrom sc,courses cwhere course_id = c.course_idand c.cname = f_cname;return(result);
end count_stu;-- 执行函数
declare sum number := 0;
beginsum := count_stu('高数');dbms_output.put_line(sum);
end;

3.3 触发器

3.3.1 概述

3.3.1.1 作用
  • 安全性: 触发器可以基于数据库的值使用户具有操作数据库的某种权利
  • 审计:触发器可以跟踪用户对数据库的操作
  • 实现复杂的数据完整性规则
  • 同步实时的复制表中数据
  • 自动计算数据值,数据值达到一定要求后进行特定的处理
3.3.1.2 分类
名称 描述
DML触发器 对表或视图执行DML操作时触发
INSTEASD OF 触发器 只定义在试图上用来替换实际的操作语句
系统触发器 在对数据库系统进行操作时触发(DDL、启动或关闭数据库)
3.3.1.3 概念
要素 条件
事件 DML、DDL、数据库系统事件(系统启动、退出)、用户事件(登录或退出数据库)
条件 where指定的逻辑表达式,为true时触发事件、执行触发器
对象 表、视图、模式、数据库
操作 要执行的pl/sql程序(执行部分)
时机 before(防止错误发生或实现业务规则)、after(记录操作或事后处理)
子类型 row(行触发,受触发器影响每一行)statement(语句触发,受触发器影响的一行)

注意:

​ 1、触发器应建立在哪个表之上

​ 2、触发器应该对什么样的DML操作进行响应

​ 3、指定DML操作之后还是之前触发

​ 4、对每次DML响应一次,还是受DML影响的每一行数据都响应一次

3.3.1.4 触发器执行顺序
  • Before触发器
  • 执行语句
  • After触发器
  • 多个Before/After 触发器,先创建先执行
3.3.1.5 创建触发器语法
create or replace trigger trigger_name
before | after | instead of
insert or delete or update of column_name ...
on table_name | view_name
for each row when trigger_condition -- 或省略,默认语句触发,这里表示行触发
begintrigger_body
end trigger_name;

trigger_name : 触发器名称

instead of : 创建替代触发器,触发事件不执行,执行触发器本身操作

insert or delete or update : 多个触发事件之间使用or连接

of column_name: 指出在哪一列触发

on table_name : 指定表创建触发器

3.3.2 DML触发器

3.3.2.1 语句级触发器
-- 创建语句级触发器的测试表
create table syslog(who varchar2(20),when date
);
-- 创建语句级触发器
create or replace trigger user_ls.delteUserafter delete on user_ls.user
begininsert into user_ls.syslog values(user,sysdate);
end deleteUser;
-- 测试触发器delete user_ls .user where id = 1;
3.3.2.2 行级触发器
-- 创建行触发器
create or replace del_stuafter delete on user_ls.studentsfor each row when (old.dept_id= '001');
begindbms_output.put_line('1行数据已被成功删除~');
end del_stu;
-- 测试触发器
delete from user_ls.students where dept_id = '001';

3.3.3 替代触发器

  • 用来对另一个表或视图进行DML操作
  • 定义替代触发器后,表或视图的操作不再被执行,而去执行触发器主体中的操作
  • 通过在替代触发器中编写代码以实现对组成视图的各个表进行操作
-- 创建视图
create or replace trigger user_ls.update_dep_viewinstead of update on user_ls.dep_viewfor each now
begin-- 更新teacher表update user_ls.teacherset tname =: new.tnamewhere teacher_id := old.teacher_id;-- 更新dept表update user_l.dept set dept_name =: new.dept_namewhere dept_name =: old .dept_name;
end update_dep_view;

instead of 没有before和after关键字,等同于after的行级触发器,用户不能修改其中的:new值

3.3.4 系统事件触发器

  • 数据库的启动(startup)
  • 数据库的关闭(shutdown)
  • 数据库服务器出错(servererror)
-- 创建系统时间触发器测试表
create table db_log (op_date timestamp);-- 创建系统事件触发器
create or replace trigger db_startupafter startupon startupon database
begin insert into db_logvalues(sysdate);
end db_startup;

db_startup触发器作用: 在用户登录数据库时,记录登录时间

startup 和 servererror 只可以创建ater startup触发器

shutdown 只能创建before shutdown 触发器

servererror触发器既能够与数据库相关联,又能够与特定模式相关联,与特定模式相关联时,表示只有该模式上的操作所导致的错误才会触发。

3.3.5 用户事件触发器

  • 与数据库定义语句DDl 或用户的登录/注销等事件相关的触发器
  • 包括以下语句:
    • create
    • alter
    • drop
    • analyze
    • associate statistics
    • disassociate statistics
    • audit
    • notaudit
    • commit
    • grant
    • revoke
    • rename
    • truncate 以上触发事件都可为after、before
    • logoff 只能为before
    • suspend 只能为after
    • logon 只能为after
-- 创建用户存储信息的表
create table user_ls.drop_obj(object_name varchar2(20),object_type varchar2(20),drooped_date date
);
-- 创建用户事件触发器(在用户删除对象之前记录到日志信息表)
create or replace trigger user_ls.dropped_objbefore dropon user_ls.schema
begininsert into user_ls.drop_objvalues(dict_obj_name,dict_obj_type,sysdate);
end dropped_obj;

3.3.6 管理触发器

3.3.6.1 查看触发器

与触发器有关的数据字典

数据字典 描述
USER_TRIGGERS 存储当前用户所拥有的触发器
DBA_TRIGGERS 存储管理员所拥有的触发器
ALL_TRIGGERS 存储所有触发器
USER_OBJECTS 存储当前用户所拥有的对象,包括触发器
DBA_OBJECTS 存储管理员所拥有的对象,包括触发器
ALL_OBJECTS 存储数据库中所有对象,包括触发器

​ USER_TRIGGERS表主要列的意义

列名 描述
TRIGGER_NAME 触发名
TRIGGER_TYPE 触发时间After、Before,行级触发、语句出发
TRIGGERING_EVENT 触发器事件
TABLE_NAME 与触发器相关的表或视图
BASE_OBJECT_TYPE 与触发器相关的对象类型:表、视图、模式、数据库
WHEN_CLAUSE 触发器的when子句代码
STATUS 触发器状态:启用、禁用
DESCRIPTION 类型或事件信息的概述
TRIGGER_BODY 触发器中的pl块
3.3.6.2 启动和禁用触发器(挂起)
alter trigger trigger_name disable | enable
3.3.6.3 修改触发器
create or replace ...
3.3.6.4 删除触发器
drop trigger trigger_name

3.4 程序包(Class)

  • 用于将逻辑相关的PL/SQL块或元素(变量、常量、自定义数据类型、异常、过程、函数、游标)组织在一起,作为一个完整的单元存储在数据库中
  • 使用包组织过程、函数、游标后,使得程序设计实现模块化
  • 调用包后会将其放在内存中,方便二次调用从内存中直接读取,提高程序运行效率
  • 两部分组成
    • 规范(specification):

      • 说明部分(包头、头部)

        • 过程名
        • 函数名
        • 其他对象名及参数
    • 包体(body):
      • 执行部分(须和规范中声明的完全匹配)

        • 过程
        • 函数
        • 参数返回值

包体中未在规范中列出的部分属于私有对象(private),只能用在包体内(对用户隐藏复杂性)

3.4.1 包规范的创建

create or replace package package_name
is | as
package_specifiction
end package_name

package_specification : 用于列出公共过程、函数、类型和对象

3.4.2 包体的创建

create or replace package body package_name
is | as
package_body
end package_name;

package_body : 用于定义过程和函数代码

3.4.3 包的使用

beginpackage_name.object_name;
end;

package_name : 包名

objec_name : 包方法或对象

3.4.3 示例

-- 创建程序包
create or replace package body user_ls.pkg_test
is-- 创建存储过程procedure prc_getCourse(c_id in user_ls.courses.id%type,c_name out user_ls.course.cname%type,c_credit out user_ls.course.credis%type,c_stucount out number)is-- 存储过程执行方法begin select cname,credits,count(sc.student_id)into c_name,c_credit,c_stucountform user_ls.courses c, user_ls.sc scwhere c.course_id = sc.course_id and c.course_id = c_idgroup by c.course_id,cname,credits; -- group by后面与select 列名保持一致end prc_getCourse;-- 创建函数function fn_maxgrade(f_c_id in user_ls.sc.course_id%type)return numberismax_grader number;-- 函数执行方法beginselect max(grade) into max_gradefrom user_ls.scwhere course_id = f_C_id;return(max_grade);end fn_maxgrade;
end pkg_test;-- 使用包函数和过程
declarec_id in user_ls.courses.id%type;c_name out user_ls.course.cname%type;c_credit out user_ls.course.credis%type;c_stucount out number;f_c_id user_ls.sc.courtse_id%type;max_grade number;
beginc_id := '001';f_c_id := '0001';user_ls okg_test.prc_getCourse(c_id,c_name,c_credit,c_stucount);max_grade := user_ls.pkg_test.fn_maxgrade(f_c_id);dbms_output.put_line('课程信息:');dbms_output.put_line('-----------------------------------');dbms_output.put_line('课程名称:' || c_name);dbms_output.put_line('课程学分:' || c_credit);dbms_output.put_line('选课人数:' || c_stucount);dbms_output.put_line('课程号为:' || f_c_id|| '的最高分是' || max_grade);dbms_output.put_line('-----------------------------------');
end;

3.4.4 获取有关包中函数和过程的信息

-- 从user_procedures中检索pkg_course_count_maxgrd的object_name 和 procedure_name列的信息
select object_name,procedure_name
from user_procedures
where object_name = 'pkg_course_count_maxgrd'

3.4.5 删除包

drop package package_name;

3.4.6 内置包

包名称 描述
DBMS_ALTER 数据库报警,允许会话间通信
DBMS_JOB 任务调度服务
DBMS_LOB 大型对象操作
DBMS_OUTPUT 实现基本的输入输出功能
DBMS_PIPE 数据库管道,运行会话期间通信
DBMS_SQL 执行动态SQL,执行DDL语句
DBMS_FILE 对操作系统文件进行读、写等操作

group by后面与select 列名保持一致
end prc_getCourse;

– 创建函数
function fn_maxgrade(f_c_id in user_ls.sc.course_id%type)
return number
is
max_grader number;
– 函数执行方法
begin
select max(grade) into max_grade
from user_ls.sc
where course_id = f_C_id;
return(max_grade);
end fn_maxgrade;
end pkg_test;

– 使用包函数和过程
declare
c_id in user_ls.courses.id%type;
c_name out user_ls.course.cname%type;
c_credit out user_ls.course.credis%type;
c_stucount out number;
f_c_id user_ls.sc.courtse_id%type;
max_grade number;
begin
c_id := ‘001’;
f_c_id := ‘0001’;
user_ls okg_test.prc_getCourse(c_id,c_name,c_credit,c_stucount);
max_grade := user_ls.pkg_test.fn_maxgrade(f_c_id);
dbms_output.put_line(‘课程信息:’);
dbms_output.put_line(’-----------------------------------’);
dbms_output.put_line(‘课程名称:’ || c_name);
dbms_output.put_line(‘课程学分:’ || c_credit);
dbms_output.put_line(‘选课人数:’ || c_stucount);
dbms_output.put_line(‘课程号为:’ || f_c_id|| ‘的最高分是’ || max_grade);
dbms_output.put_line(’-----------------------------------’);
end;


#### 3.4.4 获取有关包中函数和过程的信息```sql
-- 从user_procedures中检索pkg_course_count_maxgrd的object_name 和 procedure_name列的信息
select object_name,procedure_name
from user_procedures
where object_name = 'pkg_course_count_maxgrd'

3.4.5 删除包

drop package package_name;

3.4.6 内置包

包名称 描述
DBMS_ALTER 数据库报警,允许会话间通信
DBMS_JOB 任务调度服务
DBMS_LOB 大型对象操作
DBMS_OUTPUT 实现基本的输入输出功能
DBMS_PIPE 数据库管道,运行会话期间通信
DBMS_SQL 执行动态SQL,执行DDL语句
DBMS_FILE 对操作系统文件进行读、写等操作

Oracle使用文档相关推荐

  1. 连载三:Oracle升级文档大全

    (共33篇干货文章,建议收藏并在PC端打开) Oracle 11203->11204.6小版本物理升级方案 https://www.modb.pro/doc/190 OEM CC 12.1.0. ...

  2. oracle联机文档使用,Sqlplus 联机文档学习

    Oracle联机文档 [原文] Starting SQL*Plus Command-line The SQL*Plus executable is usually installed in $ORAC ...

  3. 【MOS】中文文档列表 - Oracle Database (文档 ID 1533057.1)

    中文文档列表 - Oracle Database (文档 ID 1533057.1) 类型: 状态: 上次主更新: 上次更新: ANNOUNCEMENT PUBLISHED 2017-2-23 201 ...

  4. 经典的ORACLE培训文档

    经典的ORACLE培训文档1 数据库的安全性.完整性.并发控制和恢复 为了保证数据库数据的安全可靠性和正确有效,DBMS必须提供统一的数据保护功能.数据保护也为数据控制,主要包括数据库的安全性.完整性 ...

  5. 连载一:Oracle迁移文档大全

    (共33个干货文档,建议收藏并在PC端打开) Oracle 10g->11g XTTS迁移方案 https://www.modb.pro/doc/188 Oracle 9i至11g exp迁移  ...

  6. oracle帮助文档_Spring Boot Config文档,使用IntelliJ IDEA的两种方法

    一个Spring Boot文档,两种方式. 在优锐课的java沙龙分享中,在现代软件开发中,应用程序由配置驱动. 如果可配置属性的数量很大,则很难记住每个属性的用途,结构或类型. 因此,有必要对这些属 ...

  7. oracle dbua 升级,33篇Oracle升级文档大全(收藏版)

    Oracle 11203->11204.6小版本物理升级方案https://www.modb.pro/doc/190 OEM CC 12.1.0.2 -> 12.1.0.5 升级报告htt ...

  8. Toad for Oracle 使用文档

    Toad®for Oracle 版本 12.0.1 发行说明 30 July 2013 目录 欢迎使用 Toad for Oracle 版本更新 解决的问题和改进 已知问题 第三方已知问题 升级和兼容 ...

  9. Oracle在线文档下载 【转载自@secooler】

    今天有同事询问Oracle在线浏览的手册是否可以下载,确实下载到本地浏览才是非常方便的,之前从@secooler大神这里找过下载链接,特此转载,以备查询,向大神致敬! @secooler 转载地址:h ...

  10. c oracle帮助文档下载,Oracle 19c 官方文档——Concepts

    Oracle 19c 官方文档--Concepts 免费 专栏简介 19c 作为 Oracle 12c 的最终版以及稳定版,在正式的 Linux 版本出来之前,先熟悉其各个部分的特性是必须的,以此为目 ...

最新文章

  1. 《从零开始学Swift》学习笔记(Day 52)——Cocoa错误处理模式
  2. python详细基础教程-Python基础教程,Python入门教程(非常详细)
  3. 【计算机网络】网络层 : 网络层简介 ( 功能 | 拥塞控制 )
  4. 深入redis内部---网络编程
  5. linux 哪个进程在使用串口_Linux内核的整体架构
  6. php websocket 实战,一次WebSocket项目实战后总结的经验
  7. Monkey测试实例
  8. 专题突破一之分块——Untitled Problem II,Balanced Lineup,[ioi2009]Regions
  9. 第七十三期:2019大裁员!年关将至,裁员比例竟达90%?
  10. matlab设置ga算法,matlab遗传算法ga函数
  11. 传输层协议(10):滑动窗口(4)
  12. 从看《长津湖》想到的数字化转型
  13. java代码实现CGCS2000大地坐标系XY值转化为对应经纬度
  14. Spyder窗口布局调整
  15. CentOS7下collectd简单安装使用
  16. 10分钟手把手教你用Android手撸一个简易的个人记账App
  17. 基于腾讯云的 Rust 和 WebAssembly 函数即服务
  18. 嵌入式STM32F767BGT6规格STM32F767BIT6引脚图 32Bit MCU+FPU
  19. 音频单元组件服务参考(Audio Unit Component Services Reference)
  20. 动图怎么做二维码?怎么将gif格式图片生成二维码?

热门文章

  1. 企业级搜索solr应用
  2. Python基础知识讲座
  3. “Map.get“ and value test should be replaced with single method call
  4. Ranged-Based for loop vs. iterator
  5. 荧火虫flash制作过程
  6. [python机器学习]机器学习简单示例-KNN、决策树、线性回归、逻辑回归
  7. 假期学习【八】首都之窗百姓信件爬虫(完整版)2020.2.6 Python
  8. 安哥拉(Angola)CNCA船运证书是CONSELHO NACIONAL DE CARREGADORES DE ANGOLA的缩写
  9. 读《asp.net MVC4开发指南(黄保翕编著)》笔记
  10. 缓存(cache)与缓冲(buffer)