《.Net程序员学用Oracle系列:导航目录》

本文大纲

触发器

创建触发器

CREATE OR REPLACE TRIGGER trg_sync_staff90
-- 功能说明
AFTER INSERT OR UPDATE OR DELETE ON t_staff
FOR EACH ROW
DECLARE
  -- 定义变量
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
  IF INSERTING THEN
    -- 定义DML语句
  ELSIF UPDATING THEN
    -- 定义DML语句
  ELSIF DELETING THEN
    -- 定义DML语句
  END IF;
END;

禁用触发器 & 启用触发器 & 删除触发器

ALTER TABLE t_staff DISABLE ALL TRIGGERS; -- 禁用 t_staff 表上所有的触发器
ALTER TABLE t_staff ENABLE ALL TRIGGERS;  -- 启用 t_staff 表上所有的触发器
ALTER TRIGGER trg_sync_staff90 DISABLE;   -- 禁用触发器 trg_sync_staff90
ALTER TRIGGER trg_sync_staff90 ENABLE;    -- 启用触发器 trg_sync_staff90
DROP TRIGGER trg_sync_staff90;            -- 删除触发器 trg_sync_staff90

任务

DBMS_JOB 包介绍

创建任务的方法有很多,在实际使用过程中,我发现用 DBMS_JOB.SUBMIT 包来创建是比较方便的,语法是 DBMS_JOB.SUBMIT(jobno, what, next_date, interval),示例:

DECLARE jobno NUMBER;
BEGIN
  DBMS_JOB.SUBMIT(jobno, 'sp_sync_staff90;', SYSDATE, 'TRUNC(SYSDATE) + 1 + 2/24');
  COMMIT;
END;

估计有人会感到疑惑,为什么创建任务的语句中 job 参数不给具体值,下面就来简要介绍下 DBMS_JOB.SUBMIT 各个参数及方法的用途和使用说明,如下:

  • job:任务编号,系统会自动分配。我尝试过给一个自己喜欢的数字,但系统不认,还是自动分配了。
  • what:任务要执行的操作(如调用过程等),可通过 DBMS_JOB.WHAT(jobno,what) 修改。
  • next_date:任务的下一次执行时间,可通过 DBMS_JOB.NEXT_DATE(jobno,next_date) 修改。
  • interval:任务执行时间间隔,可通过 DBMS_JOB.INTERVAL(jobno,interval) 修改。
  • 启动 job:DBMS_JOB.RUN(jobno)。
  • 禁用 job:DBMS_JOB.BROKEN(jobno,broken,next_date),broken 参数需要提供布尔值,next_date 参数有默认值(SYSDATE),不需要给值,broken 为 true 表示禁用任务,为 false 表示启用任务,如 DBMS_JOB.BROKEN(135,TRUE) 表示禁用 jobno 为 135 的任务。
  • 删除 job:DBMS_JOB.REMOVE(jobno)。

以上关于 DBMS_JOB 的这些 PLSQL 都不能像普通 SQL 语句一样直接运行,需要写在 BEGIN 和 END 中间,示例:

BEGIN
  DBMS_JOB.BROKEN(135,TRUE);
  COMMIT;
END;

如果想看一下整个数据库目前的任务情况,可以通过 user_jobs 视图来查询,示例:

SELECT job jobno,what,to_char(next_date, 'yyyy-mm-dd hh24:mi:ss') next_date,interval FROM user_jobs;

下面来简要说明一下 user_jobs 视图各主要字段的含义,如下:

  • job:NUMBER 类型,任务的唯一编号。
  • what:VARCHAR2(4000),任务操作内容。
  • next_date:DATE 类型,下一次执行任务的时间。
  • interval:VARCHAR2(200),任务执行时间间隔。
  • log_user:提交任务的用户。
  • priv_user:赋予任务权限的用户。
  • schema_user:对任务作语法分析的用户模式。
  • last_date:最后一次成功运行任务的时间。
  • last_sec:如 hh24:mm:ss 格式的 last_date 日期的小时,分钟和秒。
  • this_date:正在运行任务的开始时间,如果没有运行任务则为 null。
  • this_sec:如 hh24:mm:ss 格式的 this_date 日期的小时,分钟和秒。

