1、视图

在实际操作过程中,本人发现 Oracle 视图定义有一个缺陷,就是不大方便注释,每次写好的注释执行之后再打开视图定义所有注释就全都没了。后来我发现把注释写到末尾就不会被清除,但这样总感觉乖乖的,而且我没见谁这么用过,我自己也很少这么用,目前还不知道有没有其它问题。创建视图示例:

CREATE OR REPLACE VIEW v_staff2 AS
SELECT t1.staff_id,t1.staff_name,t1.dept_code,t2.enum_name dept_name,t1.gender,
t1.birthday,EXTRACT(YEAR FROM SYSDATE)-EXTRACT(YEAR FROM t1.birthday) age,
t1.edu_bg,t1.base_salary,t1.post_salary,base_salary+post_salary fixed_salary
FROM demo.t_staff t1
LEFT JOIN demo.t_field_enum t2 ON t1.dept_code=t2.enum_code AND t2.field_code='DEPT'
WHERE t1.is_disabled=0
-- 在职员工档案视图
;

查询视图的方法与查询表的方法完全相同,就不再赘述。

2、函数

2.1、创建函数

CREATE OR REPLACE FUNCTION fn_today2
RETURN DATE IS
v_today DATE;
BEGIN
v_today:=TO_DATE('2017-01-10','yyyy-mm-dd');
RETURN v_today;
END;

2.2、调用函数

在 Oracle 中调用函数,大概有三种方式。如调用函数 fn_today,示例:

-- 方式一
SELECT fn_today res FROM DUAL; -- res:2017-01-10
-- 方式二
BEGIN
DBMS_OUTPUT.PUT_LINE('res:'||TO_CHAR(fn_today,'yyyy-mm-dd')); -- res:2017-01-10
END;
-- 方式三
DECLARE
v_today DATE;
BEGIN
v_today:=fn_today;
DBMS_OUTPUT.PUT_LINE('res:'||TO_CHAR(fn_today,'yyyy-mm-dd')); -- res:2017-01-10
END;

3、存储过程

3.1、创建存储过程

创建一个带自制事物的存储过程,示例:

CREATE OR REPLACE PROCEDURE sp_sync_staff90
AS
v_sql VARCHAR2(200); -- SQL语句
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
v_sql:='TRUNCATE TABLE t_staff_young'; -- 清空 90 后职员表
EXECUTE IMMEDIATE v_sql; -- PLSQL 中不能直接执行 DDL 语句
COMMIT; INSERT INTO t_staff_young
SELECT t1.staff_id,t1.staff_name,t1.dept_code,t1.gender
FROM t_staff t1
WHERE t1.birthday>=TO_DATE('1990-01-01','yyyy-mm-dd');
COMMIT;
END;

创建一个带返回值的存储过程,示例:

CREATE OR REPLACE PROCEDURE sp_staff_status
(
p_staff_id NUMBER, -- 职员ID
p_result OUT VARCHAR2 -- 返回职员状态信息
)
AS
v_staff_status NUMBER(1);
BEGIN
IF (p_staff_id IS NULL OR p_staff_id<0) THEN
p_result:='查无此员工!';
ELSE
SELECT t.is_disabled INTO v_staff_status FROM demo.t_staff t WHERE t.staff_id=p_staff_id;
END IF; -- 如果用户没有对应权限则给出具体提示
IF v_staff_status=0 THEN
p_result:='该员工在职!';
ELSE
p_result:='该员工已离职!';
END IF;
END;

创建存储过程的时候有一个小细节需要注意一下,那就是参数名不能与程序中要访问的库表的字段重名;不过即使重名了也还是能通过编译,但等到实际调用的时候就会出问题了,因为 Oracle 会把这个参数当成库表中的字段,即便你在程序中用表别名限定了实际的字段,Oracle 也还是识别不了。如果不知道这个细节的话,是很难解决复杂存储过程中这类问题的,所以写存储过程的时候还是要遵照数据库编程规范,养成一个好的编码习惯,避免因坏习惯而入坑,白白浪费时间。

3.2、调用存储过程

在 PLSQL 的 SQL 窗口中调用无参存储过程的示例:

BEGIN
sp_sync_staff90; -- 这里必须加分号,否则有语法错误
END;

在 PLSQL 的 SQL 窗口中调用有参数存储过程的示例:

DECLARE res VARCHAR2(100);
BEGIN
sp_staff_status(2,res);
DBMS_OUTPUT.PUT_LINE('res:'||res); -- res:该员工在职!
END;

