目录

诉求SDEOBJECTIDArcMap编辑重置OBJECTID

诉求

非GIS专业的人员可能很难理解ArcSDE中的表OBJECTID的重要性,要么总想着自己动手去维护,要么就想直接忽略它,导致总会出现OBJECTID的冲突,编辑数据报错

下面简单谈谈对OBJECTID的粗浅认识,抛砖引玉,帮助更多人理解它的内部机制

SDE

ArcGIS家的ArcSDE空间数据库引擎,官方定义去官网,那里有很多,但个人感觉像机翻的,读起来很拗口。SDE就是在数据库中添加一个中间件,这样可以存储和管理空间数据,虽然很多数据库像oracle,mysql,sqlserver等都有自家的管理空间数据策略,但和ArcGIS互通方面差一些,想利用ArcGIS强大的生态,所以会考虑使用ArcSDE中间件,如果是ArcGIS的老手,其实对此也无所谓。空间数据库的本质就是定义了一套操作和管理空间数据的数据模型,就像文本数据类型,数据库定义了对它的分割、合并、拼接、转换等。只是空间数据会复杂些,空间关系运算存储等要费事的多。

表面上的体现就是安装了ArcSDE中间件后,会有一个SDE用户,这个用户下就包含对空间数据模型的定义、维护管理,里面有很多管理表、注册表、工具函数等。

OBJECTID

ArcGIS管理的数据表中OBJECTID是一个唯一主键标识,并且与一个序列Sequence对应,(可以理解序列就是一个由初始值,步长,最大值的递增函数),每新增一条数据,序列就会按步长递增生成序号。往往不需要你手动干预,除非你没按人家规则,人为破坏生成机制。

比如有时候我们需要通过SQL插入一条数据,那么OBJECTID是非空,你需要从序列中获取。表的OBJECTID和序列的对应可以在SDE用户下的TABLE_REGISTRY找到,像下面这样

select t.registration_id  from  SDE.TABLE_REGISTRY t where Owner='yourowner' and Table_Name='yourtablename';

或者直接调用sde.gdb_util.next_rowid,它会调用序列得到nextValue的。

但事情往往没有那么简单

ArcMap编辑

我们在用ArcMap编辑SDE中空间数据时,像新增,如果直接从序列中获取,那多用户下就会有锁定。

我们看下sde.gdb_util.next_rowid方法的源码

    owner_l := UPPER(owner_in);
    L_table_name(owner_in,table_in,table_l);
    p_name := UPPER(owner_in||'.'||table_l);     stmt := 'SELECT registration_id FROM SDE.table_registry '||
            'WHERE owner = :owner_l AND table_name = :table_l';     OPEN C_gdb FOR stmt USING owner_l,table_l;
    FETCH C_gdb INTO reg_id;
    IF C_gdb%NOTFOUND THEN
      raise_application_error(SDE.sde_util.SE_TABLE_NOREGISTERED,                               'Class '||p_name||' not registered to the Geodatabase.');
    End If;
    CLOSE C_gdb;     s_value := SDE.version_user_ddl.next_row_id (owner_l,reg_id);
    return(s_value);

SDE.version_user_ddl.next_row_id的主要源码片段如下,感兴趣的可以研究下

   BEGIN

      --  See if there are any ids for this table in its pipe.

      pipe_name := 'ArcSDE_IdPipe' || TO_CHAR (registration_id);
      pipe_result := DBMS_PIPE.RECEIVE_MESSAGE (pipe_name,0);        IF pipe_result = 0 THEN          -- Found ids in the pipe, read them.          DBMS_PIPE.UNPACK_MESSAGE (id_start);
         DBMS_PIPE.UNPACK_MESSAGE (id_count);
         next_id := id_start;
         id_start := id_start + 1;
         id_count := id_count - 1;       ELSE          -- Fetch ids from the sequence.  Also get the sequence's
         -- increment by value so we know how many ids we actually got.          sequence_name := 'R' || TO_CHAR (registration_id);          select_statement := 'SELECT ' || TO_CHAR(owner) || '.' || sequence_name ||
                             '.NEXTVAL FROM DUAL';
         BEGIN
            EXECUTE IMMEDIATE select_statement INTO  next_id;
         EXCEPTION
            WHEN OTHERS THEN
               raise_application_error (sde_util.SE_NO_SDE_ROWID_COLUMN,
                                        'Unable to find or access sequence ' ||
                                        owner || '.r' || 
                                        TO_CHAR (registration_id));
         END;          OPEN increment_by_cursor (owner,sequence_name);
         FETCH increment_by_cursor INTO increment_by;
         CLOSE increment_by_cursor;          id_start := next_id + 1;
         id_count := increment_by - 1;       END IF;       -- Write any remaining ids back into the pipe.       IF id_count > 0 THEN
         DBMS_PIPE.RESET_BUFFER;
         DBMS_PIPE.PACK_MESSAGE (id_start);
         DBMS_PIPE.PACK_MESSAGE (id_count);
         pipe_result := DBMS_PIPE.SEND_MESSAGE (pipe_name,4);
      END IF;       -- Return the id we found.       RETURN next_id;    END next_row_id;

