当前位置:  数据库>oracle

Oracle 批量更新sequence的存储

    来源: 互联网  发布时间:2017-06-09

    本文导语: 前言: Oracle的序列(SEQUENCE)A SCHEMA OBJECT THAT GENERATES A SERIAL LIST OF UNIQUE NUMBERS FOR TABLE COLUMNS.TO USE A SEQUENCE ,YOUR SCHEMA MUST CONTAIN THE SEQUENCE OR YOU MUST HAVE BEEN GRANTED THE SELECT OBJECT PRIVILEGE FOR ANOTHER USER IS SEQUENCE.ONCE A SEQUENCE IS DEFINED,IT CAN BE...

前言:

Oracle的序列(SEQUENCE)A SCHEMA OBJECT THAT GENERATES A SERIAL LIST OF UNIQUE NUMBERS FOR TABLE COLUMNS.TO USE A SEQUENCE ,YOUR SCHEMA MUST CONTAIN THE SEQUENCE OR YOU MUST HAVE BEEN GRANTED THE SELECT OBJECT PRIVILEGE FOR ANOTHER USER IS SEQUENCE.ONCE A SEQUENCE IS DEFINED,IT CAN BE ACCESSED AND INCREMENTED BY MULTIPLE USERS(WHO HAVE SELECT OBJECT PRIVILEGE FOR THE SEQUENCE CONTAINING THE SEQUENCE)WITH NO WAITING.THE DATABASE DOES NOT WAIT FOR A TRANSACTION THAT HAS INCREMENTED A SEQUENCE TO COMPLETE BEFORE THAT SEQUENCE CAN BE INCREMENTED AGAIN. 

简单说:序列一般用于自动递增生成主键值 ..

但是否有一些情况会导致调用SEQ_....NEXTVAL时大于主键最大值呢?

场景:

  主键表 -> T表 '100W'数据同步到T1表(同步:TRUNCATE/DELETE或IMPDP...等方式[手动改数据])

  例如: T表对应SEQ_T.NEXTVAL= 100W;

        T1表对应SEQ_T.NEXTVAL= 10W;

        TRUNCATE TABLE T1;

        INSERT TABLE T1 SELECT * FROM T;

        数据同步但T1表对应SEQ_T.NEXTVAL= 10W序列不变;

        此时T1调用序列INSERT到T1表时就会报错 ( ORA-00001 : 违反唯一约束条件 (LOTTERY.PK_T1))

        (若批量同步很多表就可能会引起很多表序列需要更新成主键最大值+ 1才能保证不报错

        (可以用把源库的SEQUENCE同步过来①或者如下存储解决② ))

  ①PLSQL 工具的COMPARE USER OBJECTS可以解决SEQUENCE序列对象同步到其他环境...在此就不细说了

  ②我们环境序列一般都是由SEQ_表名字组成.所以写批量更新存储的时候比较方便~

  如下存储针对常用于以上场景的环境,,生产环境不批量导新数据/同步用户数据/表数据 就很少用到...也可只提供参考...