4、包

我有到网上去查询 Oracle 中包的用途,结论是:它就像一个容器,可以将一组逻辑相关存储过程、函数、变量、常量和游标等 PLSQL 程序设计元素放到一起。包由包规范和包体两个部分组成,包规范用于定义公用的常量、变量、存储过程和函数,包体用户存放存储过程和函数的定义。

关于包的好处,网上大多是从程序模块化管理的角度来阐述的,比如说方便查询和维护存储过程和函数等等。我本人从未系统学过 Oracle,原本也不知道 Oracle 中包的存在,后来为写一个触发器来实现在一个批量操作(可能是新增、修改或删除)之后,同时更新另一个表中两个不同字段,更新的条件也不同,条件里需要对第一个表中的数据做聚合操作。如果我没记错的话,应该是添加可以更新,修改和删除不可以更新,如果更新语句执行之后立即提交,语法上又通不过(后来我分析这本身也是矛盾的),总之怎么写都不对。我告诉经理这条路可能走不通,然后把我的分析给他讲了一下,他也觉得我说的有道理。接下来我们开始查资料、找解决方案,经理先找到包变量的用法,并做了个测试认为可行,于是我也照模画样,把已经删掉或改过的数据外键保存到包变量中,再到触发器中去取,发现果然可行,我也这么偶然的接触到 Oracle 中的包。

4.1、创建包/包体

创建一个包含包变量的包规范,示例:

CREATE OR REPLACE PACKAGE pkg_staff AS -- 这里还可以用 IS 代替 AS
staff_id NUMBER(10); -- 包变量,职员ID
staff_name VARCHAR2(20); -- 包变量,职员名称
END;

创建一个包含函数的包规范,示例:

CREATE OR REPLACE PACKAGE pkg_case AS
FUNCTION fn_today RETURN DATE; -- 定义函数 fn_today
END;

创建包规范 pkg_case 的包体,示例:

CREATE OR REPLACE PACKAGE BODY pkg_case AS
FUNCTION fn_today
RETURN DATE IS
v_today DATE;
BEGIN
v_today:=TO_DATE('2017-01-10','yyyy-mm-dd');
RETURN v_today;
END;
END;

注意:必须先创建包规范,然后再创建包体。

4.2、调用包/包体

调用包里的数据库对象与调用普通的数据库对象方式类似,唯一的区别就是要带上包名前缀(包名.包成员名),调用 pkg_case 包里的 fn_today 函数,示例:

SELECT pkg_case.fn_today FROM DUAL; -- res:2017-01-10

5、总结

5.1、删除数据库对象

删除视图、函数、存储过程、包等数据库对象的语法相似,示例:

DROP VIEW v_staff2;
DROP FUNCTION fn_today2;
DROP PROCEDURE sp_sync_staff90;
DROP PACKAGE [BODY] pkg_staff;

