oracle template

1、创建一个job

    job

DECLARE
job BINARY_INTEGER;
begin
  sys.dbms_job.submit(job,
                      'CUX_RPT_MATERIEL_MONTH_PKG.RPT_MATERIEL_SPEND_MONTH_ALL(date''2013-06-28'');', --过程名
                      to_date('13-09-2014 16:13:59', 'dd-mm-yyyy hh24:mi:ss'), --执行时间 sysdate当前执行
                      trunc(add_months(SYSDATE,1)) + 3/24); --下次执行时间,如果为null表示只执行一次
  commit;
end;

     schedule

declare
       v_n number default 0;
       ind number default 0;
BEGIN
    select count(*)  into v_n
      from user_scheduler_jobs
    where job_action = '过程名';
  
    if  v_n > 0  then
      DBMS_SCHEDULER.drop_job('PRO_MONTH_REPORT_ALL_JOBS');
    end if;
 
  dbms_scheduler.create_job('PRO_MONTH_REPORT_ALL_JOBS',
                            job_type => 'STORED_PROCEDURE',
                            job_action => '过程名',
                            number_of_arguments => 0,
                            start_date => sysdate,
                            repeat_interval => 'Freq=Monthly;ByMonthDay=28;ByHour=0;ByMinute=0;BySecond=0',
                            end_date  => NULL,
                            job_class => 'DEFAULT_JOB_CLASS',
                            enabled   => FALSE,
                            auto_drop => FALSE,
                            comments  => '描述');
  dbms_scheduler.enable('PRO_MONTH_REPORT_ALL_JOBS');
  COMMIT;
END;

2、树操作

select ... from <TableName>
where <Conditional-1>
start with <Conditional-2>
connect by [prior] <Conditional-3>;如果connect by prior中的prior被省略,则查询将不进行深层递归。

<Conditional-1>:过滤条件,用于对返回的所有记录进行过滤。
<Conditional-2>:查询结果重起始根结点的限定条件。
<Conditional-3>:连接条件
http://www.2cto.com/database/201108/101766.html

3、CURSOR

DECLARE cursor_name CURSOR [ LOCAL | GLOBAL ]
     [ FORWARD_ONLY | SCROLL ]
     [ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ]
     [ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ]
     [ TYPE_WARNING ]
     FOR select_statement
     [ FOR UPDATE [ OF column_name [ ,...n ] ] ]
[;]

4 、 表锁

SELECT B.OWNER, B.OBJECT_NAME, A.SESSION_ID, A.LOCKED_MODE
  FROM V$LOCKED_OBJECT A, DBA_OBJECTS B
WHERE B.OBJECT_ID = A.OBJECT_ID;
 锁表与原因
select l.session_id sid,
       s.serial#,
       l.locked_mode,
       l.oracle_username,
       s.user#,
       l.os_user_name,
       s.machine,
       s.terminal,
       a.sql_text,
       a.action
  from v$sqlarea a, v$session s, v$locked_object l
where l.session_id = s.sid
   and s.prev_sql_addr = a.address
order by sid, s.serial#;

5、序列

CREATE SEQUENCE EPSE_MATERIAL_MASTER_DATA_SEQ     
INCREMENT BY 1   -- 每次加几个      
START WITH 1000     -- 从1开始计数      
NOMAXVALUE       -- 不设置最大值      
NOCYCLE          -- 一直累加,不循环      
CACHE 10;

CREATE SEQUENCE BD_WARE_FORECAST_SEQ     
INCREMENT BY 1   -- 每次加几个      
START WITH 1     -- 从1开始计数      
MAXVALUE 99999     -- 最大值99999      
CYCLE          -- 循环      
CACHE 10;

6、运用表类型

--实例1
--创建一个表的类型 定义一个 VARCHAR2(100)单值类型
CREATE OR REPLACE TYPE t_defind_type IS TABLE OF VARCHAR2(100);
DECLARE
  rids t_defind_type := t_defind_type();--声明引用表类型