--批量更新序列存储--
CREATE OR REPLACE PROCEDURE P_SYNCSEQ(USERNAME VARCHAR2 /*传入要检查/更新序列的用户*/ ) IS

  /*

  **@AUTHOR 毛海晴

  ORACLE 批量更新SEQUENCE

  注释:

    批量更新SEQUENCE,

    更新序列下一个值 = 主键最大值+1

    ---序列创建时,属性NOMAXVALUE=最大值是10的28次方

  思路:

    1、找到每个表主键列 且在该表主键最大值是什么?

    2、找到表对应SEQUENCE值 与 表主键最大值去对比。

    如果SEQUENCE 下一个值大于表主键最大值就不做更新;
 

    否则需要进行更新(2中更新方式)

    1)删除SEQUENCE ,创建新序列开始值为表主键最大值+1;  --本文选择此方案...嘿嘿~

    (坏处:赶好在DROP SEQUENCE..而程序也恰巧调用依赖它的函数和存储过程将失效

    但 后续CREATE SEQUENCE了,再调用了会重新编译 调用..不会报错....有实验过哦~)

    2)ALTER SEQUENCE .. INCREMENT BY .. NOCACHE;

      SELECT ...NEXTVAL FROM DUAL;

      ALTER SEQUENCE .. INCREMENT BY 1 CACHE 20;

    .... sequence.nextval其实也可以用user_sequences.last_number字段实现..由于最早存储就这样的写就没改~...谅解~

    SEQUENCE和表名长度最大限制是30

    SEQUENCE规范的名字SEQ_+表名字    -- 此处规范只是管理维护方便而已 并不是非要这样要求

    如果表名长度大小大于26 加上"SEQ_"就大于了SEQUENCE长度限制的30

    若表名长度大于26,那对应序列肯定不是规范命名(SEQ_表名字),再由于这样的序列并不多,所以将这些一一处理

    在更新前可先注释掉EXECUTE IMMEDIATE,先作下测试看下效果,免得EXECUTE IMMEDIATE DROP .后创建报错,导致在调用 序列不会创建,也校验不到序列

 

    所需权限:
    -- 创建序列权限 --

    -- Grant/Revoke system privileges
    grant create sequence to LOTTERY;
    --查询权限--
    -- Grant/Revoke object privileges
    grant select on DBA_CONSTRAINTS to LOTTERY;
    grant select on DBA_CONS_COLUMNS to LOTTERY;
    grant select on DBA_SEQUENCES to LOTTERY;
    grant select on DBA_TABLES to LOTTERY;
    grant select on DBA_TAB_COLUMNS to LOTTERY;
      --或者--
      -- Grant/Revoke system privileges
      grant select any dictionary to LOTTERY;
 

 */


 

  --变量

  MAX_ID            NUMBER(12 ); 

  P_SEQ_NUM          NUMBER(12 );

  P_TABLE_NAME      VARCHAR2(50 );

  P_COLUMN          VARCHAR2(50 );

  P_SEQUENCE        VARCHAR2(50 );

  P_SQL              VARCHAR2(500 );

  P_SEQ_SQL          VARCHAR2(5000 );

  P_SQL_SEQ          VARCHAR2(30000 );

  P_NEW_COUNT        NUMBER(12 );


 

  --查询表长度小于26 的表/序列

  --游标

  CURSOR C_CONS IS -- 查询表长度小于26 的表/序列

    SELECT T1.TABLE_NAME    TABLE_NAME,

          T1.COLUMN_NAME    COLUMN_NAME,

          T1.SEQUENCE_NAME1 SEQUENCE_NAME

      FROM ((SELECT C.TABLE_NAME,

                    CASE

                      WHEN C1.DATA_TYPE = 'NUMBER' THEN

                      C.COLUMN_NAME

                      ELSE

                      'TO_NUMBER(' || C.COLUMN_NAME || ')'

                    END COLUMN_NAME,

                    C.SEQUENCE_NAME1

              FROM (SELECT C.TABLE_NAME,

                            C.COLUMN_NAME,

                            'SEQ_' || C.TABLE_NAME SEQUENCE_NAME1

                      FROM DBA_CONS_COLUMNS C --用户的约束对应的表列信息

                      WHERE C.OWNER = UPPER (USERNAME)

                        AND (C.CONSTRAINT_NAME, C.TABLE_NAME) IN

                            ( SELECT S.CONSTRAINT_NAME, S.TABLE_NAME

                              FROM DBA_CONSTRAINTS S --用户的对象约束信息

                              WHERE S.OWNER = (UPPER (USERNAME))

                                AND S.CONSTRAINT_TYPE = 'P' /*CONSTRAINT_TYPE: P:主键,R:外键,C:非空约束/CHECK;*/

                            ---若主键是由多字段'ID1,ID2',该查询会显示成2行分别为(T.ID1 SEQ_T和T.ID2 SEQ_T)

                            )

                    --..一个序列被2个表/2字段共用...可以用如下方式进行

                    UNION

                    SELECT 'ETL_CS_CUST_INFO_MID' ,

                            'BATCH_NO', --若数据为VARCHAR类型需要TO_NUMBER转换来取MAX(字段)

                            'SEQ_ETL_CS_CUST_INFO_MID'

                      FROM DUAL) C,

                    DBA_TAB_COLUMNS C1

              WHERE C1.OWNER = UPPER (USERNAME)

                AND C1.COLUMN_NAME = C.COLUMN_NAME

                AND C1.TABLE_NAME = C.TABLE_NAME)

          /**

          ---提供表长度大于26 的表名字/序列  ..再关联DBA_CONS_COLUMNS找到对应的主键字段..和表长度小于26部分的查询进行UNION ALL

          CS_BEAR_ALLOWANCE_AND_INJ_DET ---> SEQ_CS_BEAR_ALLOWANCE_INJ_DET

          CS_BEAR_ALLOWANCE_AND_INJ_DETS ---> SEQ_CS_BEAR_ALLOWANCE_INJ_DETS...等

          */

            UNION ALL (SELECT M1.TABLE_NAME, COLUMN_NAME, M2.SEQUENCE_NAME

                        FROM (SELECT LENGTH(C.TABLE_NAME) AA,

                                      C.TABLE_NAME,

                                      C.COLUMN_NAME

                                FROM DBA_CONS_COLUMNS C

                                WHERE C.OWNER = UPPER (USERNAME)

                                  AND (C.CONSTRAINT_NAME, C.TABLE_NAME) IN

                                      ( SELECT S.CONSTRAINT_NAME, S.TABLE_NAME

                                        FROM DBA_CONSTRAINTS S

                                        WHERE S.OWNER = UPPER (USERNAME)

                                          AND S.CONSTRAINT_TYPE = 'P' )) M1 --如果不限制主键 可能找到NOT NULL的列

                        JOIN (SELECT TABLE_NAME, SEQUENCE_NAME

                                FROM (SELECT 'CS_BEAR_ALLOWANCE_AND_INJ_DET' TABLE_NAME,

                                            'SEQ_CS_BEAR_ALLOWANCE_INJ_DET' SEQUENCE_NAME

                                        FROM DUAL

                                      UNION ALL

                                      SELECT 'CS_BEAR_ALLOWANCE_AND_INJ_DETS' ,

                                            'SEQ_CS_BEAR_ALLOWANCE_INJ_DETS'

                                        FROM DUAL)) M2

                          ON M1.TABLE_NAME = M2.TABLE_NAME

                        WHERE AA > 26 )) T1,

          DBA_SEQUENCES SQ, --(列出的序列是否在库中存在)

          DBA_TABLES T --(列出的表是否在库中存在)..由于环境不同用到的序列可能也是不同的.若不加可能会报错

    WHERE SQ.SEQUENCE_NAME = T1.SEQUENCE_NAME1

      AND T.TABLE_NAME = T1.TABLE_NAME

      AND SQ.SEQUENCE_OWNER = UPPER (USERNAME)

      AND T.OWNER = UPPER (USERNAME);


 

  ----------------------以上查询表/对应序列/主键字段 -------------

  ----------------------以下开始判断序列是否需要更新 -------------


 

