ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

致远OA V8.1数据字典详解:通讯录、代理、考勤表结构与SQL实战

致远OA V8.1数据字典详解:通讯录、代理、考勤表结构与SQL实战 简介致远OA V8.1数据字典是一份面向致远OA系统开发、实施及运维人员的技术参考文档主要用于梳理数据库核心表结构、字段类型与约束信息帮助理解系统底层数据设计解决二次开发、数据迁移和报表取数中的结构盲区。文件以单个PDF形式打包压缩后大小约2.2MB内容完整展现了通讯录ADDRESSBOOK等业务表的字段定义包括主键ID、人员MEMBER_ID、创建与修改日期以及EXT_ATTR系列扩展字段分别对应文本、数值、日期、枚举、选人、选部门和选岗位等类型配置规则清晰易查。该资源已有2604人学习浏览在OA实施与维护场景中具有较高的参考价值。通过这份数据字典读者可以快速定位常用业务模块的数据存储逻辑理解扩展字段的业务含义从而提升定制开发效率、降低误操作风险是从事致远OA相关工作的实用工具。1. 致远OA V8.1 数据字典一张通讯录表背后的十几个数据表接到一个二次开发需求让我把致远OA V8.1 的通讯录和考勤数据同步到第三方 HR 系统。对方直接丢来一串库表名我对着数据库一张张翻注释光确认表关系就折腾了一下午。后来拿到这份覆盖 V5 到 V8.1 的数据字典才发现通讯录根本不是一张表的事——主表之外还挂着成员表、设置表、范围表、个人组表考勤那边更夸张排班、班次、打卡明细、日统计分成了七八张表。这篇笔记就按我实际拆表的顺序把致远OA V8.1 数据字典里通讯录、代理、考勤、讨论这几个核心模块的表结构讲透字段怎么读、关联怎么走、查询怎么写、坑在哪一次说清。适合要做集成、写报表、排查数据不一致的开发和实施人员。2. 通讯录表族ADDRESSBOOK 四张主表与 70 个扩展字段2.1 主表 ADDRESSBOOK从 ID 到 MEMBER_ID 的流转先看通讯录核心表 ADDRESSBOOK。这份字典里表注释写的是“V5 数据字典”但表结构在 V8.1 里仍然沿用字段类型和注释基本没动。主表字段不多核心是 ID 和 MEMBER_ID 这两个字段的配合。ID 是 BIGINT 类型的主键强制必填负责唯一标识一条通讯录记录。MEMBER_ID 是人员 ID非必填指向组织人员表里的成员。CREATE_DATE 和 UPDATE_DATE 是创建、修改时间做增量同步时直接拿 UPDATE_DATE 当水位线就行不用去翻操作日志。这里有个细节值得注意ADDRESSBOOK 主表本身并不存联系人的姓名、手机号这些业务字段它更像一个“壳”真正的联系人信息在 ADDRESSBOOK_MEMBER 表里。拆字典的时候别被表名带偏ADDRESSBOOK 是通讯录实例表ADDRESSBOOK_MEMBER 才是联系人明细表。对照关系可以理解为一条通讯录记录在自己的容器里每个容器装若干个联系人成员。主表里最值得展开的是那组 EXT_ATTR 扩展字段一共 70 个分五段不同段对应不同类型。这块内容多单独放一节讲。SELECT ID, MEMBER_ID, CREATE_DATE, UPDATE_DATE FROM ADDRESSBOOK WHERE UPDATE_DATE :lastSyncTime ORDER BY UPDATE_DATE;这段 SQL 是同步任务的骨架。参数 lastSyncTime 是上次同步点位每次跑完把最大 UPDATE_DATE 存回去。MEMBER_ID 非空时用它关联人员表拿姓名、部门为空时说明这条通讯录记录没绑定人员可能是手工建的纯外部联系人处理逻辑要分开。实际项目里我用这个写法做增量抽取一开始没注意 MEMBER_ID 可空导致 JOIN 人员表时把空成员记录全丢了后来加了个 IS NULL 分支才补齐。2.2 EXT_ATTR_1 到 EXT_ATTR_70四种类型分段的自定义字段这是整个数据字典里最容易踩坑的地方。EXT_ATTR_1 到 EXT_ATTR_70 一共 70 个字段不是随便排的分成五个语义段字段区间数据类型业务含义EXT_ATTR_1 ~ EXT_ATTR_10VARCHAR(1024)文本扩展字段存长文本备注EXT_ATTR_11 ~ EXT_ATTR_20DECIMAL(19,4)数字扩展字段存数值型自定义项EXT_ATTR_21 ~ EXT_ATTR_30DATETIME日期扩展字段存时间点EXT_ATTR_31 ~ EXT_ATTR_40VARCHAR(50)枚举类型字段存代码值EXT_ATTR_41 ~ EXT_ATTR_50VARCHAR(50)选人类型字段存人员 IDEXT_ATTR_51 ~ EXT_ATTR_60VARCHAR(50)选部门类型字段存部门 IDEXT_ATTR_61 ~ EXT_ATTR_70VARCHAR(50)选岗位类型字段存岗位 ID为什么设计成这种分段因为在 OA 的表单引擎里管理员可以自定义表单字段而这些自定义值最终落库时就落在固定编号的 EXT_ATTR 上。字段编号和类型固定具体业务含义由单位自己的表单配置决定。比如某个单位在通讯录表单里加了一个“所属项目”文本框对应值就可能存在 EXT_ATTR_1 里另一个单位拿 EXT_ATTR_11 存“年度产值”类型刚好是 DECIMAL(19,4)。读字典的要点是先确认单位实际启用了哪些自定义字段再对应到具体的 EXT_ATTR 编号。单看数据字典只能拿到“第 31 到 40 个扩展字段是枚举类型”这层信息拿不到“枚举值 1 代表什么”后者得结合单位的表单配置或者去 OA 管理后台查。EXT_ATTR_31 到 EXT_ATTR_40 这几个枚举字段尤其要注意。它们是 VARCHAR(50)不是数字类型但存的是枚举代码值。查询时如果拿数字直接等值匹配数据库会做隐式转换多数情况下能查出结果但如果枚举值有前导零或者字母隐式转换就直接翻车。我习惯在查询里显式写字符串匹配SELECT ID, MEMBER_ID FROM ADDRESSBOOK WHERE EXT_ATTR_31 01 OR EXT_ATTR_31 A1;参数说明EXT_ATTR_31 是第一个枚举扩展字段值来自单位自定义配置。这里用字符串写法是为了避免隐式转换。如果你确认枚举值都是纯数字直接写 EXT_ATTR_31 1 也能跑但一旦出现字母或前导零就废了。稳妥起见全部按字符串处理。2.3 四张附属表怎么串SET、SCOPE、TEAM、MEMBER通讯录模块不止一张主表完整字典里有 ADDRESSBOOK、ADDRESSBOOK_MEMBER、ADDRESSBOOK_SET、ADDRESSBOOK_SET_SCOPE、ADDRESSBOOK_TEAM、ADDRESSBOOK_TEAM_MEMBERS 六张表。我刚拿到字典时也是一头雾水拆完之后关系其实很清楚。ADDRESSBOOK 是主表一个 ID 对应一条通讯录配置。ADDRESSBOOK_MEMBER 是成员表通过自身 ID 关联 ADDRESSBOOK 的 MEMBER_ID存联系人姓名、单位、电话、传真、邮箱这些具体字段。ADDRESSBOOK_SET 是设置表存查看范围、关键信息、导出打印权限这些配置其中 VIEW_SCOPE 字段控制谁能看到通讯录KEY_INFO_TYPE 字段控制手机号和职务级别的显示方式。ADDRESSBOOK_SET_SCOPE 是设置的关联表通过 ADDRESSBOOK_SET_ID 反查设置 IDUSER_ID 和 USER_TYPE 联动决定这条设置作用于哪个组织实体。ADDRESSBOOK_TEAM 和个人组有关。NAME 是组名TYPE 字段区分 0 系统组、1 个人组、2 私人通讯录CREATOR_ID 标识建组人。ADDRESSBOOK_TEAM_MEMBERS 是组和成员的关联表TEAM_ID 指向组MEMBER_ID 指向成员。一张个人组表加一张关联表典型的组-成员多对多设计。给个完整的关联查询写法SELECT m.NAME, m.COMPANY_NAME, m.MOBILEPHONE, t.NAME AS TEAM_NAME FROM ADDRESSBOOK_TEAM t JOIN ADDRESSBOOK_TEAM_MEMBERS tm ON t.ID tm.TEAM_ID JOIN ADDRESSBOOK_MEMBER m ON tm.MEMBER_ID m.ID WHERE t.CREATOR_ID :userId AND t.TYPE 1;这段 SQL 查某个人建的所有个人组及其成员。TYPE 1 过滤出个人组避开系统组和私人通讯录。逻辑说明先拿 TEAM 表定位组再用 TEAM_MEMBERS 桥表把组和成员关联起来最后去 MEMBER 表取联系人字段。参数 :userId 是当前登录人的 ID做数据权限控制时直接拼这个条件。实际业务里个人组常被用来做审批流里的常用联系人分组查这个表能还原用户的分组习惯。3. 代理与考勤AGENT 和 ATTENDANCE 表族怎么读3.1 AGENT 代理表双人双单位的字段设计代理设置是 OA 里一个高频次要功能但字典里字段读起来有点绕。AGENT 表核心是“谁代理谁、什么时候代理、代理什么”。AGENT_ID 是代理人 IDAGENT_TO_ID 是被代理人 ID两个字段都是 BIGINT没有前缀区分第一次看时很容易搞反。CREATE_DATE 是代理信息创建时间START_DATE 和 END_DATE 是代理期限起止CANCEL_DATE 是取消时间。关键在几个状态字段。CANCEL_FLAG 是取消标记0 未取消1 已取消。AGENT_TYPE 是代理类型1 代理设置2 离职交接。AGENT_OPERATION 是操作类型0 被代理人自己1 集团管理员2 单位管理员。MATTER_TYPE 是事项条件设置类型0 按处理人设置1 按发起人设置。这里有个细节字典注释里写“默认值为 1”不是 0。还有 AGENT_OPTION 字段存代理选项VARCHAR(50) 类型但没有展开具体取值。HAS_AWAKE 字段注释直接写了“未使用”说明这个字段是历史遗留。实际查询代理关系时最常见的需求是“某个人当前生效的代理”。注意这里有个坑代理记录不是一条就完同一个被代理人可能被多个人分批代理也可能代理结束后又来一条新的。判断生效状态的正确姿势是查 CANCEL_FLAG 0 AND START_DATE 当前时间 AND END_DATE 当前时间不能只看有没有记录SELECT a.AGENT_ID, a.AGENT_TO_ID, a.START_DATE, a.END_DATE, u.NAME AS AGENT_NAME FROM AGENT a LEFT JOIN ORG_USER u ON a.AGENT_ID u.ID WHERE a.AGENT_TO_ID :targetUserId AND a.CANCEL_FLAG 0 AND a.START_DATE NOW() AND a.END_DATE NOW();参数 :targetUserId 是需要查询的被代理人 ID。这段 SQL 的核心是把取消的和未生效的全滤掉只留当前生效的代理关系。逻辑说明先按被代理人过滤再查取消标记和时间窗口。如果 OA 版本里 START_DATE 存的是空值说明代理设置没限制开始时间这时时间条件要改成写成可空判断我在项目里遇到过一次某条代理记录 START_DATE 是 NULL导致这条代理永远查不出来后来把时间条件拆成 IS NULL OR 判断才恢复。AGENT_DETAIL 表是代理明细AGENT_ID 关联主表APP 存应用编号ENTITY_ID 存实体 ID。用于控制代理人在哪些应用模块生效。AGENT_SCOPE 表存发起人范围IDENTITY_TYPE 和 ENTITY_ID 配合指定代理设置只对哪些组织范围内的发起人生效。比如集团管理员设代理时可以选择只对某个子公司的人生效范围就落在这张表里。3.2 ATTENDANCE 考勤表族从 HISTORY 到 DAY_STATISTICS考勤模块是致远OA 表最多的模块之一整个字典里排到 ATTENDANCE_TEAM得有十几张。按用途分组考勤组与排班ATTENDANCE_TEAM 是考勤组ATTENDANCE_ARRANGE 是排班ATTENDANCE_CLASS 是班次ATTENDANCE_DAY 是某天对应哪个班次。考勤组是顶层容器排班挂在考勤组下面班次挂在排班下面DAY 表再排具体星期几上什么班。打卡记录ATTENDANCE_HISTORY 和 ATTENDANCE_INFO两张结构很像细节不同。HISTORY 的 SIGN 字段是 VARCHAR(500)INFO 的 SIGN 是 VARCHAR(2000)。两张表都存打卡人员、部门、时间、定位信息、地址详情、图片数量、语音数量。INFO 表额外有 MAC_ADDRESS、DEVICE_INFO、PUNCH_TYPE、STATE 这些字段STATE 字段直接标了考勤结果3 上班迟到、4 下班早退、5 正常上班、6 正常下班。统计表ATTENDANCE_DAY_STATISTICS 是核心统计出口按人按天一条记录AM_START_TIME 上午签到时间、AM_END_TIME 上午签退时间、PM_START_TIME 下午签到时间、PM_END_TIME 下午签退时间还有对应的四个状态字段 AM_START_STATE、AM_END_STATE、PM_START_STATE、PM_END_STATE。NORMAL_DAY 出勤天数、AB_NORMAL_DAY 异常天数、LATE_NUM 迟到次数、LEAVE_EARLY_NUM 早退次数、OUTSIDE_NUM 外勤次数、MISSINGCLOCK_COUNT 缺卡总数。这是一张宽表设计目的就是让报表直接查它不用再去逐条打卡记录里数。实际做考勤统计导出时优先用这张表别去 HISTORY 表做聚合效率差距明显。ATTENDANCE_SETTING 表是打卡范围设置存围栏信息LONGITUDE、LATITUDE、ATTEND_RANGE 三个字段配合定义了一个地理围栏AVAILABLE 控制是否启用。这个围栏和考勤组的管理是分开的考勤组管理员后台画围栏考勤规则判断时再加载。做定位打卡功能时判断逻辑是先找到人员所属考勤组再查考勤组的 ATTENDANCE_SETTING 围栏最后算距离注意不同考勤组可能复用同一个围栏配置别按组 ID 直接绑定。3.3 表之间的关联字段考勤表族里关联字段的命名不算统一拆表时得靠注释辅助。ATTENDANCE_ARRANGE 有 ATTENDANCE_TEAM_ID 关联考勤组ATTENDANCE_CLASS 有 ATTENDANCE_ARRANGE_ID 关联排班ATTENDANCE_DAY 同时有 ATTENDANCE_ARRANGE_ID 和 ATTENDANCE_CLASS_ID锁定某一天具体哪个班次。打卡明细 HISTORY 和 INFO 表里有 TEAM_ID 和 RULE_ID直接关联考勤组和规则省了一层 JOIN——这也解释了为什么表结构看着冗余。日统计表 ATTENDANCE_DAY_STATISTICS 里 ACCOUNT_ID、DEPT_ID、TEAM_ID、RULE_ID、MEMBER_ID 五件套齐全一个人员一条记录全带齐。这里有个容易搞混的点TEAM_ID 是考勤组 ID不是团队 ID名字容易让人联想到业务团队。还有一张 ATTENDANCE_FIX_TIME 表存班级的上下班时间段WORK_TIME 上班时间、END_TIME 下班时间、EARLY_WORK_TIME 最早签到时间、LAST_END_TIME 最晚签退时间ATTEND_REMIND 和 LEAVE_REMIND 是上班下班提醒开关。考勤提醒功能的数据源就是这张表跟 ATTENDANCE_REMIND 表配合使用前者存时间点后者存提醒策略。4. 数据字典实战不碰库也能把查询 SQL 写对拿到数据字典最直接的价值就是连通数据库之前SQL 就能先写对。字段名、类型、含义、关联关系全在字典里照着一个字段一个字段拼就行。4.1 从注释反推查询 SQL以考勤日统计为例考勤日统计报表是我做过的 OA 集成里最常见的需求。管理人员要一张表某天哪些人迟到、哪些人缺卡。字典里 ATTENDANCE_DAY_STATISTICS 的字段注释直接给出了答案。SELECT m.NAME, d.PUNCH_DATE, d.AM_START_TIME, d.AM_START_STATE, d.PM_END_TIME, d.PM_END_STATE, d.LATE_NUM, d.MISSINGCLOCK_COUNT FROM ATTENDANCE_DAY_STATISTICS d LEFT JOIN ORG_MEMBER m ON d.MEMBER_ID m.ID WHERE d.PUNCH_DATE :targetDate AND d.AB_NORMAL_DAY 0 ORDER BY d.LATE_NUM DESC;逻辑说明先过滤指定考勤日再筛异常天数大于 0 的记录就是当天有问题的所有人。AM_START_STATE 等于 3 表示上班迟到PM_END_STATE 等于 4 表示下班早退。注意状态字段的值是字典注释里写明的3 上班迟到、4 下班早退、5 正常上班、6 正常下班。实际做报表时候我会再加一个 CASE WHEN 把状态码翻译成可读文案避免业务人员看到数字一头雾水。这里有个细节PUNCH_DATE 和字段名又有一个 DATE 结尾但它是 DATETIME 类型存的是考勤日零点。直接用等于号匹配日期时如果库里存的是 2025-06-01 00:00:00用 2025-06-01 匹配没问题但如果某些考勤记录存成了 2025-06-01 08:30:00等于号就查不到。稳妥写法是 BETWEEN 2025-06-01 00:00:00 AND 2025-06-01 23:59:59这个坑我在写月度统计时踩过查出来缺了五六条记录。4.2 用字段口径做核对HISTORY 与 INFO 的差别处理字典里有两张打卡明细表 ATTENDANCE_HISTORY 和 ATTENDANCE_INFO字段大部分重叠但几个关键差异决定了对账逻辑怎么走。最典型的是 SIGN 字段长度HISTORY 是 VARCHAR(500)INFO 是 VARCHAR(2000)。SIGN 字段注释是“打卡(地址/ip)”实际存储时可能是一长串拼接的定位信息包含经纬度坐标、地图地址文本。从 HISTORY 往外部系统同步时如果目标字段长度只有 500长地址会被截断导致地图上点位偏移。比对两张表时还要注意INFO 表多了 MODIFY_NUM 签到修改次数、DEVICE_INFO 设备信息、STATE 打卡状态、MAC_ADDRESS Wi-Fi 地址。这说明 INFO 表是“修正后”的明细HISTORY 是“原始”记录。对账时以 INFO 表为准只用 HISTORY 做痕迹追溯。数据不一致时优先怀疑设备端打卡后修改过或系统有补卡流程。4.3 字典字段快速转查询清单数据字典拆到后期我会把高频字段整理成一张速查表贴在项目文档里。这里给一张我常用的精简版业务场景表名关键字段查询要点通讯录同步ADDRESSBOOKUPDATE_DATE增量水位线个人组查询ADDRESSBOOK_TEAMTYPETYPE1 个人组0 系统组代理生效判断AGENTCANCEL_FLAG, START_DATE, END_DATE三个条件同时满足考勤日统计ATTENDANCE_DAY_STATISTICSPUNCH_DATE, STATE 系列状态码先翻译再展示围栏设置ATTENDANCE_SETTINGLONGITUDE, LATITUDE, ATTEND_RANGE经纬度范围半径讨论主题BBS_ARTICLETOP_SEQUENCE, ELITE_FLAG置顶和精华分开查这张表不是字典的替代品是在字典基础上按业务提炼的瘦身版。实际开发时先看这张表定位到目标表和字段再回到详细字典里确认类型与约束。5. 避坑与排查通讯录、代理、考勤字段的五个典型坑5.1 扩展字段“同名不同型”现象在 OA 后台维护的表单数据同步到第三方系统时部分字段值丢了。原因EXT_ATTR_1 到 EXT_ATTR_70 虽然都叫“扩展字段”但类型跨度极大。EXT_ATTR_1 是 VARCHAR(1024) 能存长文本EXT_ATTR_31 是 VARCHAR(50) 存枚举代码EXT_ATTR_11 是 DECIMAL(19,4) 存数值。如果同步逻辑把整个 EXT_ATTR 段当成文本统一处理数字和日期字段会被强转或截断。解决写同步前先把单位启用的自定义字段编号梳理出来按编号分组处理。文本段直接映射数字段用 CAST 转数值枚举段先映射代码值再显示日期段统一格式化成目标系统要求的字符串。做的时候花半小时列一个字段映射表后面能省大量返工。5.2 打卡地址字段长度不一致现象从 ATTENDANCE_HISTORY 同步打卡地址到外部系统地址后半截丢失地图上显示的点发生偏移。原因HISTORY 表的 SIGN 字段是 VARCHAR(500)INFO 表的 SIGN 是 VARCHAR(2000)。有些长地址或复杂拼接的定位串超过了 500 字就被截断。解决优先从 ATTENDANCE_INFO 读取打卡地址长度余量充足。如果只能读 HISTORY同步前用 LEFT(SIGN, 500) 截断并记录告警日志。类似的情况还可能出现在 RECEIVE_ID 这种 TEXT 类型的字段上建议先测一条最大长度记录再定目标表字段。5.3 代理取消标记与代理类型混用现象查某人的代理关系时发现已取消的代理也在结果里还带出了离职交接的记录。原因判断生效状态只看了 AGENT_TYPE没看 CANCEL_FLAG。AGENT_TYPE 2 是离职交接Type 1 是普通代理两者共用 AGENT 表。离职交接的记录如果没有单独清理流程CANCEL_FLAG 长时间保持 0就会伪装成有效代理。解决查询条件里强制加 CANCEL_FLAG 0并且按场景过滤 AGENT_TYPE。查普通代理就 WHERE AGENT_TYPE 1查交接记录再单独处理。5.4 事项条件设置的默认值现象读取 AGENT 表的 MATTER_TYPE 字段按字典误解“0 按处理人设置”处理结果导出的数据全是按发起人。原因字典注释在 MATTER_TYPE 后面明确标注了“默认值为 1”即新建记录默认按发起人设置。很多解析逻辑把默认值当 0 处理导致语义反转。解决先看注释里的默认值标注。写 SQL 时显式写 MATTER_TYPE 0 或 1不要依赖默认值。数据清洗阶段把 NULL 统一回填为 1避免下游逻辑误判。5.5 考勤状态码与天数字段的关系现象考勤日报显示异常天数但明细里没有状态码对应的记录。原因ATTENDANCE_DAY_STATISTICS 的 NORMAL_DAY 和 AB_NORMAL_DAY 是聚合结果汇总时可能把缺卡、外勤、迟到分别计数。AB_NORMAL_DAY 0 的记录在明细 STATE 字段里可能只有“缺卡”没有“迟到”两者维度不一致。解决报表逻辑先看聚合字段判断有没有异常再看明细字段定位异常类型。别拿聚合结果去反推具体某次打卡状态也别拿明细状态去重新合计聚合值。两者对不上时优先以日统计表为准排查口径差异确认是否包含补卡审批流。6. 数据字典的进阶用法把静态文档变成选型与排错工具数据字典最容易被低估的用途是拿它做功能边界判断。有一次客户问能不能在移动端做“考勤地点围栏外禁止打卡”我没急着回需求而是先翻了 ATTENDANCE_SETTING 表和 ATTENDANCE_INFO 表字段。ATTENDANCE_SETTING 表有 LONGITUDE、LATITUDE、ATTEND_RANGE 和 AVAILABLE 字段说明原生是支持围栏配置的。在 REAL 场景里这个能力对应的就是打卡时校验经纬度和半径。但如果要“禁止”还要看打卡写入流程里是否校验了 AVAILABLE 和距离这就不是看字段能确定的得看代码逻辑。还有一次排查通讯录看不到人按数据字典把 ADDRESSBOOK_SET 的 VIEW_SCOPE、KEY_INFO_TYPE 和 ADDRESSBOOK_SET_SCOPE 的 USER_ID 串起来一查发现是管理员的查看范围配置成“仅本人”导致下属单位人员全部不可见。修复只需改 SET 表里 VIEW_SCOPE 的枚举值为单位范围。那次排查我没动一行代码只写了三条 SELECT 就定位了根因字典的价值就体现在这种时刻。从那以后我每次做 OA 集成都会强制走一遍这个流程先按字典把表关系画成简图再对照关键字段写一条最小可用的验证 SQL跑通后再扩展业务逻辑。如果字段语义拿不准宁可先查库确认也不猜。希望帮到你。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进