BEGIN
     SELECT dsc.root_id BULK COLLECT
     INTO rids FROM bbbb dsc ;
     --输出单个值
     FOR rid IN (SELECT COLUMN_VALUE AS pid FROM table(rids)) LOOP
       dbms_output.put_line(rid.pid);
     END LOOP;
END;
--实例2
--创建一个表的类型指定类型为对象类型
create or replace type type_row as object 

  id int, 
  name varchar2(50) 
);
create or replace type type_table is table of type_row;
   --管道方式
CREATE OR REPLACE FUNCTION F_PIPE(S NUMBER) RETURN TYPE_TABLE
  PIPELINED AS
  V_TYPE_ROW TYPE_ROW;
BEGIN
  FOR I IN 1 .. S LOOP
    V_TYPE_ROW := TYPE_ROW(I, 'name'||TO_CHAR(I * I));
    PIPE ROW(V_TYPE_ROW);
  END LOOP;
  RETURN;
END F_PIPE;
   --普通方式
CREATE OR REPLACE FUNCTION F_NORMAL(S NUMBER) RETURN TYPE_TABLE AS
  RS TYPE_TABLE := TYPE_TABLE();
BEGIN
  FOR I IN 1 .. S LOOP
    RS.EXTEND;
    RS(RS.COUNT) := TYPE_ROW(RS.COUNT, 'name' || TO_CHAR(RS.COUNT));
   /* RESULT(RESULT.COUNT) := TYPE_ROW(NULL, NULL);
    RS(RS.COUNT).NAME := RS(RS.COUNT).NAME || 'xxxx';*/
  END LOOP;
  RETURN RS;
END F_NORMAL;
SELECT id,NAME from table(F_NORMAL(10000));--在返回的集合上有局限性(回报进程内存不足)
SELECT id,NAME from table(f_pipe(10000000));

7、搜索过程中的资源

SELECT * FROM User_Source t WHERE
upper(t.TEXT) LIKE '%关键字%';

--8、创建db_link

CREATE DATABASE LINK mydblink20141024
   CONNECT TO eps_50_test IDENTIFIED BY eps_50_test
   USING '(DESCRIPTION =
     (ADDRESS_LIST =
       (ADDRESS = (PROTOCOL = TCP)(HOST = 10.0.14.220)(PORT = 1521)))
       (CONNECT_DATA = (SERVICE_NAME = mixdb98)
     )
   )';

8、大数据批量查询、插入、更新和删除一些经验。

大数据批量查询【BULK COLLECT】oracle 关键字将数据放在临时表类型中,这样就可以一次性从硬盘中读取到所有的信息集,避免多次读取硬盘信息。注意:数据量过大采用limit限定之后循环读取。

大数据插入、查询、删除【FORALL】关键字进行操作,可以避免多次上下文切换。

如果存在只要数据源不需表的情况可以采用管道函数【pipelined】,获取一个Collections,然后操作这个集合来处理正常的业务,可以有效的提高效率

 例子:

 --A、创建一个表的类型
CREATE OR REPLACE TYPE t_vc IS TABLE OF VARCHAR2(100);
--实例
DECLARE
  empIds t_vc := t_vc();--声明引用表类型
BEGIN
     SELECT dsc.employee_id BULK COLLECT
     INTO empIds FROM dc_sys_employee dsc WHERE dsc.person_status = '01'
     AND dsc.company_id IN (SELECT GUID FROM dc_sys_company_info t WHERE t.status = 'Y' START WITH t.guid = '755YS'
     CONNECT BY PRIOR t.guid = t.p_company_id);
     --输出单个值
     dbms_output.put_line(empIds(1));
     --引用表类型查询数据进行删除
     delete ware_wit_plan t WHERE t.employee_id IN (SELECT COLUMN_VALUE FROM table(empIds)) AND t.source='在职' and t.status='NA' AND t.is_delete = 'N';
     COMMIT ;
END;

--B

DECLARE
   TYPE NumList IS VARRAY(20) OF NUMBER;
   depts NumList := NumList(10, 30, 70);  -- department numbers