interval 参数设置案例:

  • 每分钟(的0秒)执行一次:interval => 'TRUNC(SYSDATE,''mi'') + 1/(24*60)'
  • 每小时(的0分0秒)执行一次:interval => 'TRUNC(SYSDATE,''hh24'') + 1/24'
  • 每隔 7 天执行一次:interval => 'TRUNC(SYSDATE) + 7 + 1/24'
  • 每天凌晨两点执行一次:interval => 'TRUNC(SYSDATE) + 1 + 2/24'
  • 每周一凌晨 1 点执行一次:interval => 'TRUNC(NEXT_DAY(SYSDATE,''monday'')) + 1/24'
  • 每月 5 号凌晨 1 点执行一次:interval => 'TRUNC(LAST_DAY(SYSDATE)) + 5 + 1/24'
  • 每季度第一天凌晨 1 点执行一次:interval => 'TRUNC(ADD_MONTHS(SYSDATE,3),''Q'') + 1/24'
  • 每年 1 月 1 号凌晨 1 点执行一次:interval => 'ADD_MONTHS(TRUNC(SYSDATE,''yyyy''),12) + 1/24'

序列

我接触的两个基于 Oracle 开发的项目都从不用序列,以至于我都没有使用序列的实战经验。写这个章节前我特意查了下序列的定义,我觉得我们可以把序列当成是数字工厂,因为它唯一的功能就是生产等间隔的数值。

用过 Oracle 的人应该都知道,Oracle 没有提供类似于 SQL Server 或 MySQL 中自动增长列的功能,如果我们出于对性能或空间等其它因素的考虑,需要使用自动增长列,则可以通过序列来实现类似功能。

创建序列

创建序列的标准语法如下:

CREATE SEQUENCE seq_name [INCREMENT BY n] [START WITH n] [{MAXVALUE n/NOMAXVALUE}] [{MINVALUE n/NOMINVALUE}] [{CYCLE/NOCYCLE}] [{CACHE n/NOCACHE}];

语法选项说明:

  • INCREMENT BY n:n 表示序列中连续两个值之间的间隔,也称作步长。如果 n 是正数则表示递增,如果 n 是负数则表示递减,默认是 1。
  • START WITH n:n 表示序列的起始值,即序列的第一个值,默认是 1,递增时 n 是 minValue,递减时 n 是 maxValue。
  • MAXVALUE n:n 表示序列的最大值,也可以选择 NOMAXVALUE,即不设置最大值,默认是 999999999999999999999999999。
  • MINVALUE n:n表示序列的最小值,也可以选择 NOMINVALUE,即不设置最小值,默认是 1。
  • CYCLE 和 NOCYCLE 分别表示当序列的值达到极限值后循环取值和不循环取值。
  • CACHE n:n 定义存放序列的内存块的大小,默认为 20(个数字)。NOCACHE 表示不对序列进行内存缓冲。对序列进行内存缓冲,可以改善序列的性能。

使用序列 & 删除序列

  • 使用序列

    • seq_name.CURRVAL:返回序列的当前值。
    • seq_name.NEXTVAL:返回序列的下一个值。
  • 以下情况之一不能使用序列:
    • 1、在 DELETE、SELECT、UPDATE 的子查询中。
    • 2、在视图或物化事物的查询中。
    • 3、SELECT 查询中使用了 DISTINCT 操作符。
    • 4、SELECT 查询中有 GROUP BY 或 ORDER BY。

如果想查询一下数据中到底有那些序列,语法如下:

SELECT * FROM USER_SEQUENCES;
SELECT * FROM ALL_SEQUENCES;
SELECT * FROM DBA_SEQUENCES;

删除序列,示例:

DROP SEQUENCE seq_name;

连接

Oracle 中有个叫做 Database link 的东东,翻译成中文应该是数据库连接,为了称呼方便,下文统一称之为 dblink。在我跟公司一个技术专家对话时,对方提到“数据库连接”,于是我上网查了下:dblink 是定义一个数据库到另一个数据库的路径的对象,dblink 允许你查询远程表及执行远程程序。

