前言:
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<主键最大值,更新序列'drop-create')
    IF P_SEQ_NUM < MAX_ID THEN
      
      /*DBMS_OUTPUT.PUT_LINE( 'DROP SEQUENCE ' || P_SEQUENCE);*/
 
        --删除原来不正确的SEQUENCE
      EXECUTE IMMEDIATE 'DROP SEQUENCE ' || P_SEQUENCE;
      P_NEW_COUNT := 0;
      P_NEW_COUNT := MAX_ID + 1; -->当前主键最大值+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;

转://批量更新sequence的存储的更多相关文章

  1. MongoDB学习笔记~大叔分享批量添加—批量更新—批量删除

    回到目录 说它是批量操作,就是说将集合对象一次提交到服务器,并对数据进行持久化,如果您的代码是一次一次的提交,那不算是批量操作!在之前的mongodb仓储中并没有对批量更新和批量删除进行实现,而今天在 ...

  2. [转]MySQL批量更新死锁案例分析

    文章出处:http://blog.csdn.net/aesop_wubo/article/details/8286215 问题描述 在做项目的过程中,由于写SQL太过随意,一不小心就抛了一个死锁异常, ...

  3. 如何 ︰ 执行批量更新和插入使用.NET 提供程序在 C#.NET OpenXML

    https://support.microsoft.com/zh-cn/kb/315968 如何 ︰ 执行批量更新和插入使用.NET 提供程序在 C#.NET OpenXML Email Prin ...

  4. MySQL批量更新死锁案例分析--转载

    问题描述 在做项目的过程中,由于写SQL太过随意,一不小心就抛了一个死锁异常,如下: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackE ...

  5. .Net中批量更新或添加数据

    方法一:使用SqlBulkCopy实现批量更新或添加数据. SqlBulkCopy类一般只能用来将数据批量插入打数据库中,如果数据表中设置了主键,出现重复数据的话会报错,如果没有设置主键,那么将会添加 ...

  6. 【mysql】批量更新数据

    概述 批量更新mysql数据表数据,上网搜索基本都会说4~5方法,本人使用的更新方式为: INSERT ... ON DUPLICATE KEY UPDATE Syntax 可参见官方网站:inser ...

  7. 一个简单的批量更新oracle 数据库中 最近的服务商名称的数据

    有一个需求是这样的,我们需要更新数据库中的数据,数据时这样的 1.大约50万以上 2. 数据中有较多的重复数据 3. 需要将表中最近的代理商的名称赋值给行中的服务商名称 4. 代理商的名称可能有多个, ...

  8. SqlDataAdapter 批量更新数据库表

    在数据库中批量插入数据许多人都已经了解了,就是使用.net 中的SqlBulkCopy对象(MSDN详解).我们在做评教系统的时候使用过这个对象,它能将数据表批量导入到数据库中,效率比单条插入数据效率 ...

  9. SQL-批量插入和批量更新

    批量插入 表结构一样或类似 如果两张表的结构一样,例如一个表的结构和另一个表的结构一样,只是其中一张是临时表,而另一张表是存储数据的表,我们需要进行一次表的迁移的话,我们可以这样. insert in ...

随机推荐

  1. 初步掌握node的路由控制

    1.1.2:node.js的路由控制 1.运行原理 在1.1.1节中,提到过app.js中app.get("/",routes.index)可以用以下代码取代: app.get(& ...

  2. 动态规划法(五)钢条切割问题(rod cutting problem)

      继续讲故事~~   我们的主人公现在已经告别了生于斯,长于斯的故乡,来到了全国最大的城市S市.这座S市,位于国家的东南部,是全国的经济中心,工商业极为发达,是这个国家的人民所向往的城市.这个到处都 ...

  3. [转]JS实现千分位

    本文转自:https://www.cnblogs.com/lvmylife/p/8287247.html 方法一:正则实现 function format (num) { var reg=/\d{1, ...

  4. asp.net mvc 模型验证组件——FluentValidation

    asp.net mvc 模型验证组件——FluentValidation 示例 using FluentValidation; public class CustomerValidator: Abst ...

  5. MVC 【Razor 视图引擎】基础操作 --页面跳转,传值,表单提交

    ASPX  与  Razor  仅仅是视图不一样. 新建项目----ASP.NET MVC 4 Web 应用程序------选择模板(空).视图引擎(Razor ) 1.视图中 c# 代码  与 HT ...

  6. Net 如何计算一段代码的效率

    在.Net 4.0以后的版本,提供了一个类,该类在 System.Diagnostics命名空间下,使用该类就可以计算出执行结果相同的两端代码的效率,在代码优化上是很实用的. 泛型效率是高是低呢??我 ...

  7. 学Java的第17天。呃。。。今天有点奇葩

    神奇的老师在网上看到狗跳楼的视频然后就想到抛物线问题: 还是 属性和方法的调用: package sklx; public class Dog{ private float v = 30.0f; pr ...

  8. 【Tomcat】性能优化

    一.JVM优化 1.内存优化. 2.垃圾回收策略优化. 二.server.xml的connector优化(connector是与HTTP请求处理相关的容器,三个容器的初始化顺序为:Server-> ...

  9. JavaScript的值传递和引用传递

    译者按: 程序员应该知道递归,但是你真的知道是怎么回事么? 原文: All About Recursion, PTC, TCO and STC in JavaScript 译者: Fundebug 为 ...

  10. python爬虫入门---第一篇:获取某一网页所有超链接

    这是一个通过使用requests和BeautifulSoup库,简单爬取网站的所有超链接的小爬虫.有任何问题欢迎留言讨论. import requests from bs4 import Beauti ...