BEGIN
   FORALL i IN depts.FIRST..depts.LAST
      DELETE FROM employees_temp WHERE department_id = depts(i);
   COMMIT;
END;
/

9.oracle小计

A、UNION,UNION ALL,INTERSECT,MINUS的区别 
Union,对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序;Intersect,对两个结果集进行交集操作,不包括重复行,同时进行默认规则的排序;Minus,对两个结果集进行差操作,不包括重复行,同时进行默认规则的排序。
intersect运算返回查询结果中相同的部分 

10.oracle临时表空间

--查询临时表空间及大写
SELECT NAME, BYTES / 1024 / 1024 AS "大小(M)"
  FROM V$TEMPFILE
 ORDER BY BYTES;
--查询默认临时表空间
SELECT *
  FROM DATABASE_PROPERTIES
 WHERE PROPERTY_NAME = 'DEFAULT_TEMP_TABLESPACE';
--创建temp02临时表空间
CREATE TEMPORARY TABLESPACE TEMP02 TEMPFILE 'D:\ORACLE\ORADATA\TFJS\TEMP01.DBF' SIZE 1000M AUTOEXTEND ON;
--修改默认临时表空间temp02
ALTER DATABASE DEFAULT TEMPORARY TABLESPACE TEMP02;
--删除temp临时表空间
DROP TABLESPACE TEMP INCLUDING CONTENTS AND DATAFILES;
--创建temp临时表空间
CREATE TEMPORARY TABLESPACE TEMP TEMPFILE 'TEMP01.DBF' SIZE 4000M REUSE AUTOEXTEND ON NEXT 640K MAXSIZE UNLIMITED
--修改默认临时表空间temp
ALTER DATABASE DEFAULT TEMPORARY TABLESPACE TEMP;
--删除temp02临时表空间
DROP TABLESPACE TEMP02 INCLUDING CONTENTS AND DATAFILES;
--查询剩余表空间
SELECT TABLESPACE_NAME, FREE_SPACE / 1024 / 1024 AS "FREE SPACE(M)"
  FROM DBA_TEMP_FREE_SPACE
 WHERE TABLESPACE_NAME = 'TEMP';

11、表分区

*表分区的几种类型及操作方法

 一.范围分区:

    当使用范围分区时,请考虑以下几个规则:
   1、每一个分区都必须有一个VALUES LESS THEN子句,它指定了一个不包括在该分区中的上限值。分区键的任何值等于或者大于这个上限值的记录都会被加入到下一个
高一 些的分区中。
   2、所有分区,除了第一个,都会有一个隐式的下限值,这个值就是此分区的前一个分区的上限值。
   3、在最高的分区中,MAXVALUE被定义。MAXVALUE代表了一个不确定的值。这个值高于其它分区中的任何分区键的值,也可以理解为高于任何分区中指定的VALUE LESS THEN的值,同时包括空值。
二.列表分区:
     该分区的特点是某列的值只有几个,基于这样的特点我们可以采用列表分区。
三.散列分区:
    这类分区是在列值上使用散列算法,以确定将行放入哪个分区中。当列的值没有合适的条件时,建议使用散列分区。
    散列分区为通过指定分区编号来均匀分布数据的一种分区类型,因为通过在I/O设备上进行散列分区,使得这些分区大小一致。

四.组合范围散列分区
     这种分区是基于范围分区和列表分区,表首先按某列进行范围分区,然后再按某列进行列表分区,分区之中的分区被称为子分区。

五.复合范围散列分区:
    这种分区是基于范围分区和散列分区,表首先按某列进行范围分区,然后再按某列进行散列分区。
 12、trigger

create or replace trigger inv_dtl_tmp_after_insert
  before insert on inv_dtl_tmp
  for each row
begin
  if inserting then
    if :NEW.zictag IS NOT NULL then
      select substr(:NEW.zictag,0,1) into :NEW.zictag from dual;
     ELSE
        :NEW.zictag:='1';
    end if;
  end if;