dblink 有两种类型的,分别是公用的和私有的。一个公用数据库链接对于数据库中的所有用户都是可用的,而一个私有链接仅对创建它的用户可用。由一个用户给另外一个用户授权私有数据库链接是不可能的,一个数据库链接要么是公用的,要么是私有的。在任何分布式环境里,dblink 都是必要的。另外要注意的是 dblink 是单向的连接。

创建 dblink

创建 dblink 之前先得确定三件事,第一本地数据库和远程数据库之间的网络是可以正常连接的,第二创建 dblink 的账号必须得有 CREATE DATABASE LINK 或 CREATE PUBLIC DATABASE LINK 的权限,第三用来登录到远程数据库的帐号必须得有 CREATE SESSION 权限。

实践告诉我,创建 dblink 的正确语法如下:

CREATE [PUBLIC] DATABASE LINK dblink_name CONNECT TO user_name IDENTIFIED BY user_pwd USING 'connect_string';

其中 connect_string 有两种写法,示例:

-- 第一种写法
CREATE PUBLIC DATABASE LINK dblink168
CONNECT TO office
IDENTIFIED BY 123456
USING '192.168.1.168:1521/orcl';
-- 第二种写法
CREATE PUBLIC DATABASE LINK dblink168
CONNECT TO office
IDENTIFIED BY 123456
USING '(DESCRIPTION = (
        ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.168)(PORT = 1521))
    )(
        CONNECT_DATA = (SERVICE_NAME = orcl)
    )
)';

网上很多文章中给出的创建语法里都不包含指定密码这一项,还说如果不指定,则使用当前的用户名和口令登录到远程数据库,我反复实验了好多次,都是直接报语法错误。不过我倒是发现了一个特点,指定密码创建成功之后,再去查看 dblink 定义的 SQL,会发现密码指令项不见了。我猜应该是 Oracle 做了特殊的加密处理,所以如果你要创建 dblink,不必担心显示指定密码后别人会看到,造成安全泄漏。

使用 dblink & 删除 dblink

  • 使用 dblink

我觉得 dblink 真正的魅力之一便是使用方便,无论增删改查那种语句,只需要在表名后面跟上 @dblink_name 就能操作远程数据库了。如要查询 168 上用户表中女员工的数量,示例:

SELECT COUNT(1) FROM t_staff@dblink168 t WHERE t.gender=0;

测试中我也发现一个小问题,假如我要查询 168 上的服务器时间,按理说写法应该如下:

SELECT SYSDATE FROM DUAL@dblink168; -- 结果显示出来的时间仍是本地数据库的服务器时间

如果为了命名更加统一,或者不想让对方知道 dblink 的名字,也可以通过视图或同义词包装一下,示例:

CREATE VIEW v_name AS SELECT * FROM table_name@dblink_name;
CREATE SYNONYM table_name FOR table_name@dblink_name;

跟 dblink 有关的几个视图,介绍如下:

SELECT * FROM dba_db_links; -- 查询当前数据库实例中所有 dblink
SELECT * FROM v$dblink;     -- 查询当前数据库示例中正在打开状态的 dblink
SELECT * FROM user_sys_privs WHERE PRIVILEGE LIKE '%LINK%'; -- 查询跟 dblink 有关的系统权限
  • 删除 dblink

对于非 PUBLIC 类型的 dblink,只有 owner 自己才能删除,非 PUBLIC 类型的 dblink 没有这个要求。删除 dblink 的示例:

DROP [PUBLIC] DATABASE LINK dblink168;

总结

本文主要介绍了 Oracle 中相对不那么常用的一些对象的 SQL 操作,但在实际做项目过程中,有时候它们又非常实用,所以有必要总结一下,以免用到的时候不记得语法,还得去查资料。

《.Net程序员学用Oracle系列:导航目录》

本文声明:如果您认为这篇文章还可以或对您有帮助,请点击文章末尾的“推荐”按钮。欢迎转载、演绎或用于商业目的,但必须保留本文的署名韩宗泽,并且要在明显位置给出原文链接!本人初写博客,水平有限,若有不当之处,敬请批评指正,谢谢!