BEGIN

  ----------------------SEQUENCE判断更新语句 -----------------------------

  --~~注释:DBMS_OUTPUT.PUT_LINE(XX)是将这个结果或者查询显示出来

  --EXECUTE IMMEDIATE XX; --执行XX的查询

  --开始 SEQUENCE.nextval和主键最大值 做比较..


 

  FOR P_C_CONS IN C_CONS LOOP

    --利用C_CONS游标对应列值

    P_TABLE_NAME := P_C_CONS.TABLE_NAME;

    P_COLUMN    := P_C_CONS.COLUMN_NAME;

    P_SEQUENCE  := P_C_CONS.SEQUENCE_NAME;

 

    ---每次循环都赋值0 ..

    MAX_ID := 0;

    --查询表主键中最大值

    P_SQL := 'SELECT MAX(' || P_COLUMN || ')  FROM  ' || P_TABLE_NAME;

    --USING MAX_ID

    EXECUTE IMMEDIATE P_SQL

      INTO MAX_ID;

 

    -- 查询序列.nextval值

    P_SEQ_SQL := 'SELECT ' || P_SEQUENCE || '.NEXTVAL FROM DUAL' ;

    --USING P_SEQ_SQL

 

    EXECUTE IMMEDIATE P_SEQ_SQL

      INTO P_SEQ_NUM;

 

    ---SEQUENCE.nextval和主键最大值 做比较..(如果SEQUENCE.nextval当前主键最大值+1 才是SEQUENCE要更新值,才保证主键值再加入的时候不冲突;

      P_SQL_SEQ  := 'CREATE SEQUENCE ' || P_SEQUENCE ||

                    ' MINVALUE 1 NOMAXVALUE START WITH ' || P_NEW_COUNT ||

                    '  INCREMENT BY 1 CACHE 20'; --创建正确的SEQUENCE语句

   

      /*打印序列创建语句*/

      /*DBMS_OUTPUT.PUT_LINE('CREATE SEQUENCE ' || P_SEQUENCE ||

      ' MINVALUE 1 NOMAXVALUE START WITH ' ||

      P_NEW_COUNT || '  INCREMENT BY 1 CACHE 20');*/

   

      --执行创建序列语句

      EXECUTE IMMEDIATE P_SQL_SEQ;

     

      --打印错 错误序列对应的表、序列由之前值更新到现在的值;

      DBMS_OUTPUT.PUT_LINE( '错误序列对应的表:' || P_TABLE_NAME || '

            ' || P_SEQUENCE || ' 由' ||

                          P_SEQ_NUM || '更新到' || P_NEW_COUNT || ';' );

    END IF ;

  END LOOP;

END P_SYNCSEQ;
 

--使用步骤:

--  编辑存储..-->调用存储(Call change_varchar2(username => 'u1' );或者begin..传值.等)

--输出结果:


--DROP SEQUENCE SEQ_T1    --本文中存储打印部分注释掉了.若想看其效果将注释/**/打开.

--CREATE SEQUENCE SEQ_T1 MINVALUE 1 NOMAXVALUE START WITH 1004  INCREMENT BY 1 CACHE 20  --本文中存储打印部分注释掉了.若想看其效果将注释/**/打开.

--错误序列对应的表:T1

            SEQ_T1 由1000更新到1004;

祝好~


    
 
 

您可能感兴趣的文章:

  • Oracle Database 建立与查询 Sequence
  • oracle sequence语句重置方介绍
  • Oracle sequence序列的用法
  • Hibernate Oracle sequence的使用技巧
  • Oracle、DB2、PostgreSQL之Sequence大总结
  • Oracle中使用触发器(trigger)和序列(sequence)模拟实现自增列实例
  • Oracle创建自增字段--ORACLE SEQUENCE的简单使用介绍
  • sqlserver实现oracle的sequence方法
  • 浅谈在Hibernate中使用Oracle sequence
  • oracle的sequence怎么在EJB中实现???
  • oracle分页存储过程 oracle存储过程实例
  • Oracle自动存储管理支持库 ASMLib
  • Oracle存储过程调试简述
  • oracle的存储过程实例讲解
  • Oracle存储过程如何返回一个结果集&如何获取
  • 关于SHELL调用oracle存储过程出现的一个小问题
  • Oracle利用存储过程造数据
  • oracle数据库中查看系统存储过程的方法
  • 求教:shell 脚本怎么获取ORACLE存储过程的返回值?
  • 帮我看一下程序,java调用oracle数据存储的问题?
  • 谁有oracle存储过程的原代码?谢谢!
  • 关键字: oracle,存储过程,数据库,查询,动态sql包,数组,参传,jdbc 1
  • oracle 在一个存储过程中调用另一个返回游标的存储过程
  • Linux下用SHELL脚本执行带输入输出参数的ORACLE存储过程并得到结果
  • Oracle ASM自动管理存储管理简介
  • Linux下Oracle RAC一个节点宕机导致共享存储无法挂载的故障排除
  • 实现Oracle数据库的存储过程中拥有“role”权限
  • 对Oracle存储过程的几点认识
  • Oracle主键自增及存储过程的实现
  • Oracle索引存储关系到数据库的运行效率
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • 对Oracle存储过程的几点认识 iis7站长之家
  • Oracle 2010年4月更新修复Oracle协作套件安全漏洞
  • Oracle 2010年7月更新修复Oracle Fusion中间件安全漏洞
  • oracle更新xml节点问题的一些细节
  • Oracle 2010年7月更新修复多个Oracle Database安全漏洞
  • Oracle 2010年7月更新修复Transportation Manager安全漏洞
  • Oracle 2010年7月更新修复Enterprise Manager Grid Control安全漏洞
  • jsp如何选择更新oracle的date字段
  • Oracle 2010年7月更新修复多个PeopleSoft安全漏洞
  • Oracle 2010年7月更新修复多个E-Business Suite安全漏洞
  • Oracle 2010年4月更新修复多个E-Business Suite安全漏洞
  • Oracle多表级联更新详解
  • ORACLE学习笔记-添加更新数据函数篇
  • 如何用不算很熟练的jsp,oracle,javascript,html,css等建设动态网站,要网页打开速度快、易于日常维护更新?
  • 利用可更新ResultSet的updateBinaryStream()可以把图片存到mySql数据库,却不能存到Oracle数据库,怎么办?
  • 批量更新关联表(oracle、sql server)
  • 为什么我用javabean更新不了数据库?javabean,oracle高手请进!!!!!高分相赠!!!在线等待中。。。
  • Oracle 12c发布简单介绍及官方下载地址
  • 在linux下安装oracle,如何设置让oracle自动启动!也就是让oracle那个服务自动启动,不是手动的
  • oracle 11g最新版官方下载地址
  • 请问su oracle 和su - oracle有什么不同?
  • Oracle 数据库(oracle Database)Select 多表关联查询方式
  • 虚拟机装Oracle R12与Oracle10g
  • Oracle数据库(Oracle Database)体系结构及基本组成介绍
  • Oracle 数据库开发工具 Oracle SQL Developer
  • 如何设置让Oracle SQL Developer显示的时间包含时分秒
  • Oracle EBS R12 支持 Oracle Database 11g
  • Oracle 10g和Oracle 11g网格技术介绍
  • SCO unix下安装oracle,但没有光盘,请大家推荐一个oracle下载站点(unix版本的)。谢谢!!!!
  • oracle中如何把表中具有相同值列的多行数据合并成一行
  • 请问大家用oracle数据库, 用import oracle.*;下的东西么? 还是用标准库?


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,