上面主要做了两件事情,首先我们sde.gdb_util.next_rowid时不是想象中的从R序列中直接获取,而是先去一个特定管道ArcSDE_IdPipe+表序列名中拿,没有再从R序列中获取,并一次取步长的范围。所以有时候会事与愿违的发现得到的nextValue和想象中的不一样。当管道中没有值时才去序列获取。有时候OBJECTID已经错乱(新增报错OBJECTID重复),我们只调整序列的当前值不足以解决问题,管道中获取的值可能还是小于序列值的,可能导致后面还是重复。所以建议更新时,先清空管道,让第一次读取就从序列中读取。

管道用于多会话之间传递信息。

重置OBJECTID

如果OBJECTID已经错乱,如果正确重置?我们甚至遇到过,当查看oracle中OBJECTID类型是INT,INT最大数才2147483648,实际里面竟然存储却远大于这个数。查阅oracle文档会发现,底层oracle存储int是映射到number的,所以范围会大很多。但这也给我们提了醒,OBJECTID自然增长怎么会增长到远超2147483648,我们一般不会在一个表里放几十亿,几百亿的数据量吧。这可能就是乱用或忽略OBJECTID生成策略带来的小坑。

基于以上的解读,重置OBJECTID的基本流程应该是:清空管道,更新OBJECTID,更新序列。在oracle中写了一个存储过程以供参考,源码如下:

年纪大了,记性不好,记录一下,方便查阅

刚说什么来着?emmmmmm,对,源码