.Net程序员学用Oracle系列:视图、函数、存储过程、包的更多相关文章

  1. .Net程序员学用Oracle系列(7):视图、函数、过程、包

    <.Net程序员学用Oracle系列:导航目录> 本文大纲 1.视图 1.1.创建视图 2.函数 2.1.创建函数 2.2.调用函数 3.过程 3.1.创建过程 3.2.调用过程 4.包 ...

  2. .Net程序员学用Oracle系列(7):视图、函数、存储过程、包

    1.视图 1.1.创建.删除及调用普通视图 1.2.高级视图介绍 2.函数 2.1.系统函数介绍 2.2.创建.删除及调用自定义函数 3.存储过程 3.1.创建.修改及删除存储过程 3.2.调用存储过 ...

  3. .Net程序员学用Oracle系列(8):触发器、任务、序列、连接

    <.Net程序员学用Oracle系列:导航目录> 本文大纲 1.触发器 1.1.创建触发器 1.2.禁用触发器 & 启用触发器 & 删除触发器 2.任务 2.1.DBMS_ ...

  4. .Net程序员学用Oracle系列(25):触发器详解

    1.触发器理论 1.1.触发器的应用场景 1.2.触发器的类型 1.3.DML 触发器的触发顺序 2.触发器实战 2.1.创建触发器 2.1.1.创建 DML 触发器 2.1.2.创建 DDL 触发器 ...

  5. .Net程序员学用Oracle系列(28):PLSQL 之SQL分类和动态SQL

    1.SQL 语句分类 1.1.分类方法及类型 1.2.数据定义语言 1.3.数据操纵语言 1.4.其它语句 2.动态 SQL 理论 2.1.动态 SQL 的用途 2.2.动态 SQL 的语法 2.3. ...

  6. .Net程序员学用Oracle系列(30):零碎补充、最后总结(The End)

    1.同义词 2.Flashback 技术 3.连接字符串的写法 4.转义字符 & 特殊运算符 5.文件类型 6.查看参数 & 修改参数 7.AWR 工具 8.学习方法 & 学习 ...

  7. .Net程序员学用Oracle系列(8):触发器、作业、序列、连接

    1.触发器 2.作业 2.1.作业调度功能和应用 2.2.通过 DBMS_JOB 来调度作业 3.序列 3.1.创建序列 3.2.使用序列 & 删除序列 4.连接 4.1.创建连接 4.2.使 ...

  8. 系列文章----.Net程序员学用Oracle系列

    .Net程序员学用Oracle系列(18):PLSQL Developer 攻略 .Net程序员学用Oracle系列(17):数据库管理工具(SQL Plus) .Net程序员学用Oracle系列(1 ...

  9. .Net程序员学用Oracle系列(1):导航目录

    本人从事基于 Oracle 的 .Net 企业级开发近三年,在此之前学习和使用的都是 (MS)SQL Server.未曾系统的了解过 Oracle,所以长时间感到各种不习惯.不方便.怪异和不解,常会遇 ...

  10. .Net程序员学用Oracle系列(2):准备测试环境

    <.Net程序员学用Oracle系列:导航目录> 本文大纲 1.创建说明 1.1.为什么要创建的测试环境? 1.2.了解 Oracle 实例的默认用户 2.创建环境 2.1.创建基本环境 ...

随机推荐

  1. CentOS 7 学习(二) 配置Nginx反向代理

    CentOS 7 学习(二) 配置Nginx反向代理 Nginx可以通过php-fpm来运行PHP程序,也可以转向apache,让apache调用php程序来运行. 不过对于Nginx来说,其反向代理 ...

  2. iOS动态性:动态添加属性的方法——关联(e.g. 向Category添加属性)

    想到要如何为所有的对象增加实例变量吗?我们知道,使用Category可以很方便地为现有的类增加方法,但却无法直接增加实例变量.不过从Mac OS X v10.6开始,系统提供了Associative ...

  3. IDS 源镜像端口添加

    把核心交换机的G1/2口镜像到目的交换机的G1/4口,两个交换机之间都是连接的24口 1.核心交换机配置 Ruijie# configure tRuijie(config)# vlan 77Ruiji ...

  4. 第2章KNN算法笔记_函数classify0

    <机器学习实战>知识点笔记目录 K-近邻算法(KNN)思想: 1,计算未知样本与所有已知样本的距离 2,按照距离递增排序,选前K个样本(K<20) 3,针对K个样本统计各个分类的出现 ...

  5. Java 伙伴系统(模拟)

    参考:https://labrick.cc/2015/10/12/buddy-system-algorithm/ 代码过烂 不宜参考. output: [operating.entity.Heap@4 ...

  6. nova创建虚拟机源码分析系列之四 nova代码模拟

    在前面的三篇博文中,介绍了restful和SWGI的实现.结合restful和WSGI配置就能够简单的实现nova服务模型的最简单的操作. 如下的内容是借鉴网上博文,因为写的很巧妙,将nova管理虚拟 ...

  7. axios配合vue+webpack使用

    1.安装引用: cnpm install axios --save-dev 2.在组件中引入: import axios from 'axios'; 3.使用示例: 执行GET请求: // 为给定 I ...

  8. MySQL如何找到表与表之间的关系?

    如何找到两张表之间的关系? 先站在左表的角度上去找,如果可以找到左表的多个字段可以对应右表的一个字段,那么左表的一个字段foregin key右表的一个字段.一般情况下为id... 2.如果右表的多个 ...

  9. robotframework的学习笔记(十五)----robotframework标准库Collections

    Collections库是RobotFramework用来处理列表和字典的库,官方文档是这样介绍的:A test library providing keywords for handling lis ...

  10. 【精选】Nginx模块Lua-Nginx-Module学习笔记(二)Lua指令详解(Directives)

    源码地址:https://github.com/Tinywan/Lua-Nginx-Redis Nginx与Lua编写脚本的基本构建块是指令. 指令用于指定何时运行用户Lua代码以及如何使用结果. 下 ...