end;


过程 例子

主过程

create or replace procedure WX_MATERIAL_INFORM IS
  num NUMBER;
  str varchar2(300);
BEGIN 
  FOR c IN (SELECT orderid, creat_time, employee_id, employee_name, div_code, div_name, company_id, company_name, brach_id, brach_name, status, origin, last_update_time, update_own, remark, end_time, guid, msg_status FROM int_material_inform WHERE msg_status = '0')
  LOOP
    INSERT INTO his_int_material_inform
      (orderid, creat_time, employee_id, employee_name, div_code, div_name, company_id, company_name, brach_id, brach_name, status, origin, last_update_time, update_own, remark, end_time, guid, msg_status)
    VALUES
      (c.orderid, c.creat_time, c.employee_id, c.employee_name, c.div_code, c.div_name, c.company_id, c.company_name, c.brach_id, c.brach_name, c.status, c.origin, c.last_update_time, c.update_own, c.remark, c.end_time, c.guid, c.msg_status);
  END LOOP;
  --DELETE FROM int_material_inform WHERE msg_status = '0';
  COMMIT;
  BEGIN
    WX_TEST(SYSDATE);
    COMMIT ;
    EXCEPTION
      WHEN TOO_MANY_ROWS THEN
         dbms_output.put_line('TOO_MANY_ROWS');
      WHEN NO_DATA_FOUND THEN
          dbms_output.put_line('NOT_DATA_FOUND');
          ROLLBACK;--回滚防止WX_TEST锁表
      WHEN OTHERS THEN
         BEGIN 
            SELECT COUNT(1) INTO num FROM USER_TABLES WHERE TABLE_NAME = UPPER('BBBB_1') ;
            IF num > 0 THEN
               EXECUTE IMMEDIATE 'DROP TABLE BBBB_1' ;
               dbms_output.put_line('DROP TABLE BBBB_1');
            END IF;
            str := 'CREATE TABLE BBBB_1 AS SELECT * FROM BBBB';--过程中加入DDL语句
            EXECUTE IMMEDIATE str;--立即执行
          END;
         dbms_output.put_line(SQLERRM);
         dbms_output.put_line(SQLCODE);
         dbms_output.put_line('出现异常备份数据');
   END;
   
  EXCEPTION
    WHEN OTHERS THEN
    ROLLBACK ;
    dbms_output.put_line(SQLERRM);
    dbms_output.put_line(SQLCODE);
  /*  set_pro_log('his_int_material_inform',
                '微信通知迁移失败:' || sqlerrm,
                sysdate,
                '');*/
end WX_MATERIAL_INFORM;

被调用过程

--参数 分为in out inout 默认为in
CREATE OR REPLACE PROCEDURE WX_TEST(IDATE DATE, RESULT_TEXT OUT VARCHAR2) IS
  IDX    VARCHAR2(10);
  I_DATE DATE;
  CURSOR CURSOR_1 IS
    SELECT B.LANGUAGE FROM B;
  MYREC B%ROWTYPE;

  CURSOR CURSOR_2(I VARCHAR2) IS
    SELECT B.LANGUAGE FROM B WHERE B.LANGUAGE = I;
  MYCOL B.LANGUAGE%TYPE;