.Net程序员学用Oracle系列(8):触发器、任务、序列、连接的更多相关文章

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

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

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

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

  3. .Net程序员学用Oracle系列(6):表、字段、注释、约束、索引

    <.Net程序员学用Oracle系列:导航目录> 本文大纲 1.表 1.1.创建表 1.2.修改表 & 删除表 2.字段 2.1.添加字段 2.2.修改字段 & 删除字段 ...

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

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

  5. .Net程序员学用Oracle系列(9):系统函数(上)

    <.Net程序员学用Oracle系列:导航目录> 本文大纲 1.字符函数 1.1.字符函数简介 1.2.语法说明及案例 2.数字函数 2.1.数字函数简介 2.2.语法说明及案例 3.日期 ...

  6. .Net程序员学用Oracle系列(10):系统函数(下)

    <.Net程序员学用Oracle系列:导航目录> 本文大纲 1.转换函数 1.1.TO_CHAR 1.2.TO_NUMBER 1.3.TO_DATE 1.4.CAST 2.近似值函数 2. ...

  7. .Net程序员学用Oracle系列(11):系统函数(下)

    1.聚合函数 1.1.COUNT 函数 1.2.SUM 函数 1.3.MAX 函数 1.4.MIN 函数 1.5.AVG 函数 2.ROWNUM 函数 2.1.ROWNUM 函数简介 2.2.利用 R ...

  8. .Net程序员学用Oracle系列(15):DUAL、ROWID、NULL

    1.DUAL 表 2.ROWID 类型 2.1.利用 ROWID 查询数据 2.2.利用 ROWID 更新数据 3.NULL 值 3.1.NULL 与空字符串 3.2.NULL 与函数 3.3.NUL ...

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

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

随机推荐

  1. struts2注解redirect传递参数解决方案时,中国的垃圾问题

    struts2注解redirect传递参数解决方案时,中国的垃圾问题 试过很多方法  tomcat 编码  .字符串转换 .URLEncoder  .. 但是,没有解决方案,然后仔细阅读   stru ...

  2. 快速构建Windows 8风格应用32-构建辅助磁贴

    原文:快速构建Windows 8风格应用32-构建辅助磁贴 引言 Windows Phone中,我们开发者可能会开发的一个功能点是将数据列表中某一项"Pin To Start(固定到开始屏幕 ...

  3. DirectX (13) 粒子系统

    笔者:i_dovelemon 资源:CSDN 日期:2014 / 10 / 16 主题:Point Sprite, Particle System 介绍 在游戏中.非常多的绚丽,灿烂的特效,都能够使用 ...

  4. leetcode第27题--Implement strStr()

    Implement strStr(). Returns a pointer to the first occurrence of needle in haystack, or null if need ...

  5. 探秘IntelliJ IDEA 13测试版新功能——调试器显示本地变量

    IntelliJ IDEA在业界被公认为最好的Java开发平台之一,JetBrains公司将在12月正式发布IntelliJ IDEA 13版本. 现在,小编将和大家一起探秘密IntelliJ IDE ...

  6. 让png在ie下正常显示 用到了jquery插件DD_belatedPNG 但是在ie6中这句话 前面添加有效 后面移除无效 IE6 jq removeClass无效

    jQuery(this).addClass("background").siblings().removeClass("background") 导致IE6移除 ...

  7. Your build host version of Xamarin.IOS (release NO.)is too recent to work with the IOS designer

    Encounted such error in VS after I update the xamarin at Mac side.Here is the solution for u to refe ...

  8. fscanf功能具体解释

    cfscanf fscanf fscanf : 格,fscanf格格 :int fscanf(FILE *stream, char *format,[argument...]); int fscanf ...

  9. SSMS2008插件开发(2)--Microsoft Visual Studio 2008插件开发介绍

    原文:SSMS2008插件开发(2)--Microsoft Visual Studio 2008插件开发介绍 由于开发SSMS2008插件是通过VS2008进行的,有必要先介绍一下VS2008的插件开 ...

  10. Unit of work + Repository

    (Unit of work + Repository) 今日后开启进阶模式! 谈到MVC与EntityFramework,则不得不说一说事务与仓储(Unit of work + Repository) ...