zoukankan      html  css  js  c++  java
  • oracle-pl/sql之二

    java

    触发器

    你可以编写用户定义的函数(用pl/sql,java,c)来提供在sql中或sql内置函数中不可用的功能

    有时,我们会发现有些功能通过PL/SQL完成会很麻烦,而通过C/C++语言编程则会容易很多。因此,oracle提供了在PL/SQL程序里直接调用外部函数(包括C函数或Java方法)的功能,从而扩展了PL/SQL的程序功能。

    在Oracle的存储过程和函数中,其实IS和AS是同义词,没有什么区别。
    还有在自定义类型(TPYE)和包(PACKAGE)时,使用IS和AS也并没有什么区别。
    但是在创建视图(VIEW)时,只能使用AS而不能使用IS。
    在声明游标(CURSOR)时,只能使用IS而不能使用AS。

    用java的方法

    例子:一个简单的需求,用Java代码实现求圆的面积,圆周率PI为3.14,输入的参数为圆的半径R,输出圆的面积S,要求可以在oracle中用PL/SQL代码调用该Java类实现求圆的面积的功能。
    
    Step 1:编写Java代码,PL/SQL Developer本身虽然支持编写Java代码,但是毕竟不是专业的,对Java的工具提供的不是特别好,我喜欢用MyEclipse开发好以后复制过来,下面是我在MyEclipse中开发好的代码。
    
    // 圆工具类,计算圆的面积
    public class CircleTools {
      // 定义常量PI
      public static final double PI = 3.14;
     
      // 计算面积
      public static double calcSquare(double r) {
        return PI * r * r;
      }
    }
    
    注意在写Java代码的时候,为了能够直接能够在oracle中被调用,所以这里在需要调用的方法前要加上public和static。
    
    
    Step 2:写好Java代码,下面就是要将Java导入到oracle数据库中,
    导入的方法在前文提到过可以用loadJava或者直接写。如果要用loadJava导入,先把上面的代码文件保存为CircleTools.java,然后在cmd命令行中进入该目录下,然后执行如下命令:
    
    loadjava是安装数据库自带的工具
    [oracle@oracle1 ~]$ which loadjava
    /u01/app/oracle/product/11.2.0/dbhome_1/bin/loadjava
    
    loadjava –u username/userpassword –v -resolve CircleTools.java
    
    执行上面的命令就OK了,下面提供另一种方法,就是直接在PL/SQL中写,写法如下:
    
    CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED circletools AS
    // 圆工具类,计算圆的面积
    public class CircleTools {
      // 定义常量PI
      public static final double PI = 3.14;
      // 计算面积
      public static double calcSquare(double r) {
        return PI * r * r;
      }
    }
    
    
    查看这个数据字典发现已经进入数据库中了
    select * from user_objects
    where length(object_type) >5;
    
    
    Step 3:编写存储过程(procedure)或者函数(function)来封装,以实现以后的调用,一般来说,如果一个Java方法没有返回值,那么就封装成存储过程,如果有返回值,就封装成函数,这里我只给出一个封装成函数的例子:
    
    CREATE OR REPLACE FUNCTION calc_square(r IN NUMBER) RETURN NUMBER AS
      LANGUAGE JAVA NAME 'CircleTools.calcSquare(double) return double';
    
    Step 4:测试函数,2是半径
    select calc_square(2) from dual;
    
    Step 5:如果不想用那个Java类了,可以用dropjava命令删除掉系统中的Java,这个跟loadjava很相似,
    dropjava -user username/userpassword@db -v javasourcename
    
    注意上面删除的是Java的source name,不是class name,即对象的OBJECT_TYPE是JAVA SOURCE,不是JAVA CLASS。

    触发器

    ===============================

    创建触发器

    create or replace trigger test.login_log  
      after create or drop on schema
     BEGIN
     -- 以下使用的是事件属性
     DBMS_OUTPUT.PUT_LINE('I believe you have created a ' ||
     ORA_DICT_OBJ_TYPE || ' called ' ||
     ORA_DICT_OBJ_NAME);
     END;

    测试触发器

    set serveroutput on
    CREATE TABLE "TEST"."T3"
      (
        "PRODUCT_ID"   NUMBER,
        "PRODUCT_NAME" VARCHAR2(80 BYTE),
        "MONTH"        NUMBER
      );
    drop table t3 purge;

    ===========================

    记录登录数据库历史记录,使用触发器

    建表可以在普通用户之下,但创建触发器需要在sys用户下

    create table login_history  
    (  
      username   varchar2(60),  --用户名  
      machine    varchar2(60),  --机器名  
      login_time date,          --登录时间  
      ip         varchar2(50)   --ip地址  
    );


    create or replace trigger login_log  
      after logon on database  
    begin  
      insert into test.login_history
         select username, machine, sysdate, sys_context('userenv', 'ip_address')  
          from v$session  
         where audsid = userenv('sessionid');  
      commit;  
    end;  

    CREATE OR REPLACE TRIGGER TRIGGER1
    BEFORE DELETE OR INSERT OR UPDATE OF IP,LOGIN_TIME,MACHINE,USERNAME ON LOGIN_HISTORY
    BEGIN
      NULL;
    END;

    可用的DDL事件
    DDL事件 			触发时机
    ALTER 				对数据库中的任何一个对象使用SQL的ALTER命令时触发
    ANALYZE 			对数据库中的任何一个对象使用SQL的ANALYZE命令时触发
    ASSOCIATE STATISTICS 统计数据关联到数据库对象时触发
    AUDIT 				通过SQL的AUDIT命令打开审计时触发
    COMMENT 			对数据库对象做注释时触发
    CREATE 				通过SQL的CREATE命令创建数据库对象时触发
    DDL 				列表中所用的事件都会触发
    DISASSOCIATE STATISTICS 去掉统计数据和数据库对象的关联时触发
    DROP 				通过SQL的DROP命令删除数据库对象时触发
    GRANT 				通过SQL的GRANT命令赋权时触发
    NOAUDIT 			通过SQL的NOAUDIT关闭审计时触发
    RENAME 				通过SQL的RENAME命令对对象重命名时触发
    REVOKE 				通过SQL的REVOKE语句撤销授权时触发
    TRUNCATE 			通过SQL的TRUNCATE语句截断表时触发 
    可用属性
    Oracle 提供了一系列的函数用来提供关于什么触发了DDL触发器以及触发器的状态灯信息。上面那个触发器的例子就使用了属性。
    DDL触发器事件以及属性函数
    函数名 							返回值
    ORA_CLIENT_IP_ADDRESS 			客户端IP地址
    ORA_DATABASE_NAME 				数据库名称
    ORA_DES_ENCRYPTED_PASSWORD 		当前用户的DES算法加密后的密码
    ORA_DICT_OBJ_NAME 				触发DDL的数据库对象名称
    ORA_DICT_OBJ_NAME_LIST 			受影响的对象数量和名称列表
    ORA_DICT_OBJ_OWNER 				触发DDL的数据库对象属主
    ORA_DICT_OBJ_OWNER_LIST 		受影响的对象数量和名称列表
    ORA_DICT_OBJ_TYPE 				触发DDL的数据库对象类型
    ORA_GRANTEE 					被授权人数量
    ORA_INSTANCE_NUM 				数据库实例数量
    ORA_IS_ALTER_COLUMN 			如果操作的参数column_name指定的列,返回true,否则false
    ORA_IS_CREATING_NESTED_TABLE 	如果正在创建一个嵌套表则返回true,否则false
    ORA_IS_DROP_COLUMN 				如果删除的参数column_name指定的列,返回true,否则false
    ORA_LOGIN_USER 					触发器所在的用户名
    ORA_PARTITION_POS 				SQL命令中可以正确添加分区子句位置
    ORA_PRIVILEGE_LIST 				授予或者回收的权限的数量。
    ORA_REVOKEE 					被回收者的数量
    ORA_SQL_TXT 					触发了触发器的SQL语句的行数。
    ORA_SYSEVENT 					导致DDL触发器被触发的时间
    ORA_WITH_GRANT_OPTION 			如果授权带有grant选项,返回true。否则false
    更多属性函数请参考官方文档PL/SQL Language Reference -> Triggers and Oracle Database Data Transfer Utilities
    创建触发器

    CREATE OR REPLACE TRIGGER test.no_drop BEFORE DDL ON DATABASE BEGIN IF ORA_SYSEVENT = 'CREATE' THEN DBMS_OUTPUT.PUT_LINE('Warning !!! You have created a '|| ORA_DICT_OBJ_TYPE ||' called '|| ORA_DICT_OBJ_NAME|| '; UserName(creater):'|| ORA_DICT_OBJ_OWNER||'; IP:'|| ORA_CLIENT_IP_ADDRESS||'; event:'|| ORA_SYSEVENT); ELSIF ORA_SYSEVENT = 'DROP' THEN RAISE_APPLICATION_ERROR (-20000, 'Cannot create the ' || ORA_DICT_OBJ_TYPE || ' named ' || ORA_DICT_OBJ_NAME || ' as requested by ' || ORA_DICT_OBJ_OWNER); END IF; END;

    测试触发器
    set serveroutput on
    CREATE TABLE "TEST"."T4"
      (
        "PRODUCT_ID"   NUMBER,
        "PRODUCT_NAME" VARCHAR2(80 BYTE),
        "MONTH"        NUMBER
      );
    drop table t4 purge;

    package包的使用

    SET SERVEROUTPUT ON SIZE 40000
    DECLARE
    req UTL_HTTP.REQ;
    resp UTL_HTTP.RESP;
    value VARCHAR2(1024);
    BEGIN
    --UTL_HTTP.SET_PROXY('proxy.my-company.com', 'corp.my-company.com');
    req := UTL_HTTP.BEGIN_REQUEST('http://www.ka1che.com');
    UTL_HTTP.SET_HEADER(req, 'User-Agent', 'Mozilla/4.0');
    resp := UTL_HTTP.GET_RESPONSE(req);
    LOOP
    UTL_HTTP.READ_LINE(resp, value, TRUE);
    DBMS_OUTPUT.PUT_LINE(value);
    END LOOP;
    UTL_HTTP.END_RESPONSE(resp);
    EXCEPTION
    WHEN UTL_HTTP.END_OF_BODY THEN
    UTL_HTTP.END_RESPONSE(resp);
    END;

    ==================================================

    http://blog.csdn.net/ls_man/article/details/11981967

    创建过程来自动杀死相关session

    GRANT create view to PERSONAL;
    grant alter system to personal;

    create view mysession as  
    select SID,SERIAL# from v$session
    where schemaname in ('TEST1','TEST2');

    create user test1 identified by 123456;
    create user test2 identified by 123456;
    grant connect,resource to test1,test2;



    create or replace procedure kill_session is  
      v_sid    varchar2(30);  
      v_serial varchar2(30);  
      v_sql    varchar2(1000);  
      TYPE DyData IS REF CURSOR;  
      rows DyData;  
    begin  
     
      v_sql := 'select * from mysession ';  
      OPEN rows FOR v_sql;  
      LOOP  
        FETCH rows  
          into v_sid, v_serial;  
        
        v_sql := 'alter system kill session ''' || v_sid || ',' || v_serial || '''';  
        execute immediate v_sql;  
        --dbms_output.put_line(v_userid || '__' || v_user || '__' || v_pwd);  
        
        EXIT WHEN rows%NOTFOUND;  
      END LOOP;  
     
    end kill_session;  


    ======================================


    Oracle wrap 和 unwrap( 加密与解密) 说明
    http://blog.chinaunix.net/uid-7589639-id-3767585.html

    wrap 的使用步骤如下:
    (1)将我们要加密的sql 语句保存到一个sql文本里。
    (2)用wrap 进行处理,指定输入的sql,即我们第一步的问题,然后指定输出的路径和文件名,默认扩展名是plb。
    (3)执行我们第二步进过wrap 处理的sql,即plb文件,创建我们的对象.

    命令行界面
    cat dave.sql
    wrap iname=dave.sql
    cat dave.plb

    sqlplus界面
    @dave.plb
    select F_DAVE(4) from dual;
    select text from dba_source where name='F_DAVE';

    wrap的目的是为了加密,所以Oracle并没有提供unwrap 的方法。 itpub上的一些牛人研究了一下这个问题,写了一些unwrap的代码。 具体讨论的过程,参考itpub的2个帖子:

    阿里巴巴的张端弄了一个界面的Unwrap软件,下载地址:

  • 相关阅读:
    rails时间问题
    stringify_keys 和symbolize_keys
    thritf
    Nginx负载均衡反向代理
    CentOS 7 yum 安装 Nginx
    CentOS 7安装与配置Tomcat8
    CentOS 7安装与配置JDK8
    系统数据字典模块设计
    mysql视图
    阿里云maven中央仓库
  • 原文地址:https://www.cnblogs.com/createyuan/p/6908777.html
Copyright © 2011-2022 走看看