BEGIN
  I_DATE := IDATE;
  DBMS_OUTPUT.PUT_LINE('记录日志1' || I_DATE);

  OPEN CURSOR_1;
  FETCH CURSOR_1
    INTO MYREC;
  WHILE CURSOR_1%FOUND LOOP
    DBMS_OUTPUT.PUT_LINE('sdfs' || MYREC.LANGUAGE);
    FETCH CURSOR_1
      INTO MYREC;
  END LOOP;
  CLOSE CURSOR_1;

  OPEN CURSOR_2('US');
  LOOP
    FETCH CURSOR_2
      INTO MYCOL;
    EXIT WHEN CURSOR_2%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(MYCOL);
  END LOOP;
  CLOSE CURSOR_2;
  -- dbms_output.put_line(SQLCODE);
  SELECT B.ID INTO IDX FROM BBBB B WHERE B.ID = '0' FOR UPDATE NOWAIT; --对表上锁
  --DELETE FROM int_material_inform WHERE msg_status = '0';
  -- error_number_in 之容许从 -20000 到 -20999 之间,
  -- 这样就不会与 ORACLE 的任何错误代码发生冲突。error_msg_in 的长度不能超过 2k,否则截取 2k
  IF IDX = 0 THEN
    RESULT_TEXT := IDX;
    RAISE_APPLICATION_ERROR(-20001, '数值不能为0');
  END IF;
  /* EXCEPTION
    WHEN OTHERS THEN
    ROLLBACK ;
    dbms_output.put_line(SQLERRM);
    dbms_output.put_line(SQLCODE);
  \*  set_pro_log('his_int_material_inform',
                '微信通知迁移失败:' || sqlerrm,
                sysdate,
                '');*\*/
END WX_TEST;

SQL优化纪要

--listagg函数与wm_concat函数
SELECT listagg(zicplnnum,',') WITHIN GROUP (ORDER BY zicplnnum),wm_concat(zicplnnum) FROM inventory_plans_details;
--树结构,SYS_CONNECT_BY_PATH函数用于显示节点路径;SIBLINGS对树的分支进行排序
--注意:如果要先过滤再进行树形查询,则要用子查询
SELECT T.GUID,T.P_COMPANY_ID,T.COMPANY_NAME,SYS_CONNECT_BY_PATH(T.COMPANY_NAME,',')  路径
FROM dc_sys_company_info t START WITH  t.guid = 'B025Y'
       CONNECT BY (PRIOR T.GUID) = T.P_COMPANY_ID
ORDER SIBLINGS BY T.GUID DESC;
--函数coalesce相对于nvl要好用,可以接受多个列,返回第一个不为null的值
--随机排序函数order by dbms_random.value()
--定义转义语句后面加ESCAPE 如:ESCAPE'\'
--关键字“WITH CHECK OPTION”限制数据的录入或者ALTER TABLE V_TABLE ADD CONSTRAINTS V_COL CHECK(COL >10)
INSERT INTO (SELECT CRDATE FROM inventory_plans t
WHERE t.CRDATE < SYSDATE WITH CHECK OPTION)
VALUES(SYSDATE);
--多表插入用无条件insert、insert all(加条件)、insert first(第一个表满足条件插入、第二个表就不用插入了)
INSERT ALL INTO test_1 VALUES(ID,t_desc) INTO test_2 VALUES(ID,t_desc)
SELECT 3 AS ID,'测试3' AS t_desc FROM dual;
--用其他表中值更新用merge into,匹配到了就修改,没有匹配到就插入
MERGE INTO test_1 USING(SELECT * FROM test_2) t2
ON (test_1.id = t2.id)
WHEN MATCHED THEN
  UPDATE SET TEST_1.T_DESC = T2.T_DESC
WHEN NOT MATCHED THEN
  INSERT (ID,T_DESC) VALUES(t2.id,t2.t_desc)
--translate函数与regexp_replace函数
SELECT TRANSLATE(zicplnnum,'-123444544','-'),zicplnnum ,listagg(zicplnnum,',') WITHIN GROUP (ORDER BY zicplnnum),wm_concat(zicplnnum)
FROM inventory_plans_details GROUP BY zicplnnum;
 --累计合 对应的累计查用sum(case when) 变成负数
 SELECT T.ZICPLNNUM, T.ZICEQUNR, T.ZICTIDNR,
        SUM(T.ZICTIDNR) OVER(ORDER BY T.ZICSHTXT) 累计合,
        (SELECT LISTAGG(B.ZICTIDNR, '+') WITHIN GROUP(ORDER BY B.ZICSHTXT) FROM SYS_TEST B
          WHERE B.ZICSHTXT <= T.ZICSHTXT
            AND B.ZICEQUNR = 1) 累计合公式
   FROM SYS_TEST T
  WHERE T.ZICEQUNR = 1  ORDER BY T.ZICSHTXT;