create or replace procedure P_ResetObjectID(owner in NVARCHAR2, tablename in NVARCHAR2)
is
/*
重置sde table objectID
*/
reg_id         pls_integer;
owner_l        VARCHAR2(64);
table_l        VARCHAR2(64);
pipe_name         VARCHAR2(30);
max_id           NUMBER;
stmt           varchar2(512);
sequence_name     VARCHAR2(64);
begin
    owner_l := UPPER(owner);
    table_l := UPPER(tablename);     stmt := 'SELECT registration_id FROM SDE.table_registry '||
            'WHERE owner ='''|| owner_l ||''' AND table_name = '''|| table_l ||'''';
    EXECUTE IMMEDIATE stmt INTO  reg_id;
    if reg_id is null then return;
    end if;
    pipe_name := 'ArcSDE_IdPipe' || TO_CHAR (reg_id);
    --清除arcgis缓存管道
    stmt := 'select sys.dbms_pipe.remove_pipe('''||pipe_name||''') from dual ';
    EXECUTE IMMEDIATE stmt;
    --更新oid
    stmt := 'update '||table_l||' set objectid=rownum ';
    EXECUTE IMMEDIATE stmt;
    --获取最大oid
    stmt := 'select max(objectid)  from '||table_l;
    EXECUTE IMMEDIATE stmt INTO  max_id;
    if max_id is NULL then return;
    end if;
    --修改序列的当前值
    sequence_name := 'R' || TO_CHAR (reg_id);
    stmt := 'drop  sequence '||sequence_name||' ';
    EXECUTE IMMEDIATE stmt;
    stmt := 'create sequence '||sequence_name||' minvalue 1 maxvalue 2147483647 start with '||max_id||' increment by 16 cache 20';
    EXECUTE IMMEDIATE stmt;
    stmt := 'grant select on '||owner_l||'.'||sequence_name||' to public';
    EXECUTE IMMEDIATE stmt;
end P_ResetObjectID;

手机在手边,可关注vx:xishaobb,互动或获取更多信息,欢迎交流指正,当然这里也一直更新de,有缘见,拜了个拜拜

关于ArcGIS的OBJECTID生成策略拙见的更多相关文章

  1. 可实现的全局唯一有序ID生成策略

    在博客园搜素全局唯一有序ID,罗列出来的文章大致讲述了以下几个问题,常见的生成全局唯一id的常见方法 :使用数据库自动增长序列实现 : 使用UUID实现:  使用redis实现: 使用Twitter的 ...

  2. Hibernate(4)——主键生成策略、CRUD 基础API区别的总结 和 注解的使用

    俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及的知识点总结如下: hibernate的主键生成策略 UUID 配置的补充:hbm2ddl.auto属性用法 注解还是配置文件 h ...

  3. hibernate主键生成策略

    在hibernate中,提供了多种主键生成器(不同的数据库,不同的表结构使用的主键生成策略也不相同),查阅相关资料经过实验总结如下: 1.increment 主键按照数值顺序递增,使用当前实例中最大值 ...

  4. Hibernate 表映射 主键生成策略与复合主键

    主要分析三点: 一.数据表和Java类的映射 : 二.单一主键映射和主键的生成策略 : 三.复合主键的表映射 : 一.数据表和Java类的映射  Hibernate封装了数据库DDL语句,只需要将数据 ...

  5. Hibernate主键生成策略(转)

    1.自动增长identity 适用于MySQL.DB2.MS SQL  Server,采用数据库生成的主键,用于为long.short.int类型生成唯一标识 使用SQL Server 和 MySQL ...

  6. id生成策略 id工具类

    import java.util.Random; /** * 各种id生成策略 * <p>Title: IDUtils</p> * <p>Description: ...

  7. hibernate 注解 主键生成策略

    一.JPA通用策略生成器       通过annotation来映射hibernate实体的,基于annotation的hibernate主键标识为@Id, 其生成规则由@GeneratedValue ...

  8. hibernate(四)ID生成策略

    一.ID生成策略配置 1.ID生成方式在xml中配置方式: <?xml version="1.0"?> <!DOCTYPE hibernate-mapping P ...

  9. 大家一起撸代码之——Hibernate各种主键生成策略与配置详解

    1.assigned 主键由外部程序负责生成,在 save() 之前必须指定一个.Hibernate不负责维护主键生成.与Hibernate和底层数据库都无关,可以跨数据库.在存储对象前,必须要使用主 ...

随机推荐

  1. ArchLinux安(重)装指南

    说实话,我其实是不想要出这篇博客的.在我这一个月安装Arch的过程中,让我感触比较深的一点是: 没有谁比这个系统的官方更懂它. 尤其是这种比较复杂的系统,更是如此. 这几天,我经历了一次重装,系统坏了 ...

  2. golang学习之路

    目录 go语言介绍 开发环境准备 go语言基础 Go语言常用标准库 数据库相关 前端相关 web开发 go语言介绍 为什么要学习go语言 开发环境准备 从零开始搭建Go语言开发环境 VS Code配置 ...

  3. 地图的标注Marker

    (1)在point处添加标注:var marker = new BMap.Marker(point); (2)添加覆盖物:map.addOverlay(marker); (3)激活标注的拖拽功能:ma ...

  4. Spring Boot 2.X(三):使用 Spring MVC + MyBatis + Thymeleaf 开发 web 应用

    前言 Spring MVC 是构建在 Servlet API 上的原生框架,并从一开始就包含在 Spring 框架中.本文主要通过简述 Spring MVC 的架构及分析,并用 Spring Boot ...

  5. 网页布局——Flex弹性框布局

    布局的传统解决方案,基于盒状模型,依赖 display 属性 + position属性 + float属性.它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现. 需要安卓4.4及以上版本可以使用 ...

  6. Ubuntu安装Chrome浏览器及解决启动no-sandbox问题

    1.安装浏览器 # apt-get install gonme # apt-get update # apt-get install google-chrome-stable 2.启动Chrome浏览 ...

  7. 安装Elasticsearch可视化插件

    背景 项目中使用Elasticsearch , 最开始14年使用的时候需要es自己安装插件才能通过web页面查看数据情况,目前新版本的ES安装插件很费劲,通过搜索发现目前谷歌浏览器就有这个插件,这里简 ...

  8. Mac上Charles抓包iOS的https请求

    介绍一款抓包工具,一般我在windows下使用Fiddler抓包,Fiddler使用教程这里就不讲了,重点介绍使用mac时的抓包工具----Charles. 进入官网 :Charles官网地址官网下载 ...

  9. 【Java必修课】一图说尽排序,一文细说Sorting(Array、List、Stream的排序)

    简说排序 排序是极其常见的使用场景,因为在生活中就有很多这样的实例.国家GDP排名.奥运奖牌排名.明星粉丝排名等,各大排行榜,给人的既是动力,也是压力. 而讲到排序,就会有各种排序算法和相关实现,本文 ...

  10. Windows系统调用中的现场保存

    Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html Windows系统调用中的现场保存 我们之前介绍过三环进零环的步骤 ...