--取最大值最小值,根据开窗函数的排序用first_value取值
SELECT t.zicplnnum,t.zicequnr,t.zictidnr,
first_value(t.zictidnr) OVER(PARTITION BY t.zicequnr ORDER BY t.zictidnr desc)  最小值,
 t.zicshtxt FROM sys_test  t ORDER BY t.zicequnr,t.zictidnr  ;
--比例函数ratio_to_report
 SELECT T.ZICPLNNUM, T.ZICEQUNR, T.ZICTIDNR,T.ZICSHTXT,
 ROUND(ratio_to_report(T.ZICTIDNR) OVER(PARTITION BY t.zicequnr) * 100,2) 占比例
   FROM SYS_TEST T
 ORDER BY T.ZICEQUNR; 

--报表分组

-- ROLLUP和GROUPING函数的引用
--例外。可以使用GROUPING_ID来进行操作(值是GROUPING的十进制数)
SELECT NVL(ZICPLNNUM, '合计') ZICPLNNUM,
       CASE
         WHEN GROUPING(ZICPLNNUM) = 1 THEN
          NULL
         WHEN GROUPING(ZICEQUNR) = 1 THEN
          '小计'
         ELSE
          ZICEQUNR
       END AS 记录,
       ZICEQUNR,
       SUM(ZICTIDNR)
  FROM INVENTORY_PLANS_DETAILS
 GROUP BY ROLLUP(ZICPLNNUM, ZICEQUNR);
 --cube 函数返回每一个组合的小计
select earnmonth, area, sum(personincome)
from earnings
group by cube(earnmonth,area)
order by earnmonth,area nulls last;

--行列转换操作

--PIVOT(列转行函数)将zictplnr列转换成对应的行
SELECT * FROM (SELECT zicplnnum,zictplnr FROM inventory_plans_details)
PIVOT( SUM(1) FOR zictplnr IN ('x' AS is_x,'xx' AS is_xx,'xxx' AS is_xxx));
--语法
SELECT ...
FROM  ...
PIVOT [XML]
   (pivot_clause
    pivot_for_clause
    pivot_in_clause )
WHERE ...

--UNPIVOT行转列函数
SELECT zicshtxt,ds FROM (SELECT zicshtxt , zicplnnum,zictplnr,NULL AS t_col FROM inventory_plans_details)
UNPIVOT INCLUDE NULLS (ds FOR col IN ( zicplnnum,zictplnr,t_col));
--语法
SELECT ...
FROM  ...
UNPIVOT [INCLUDE|EXCLUDE NULLS]
   (unpivot_clause
    unpivot_for_clause
    unpivot_in_clause )
WHERE ...

--执行计划查看

explain plan for  SELECT * FROM (
SELECT ROWNUM AS sn ,t1.* FROM (
SELECT t.guid,t.filiale_id FROM dc_sys_company_info t ORDER BY t.filiale_id ) t1
WHERE ROWNUM <= 10) WHERE sn >5;
select * from table(dbms_xplan.display);

 参考链接:

oracle for update和for update nowait的区别

http://www.cnblogs.com/quanweiru/archive/2012/11/09/2762223.html

oracle游标的定义使用

http://blog.163.com/ufsoftwhy@126/blog/static/40781436200812331257361/

游标是邪恶的!

http://www.cnblogs.com/moss_tan_jun/archive/2011/11/26/2263988.html

ORACLE 异常错误处理

 

http://www.cnblogs.com/soundcode/archive/2012/01/10/2318385.html

FORALL的使用

http://blog.csdn.net/indexman/article/details/9262915

表分区及维护

http://tianzt.blog.51cto.com/459544/171759/

Oracle的pipelined函数实现高性能大数据处理

http://mikixiyou.iteye.com/blog/1673672

你可能感兴趣的:(oracle template)