简介:致远OA V8.1 数据字典是面向致远OA二次开发、系统集成与数据库运维人员的基础参考文档,用于快速查阅系统底层表结构与字段定义,解决开发中字段含义不明、扩展字段用途不清等问题。资源包共1个PDF文件,约2.2MB,内容以表格形式系统整理各数据表信息,涵盖字段名称、数据类型、是否强制及注释说明,便于检索与对照。文档以ADDRESSBOOK通讯录表为例,详细列出主键ID、人员ID、创建与修改时间,以及文本、数字、日期、枚举、选人、选部门、选岗位等各类扩展字段的类型与用途,并延伸至ADDRESSBOOK_MEMBER等关联表,帮助读者理解联系人数据的组织方式。目前已有2606人学习下载,适合需要梳理致远OA数据库架构、编写SQL或排查数据问题的开发者参考,也可作为系统升级与维护时的结构对照依据。
1. 致远OA V8.1 数据字典:一份能让你少加三天班的表结构底稿
接手一套已经跑了三五年的致远OA V8.1,最怕的不是代码看不懂,而是数据库里那几百张表像黑匣子一样横在面前。业务方说“通讯录里那个扩展字段怎么不显示”,运维说“考勤统计对不上”,你打开数据库一看,ADDRESSBOOK 表里 EXT_ATTR_1 到 EXT_ATTR_70 排得整整齐齐,可哪个字段对应哪个业务含义,全靠猜。这份 V8.1 数据字典就是干这个用的——它把通讯录、代理、考勤、讨论区这几个核心模块的表结构、字段类型、是否必填、字段注释全部摊开,让你不用再对着建表语句一行行反推。适合谁?做致远二次开发的、接运维工单的、准备做数据迁移或报表对接的,以及被“字段含义不明”坑过的后端。它不是官方手册的替代品,而是一份能直接贴进 IDE 当注释用的速查底稿。
2. 通讯录模块拆解:ADDRESSBOOK 的 70 个扩展字段怎么读
通讯录是致远里被改得最狠的模块之一,因为每个单位的组织架构和人员信息维度都不一样。V8.1 把扩展能力全压在 ADDRESSBOOK 这张主表上,70 个 EXT_ATTR 字段按类型分成了五组,不先搞清楚分组逻辑,查数据就是大海捞针。
2.1 五组扩展字段的类型划分与业务映射
先看字段命名规律。EXT_ATTR_1 到 EXT_ATTR_10 是 VARCHAR(1024),文本类型,适合存备注、标签、自定义描述这类不定长内容。EXT_ATTR_11 到 EXT_ATTR_20 是 DECIMAL(19,4),数字类型,精度到小数点后四位,用来存金额、评分、工时都够用。EXT_ATTR_21 到 EXT_ATTR_30 是 DATETIME,日期类型,记录自定义的时间节点。EXT_ATTR_31 到 EXT_ATTR_40 是 VARCHAR(50),枚举类型,存的是字典编码或状态值。EXT_ATTR_41 到 EXT_ATTR_70 全是 VARCHAR(50),但注释里明确写了选人、选部门、选岗位三类,每类十个字段,存的是对应组织模型实体的 ID。
这个分组不是随便定的。文本和数字字段直接存值,枚举字段存编码,选人/选部门/选岗位字段存的是外键 ID。如果你在报表里直接查 EXT_ATTR_41 想拿到人名,那肯定拿不到,得 JOIN 组织模型表。常见做法是先把字段分组和业务含义的对应关系整理成一张映射表,再写查询。
-- 查看 ADDRESSBOOK 表结构,确认扩展字段的实际类型 SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, IS_NULLABLE, COLUMN_COMMENT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'ADDRESSBOOK' AND COLUMN_NAME LIKE 'EXT_ATTR%' ORDER BY CAST(SUBSTRING(COLUMN_NAME, 10) AS UNSIGNED);这段 SQL 在 MySQL 环境下跑,能一次性把 70 个扩展字段的类型、长度、是否可空、注释全拉出来。参数说明:SUBSTRING(COLUMN_NAME, 10) 是从 EXT_ATTR_ 后面截取数字部分,用来按字段序号排序,不然默认按字母序排会乱。IS_NULLABLE 全是 FALSE 说明这些字段虽然业务上可空,但建表时没设 NOT NULL,插入数据时给 NULL 不会报错,但查询时要注意 NULL 值的处理。
2.2 主表与 ADDRESSBOOK_MEMBER 的关联查询写法
ADDRESSBOOK 存的是通讯录条目的基础信息,ADDRESSBOOK_MEMBER 存的是外部联系人的详细信息。两张表通过 MEMBER_ID 关联,但注意 ADDRESSBOOK_MEMBER 的主键是 ID,不是 MEMBER_ID。实际查询时,ADDRESSBOOK 的 MEMBER_ID 指向 ADDRESSBOOK_MEMBER 的 ID。
-- 查询通讯录条目及其外部联系人详情 SELECT a.ID AS addressbook_id, a.MEMBER_ID, m.NAME AS member_name, m.COMPANY_NAME, m.MOBILEPHONE, m.EMAIL, a.CREATE_DATE, a.UPDATE_DATE FROM ADDRESSBOOK a LEFT JOIN ADDRESSBOOK_MEMBER m ON a.MEMBER_ID = m.ID WHERE a.TYPE = '1' -- TYPE 字段区分通讯录类型 ORDER BY a.UPDATE_DATE DESC;逻辑说明:用 LEFT JOIN 是因为 ADDRESSBOOK 里可能存的是内部人员,MEMBER_ID 不一定对应外部联系人表。TYPE 字段在字典里只写了“I”,实际业务中通常用数字或字符区分内部/外部,具体值需要结合 ADDRESSBOOK_SET 表的配置来看。参数上,ORDER BY a.UPDATE_DATE DESC 能快速定位最近修改的条目,排查数据问题时很实用。
注意:ADDRESSBOOK_MEMBER 的 CREATOR_ID 和 CREATOR_NAME 都是 TRUE,也就是必填。如果通过接口写入数据,这两个字段必须传,否则会报约束错误。
2.3 ADDRESSBOOK_SET 与 ADDRESSBOOK_SET_SCOPE 的权限配置逻辑
通讯录的查看范围、关键信息、导出打印权限全在 ADDRESSBOOK_SET 表里控制。VIEW_SCOPE 是 SMALLINT,KEY_INFO 也是 SMALLINT,KEY_INFO_TYPE 用 1、2、3 区分手机号+职务级别、仅手机号、仅职务级别。EXTERNAL_SCOPE 控制编外人员权限,1 是按工作范围显示,2 是全部隐藏。
ADDRESSBOOK_SET_SCOPE 是权限范围的具体存储表。ADDRESSBOOK_SET_TYPE 区分设置类型:1 是查看范围,2 是关键信息,3 是导出与打印权限。USER_ID 和 USER_TYPE 组合起来指向组织模型里的实体。
-- 查询某个单位的通讯录查看范围配置 SELECT s.ID AS set_id, s.VIEW_SCOPE, s.KEY_INFO, s.KEY_INFO_TYPE, sc.USER_ID, sc.USER_TYPE, sc.ADDRESSBOOK_SET_TYPE FROM ADDRESSBOOK_SET s JOIN ADDRESSBOOK_SET_SCOPE sc ON s.ID = sc.ADDRESSBOOK_SET_ID WHERE s.ACCOUNT_ID = ? -- 传入单位 ID AND sc.ADDRESSBOOK_SET_TYPE = 1;参数说明:ACCOUNT_ID 是单位 ID,在致远里通常对应组织模型中的单位实体。USER_TYPE 存的是组织模型实体类型,常见值有 ACCOUNT、DEPARTMENT、POST 等。如果查出来的范围不对,先确认 ADDRESSBOOK_SET_SCOPE 里有没有对应记录,再看 USER_TYPE 是否匹配。
3. 代理与考勤模块:AGENT 和 ATTENDANCE 系列表的落地用法
代理和考勤是致远里业务逻辑最绕的两个模块,表多、字段多、状态流转复杂。数据字典把这两块的表结构列得很细,但光看字段注释不够,得知道表之间怎么串。
3.1 AGENT 表的状态字段与代理期限判断
AGENT 表存代理设置,核心字段是 AGENT_ID(代理人)、AGENT_TO_ID(被代理人)、START_DATE、END_DATE、CANCEL_DATE、CANCEL_FLAG。CANCEL_FLAG 是 SMALLINT,0 表示未取消,1 表示已取消。AGENT_TYPE 区分代理设置和离职交接,1 是代理设置,2 是离职交接。
判断一个代理是否生效,不能只看 CANCEL_FLAG,还要看当前时间是否在 START_DATE 和 END_DATE 之间。
-- 查询当前生效的代理关系 SELECT a.ID, a.AGENT_ID, a.AGENT_TO_ID, a.START_DATE, a.END_DATE, a.AGENT_TYPE, a.AGENT_OPTION FROM AGENT a WHERE a.CANCEL_FLAG = 0 AND NOW() BETWEEN a.START_DATE AND a.END_DATE AND a.AGENT_TYPE = 1;逻辑说明:NOW() 是数据库当前时间,BETWEEN 确保代理在有效期内。AGENT_OPTION 是 VARCHAR(50),存的是代理选项的编码,具体含义需要结合业务配置。如果查不到生效代理,先检查 CANCEL_FLAG 是否为 1,再看日期范围是否覆盖当前时间。
AGENT_DETAIL 表通过 AGENT_ID 关联 AGENT,APP 字段是 BIGINT 且必填,表示代理的应用模块。AGENT_SCOPE 存发起人范围,ENTITY_TYPE 指定实体类型,如 ACCOUNT、DEPARTMENT,ENTITY_ID 是对应实体 ID。
3.2 ATTENDANCE_DAY_STATISTICS 的统计字段与考勤日计算
考勤日统计表 ATTENDANCE_DAY_STATISTICS 是考勤模块里查询频率最高的表之一。PUNCH_DATE 是考勤日,WEEK_DAY 是工作日星期,AM_START_TIME、AM_END_TIME、PM_START_TIME、PM_END_TIME 记录上午签到、上午签退、下午签到、下午签退时间。AM_START_STATE 到 PM_END_STATE 是签到签退结果。
统计字段包括 NORMAL_DAYS(出勤天数)、AB_NORMAL_DAY(异常天数)、LATE_NUM(迟到次数)、LEAVE_EARLY_NUM(早退次数)、OUTSIDE_NUM(外勤次数)、MISSINGCLOCK_COUNT(缺卡总数)。PUNCH_CLASS 是应打卡次数,1 表示一天一次,2 表示一天两次。
-- 查询某人员某月的考勤统计汇总 SELECT MEMBER_ID, PUNCH_DATE, WEEK_DAY, 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_DAYS, LATE_NUM, LEAVE_EARLY_NUM, MISSINGCLOCK_COUNT FROM ATTENDANCE_DAY_STATISTICS WHERE MEMBER_ID = ? AND PUNCH_DATE BETWEEN '2024-01-01' AND '2024-01-31' ORDER BY PUNCH_DATE;参数说明:MEMBER_ID 是人员 ID,PUNCH_DATE 是考勤日。AM_START_STATE 等状态字段是 SMALLINT,具体值需要对照字典里的状态定义。如果统计结果和实际打卡记录对不上,先检查 ATTENDANCE_HISTORY 表里的原始打卡记录,再看统计表是否及时更新。
3.3 ATTENDANCE_HISTORY 与 ATTENDANCE_INFO 的差异与选用
ATTENDANCE_HISTORY 和 ATTENDANCE_INFO 两张表结构高度相似,但用途不同。ATTENDANCE_HISTORY 的 SIGN 字段是 VARCHAR(500),ATTENDANCE_INFO 的 SIGN 是 VARCHAR(2000)。ATTENDANCE_INFO 多了 IS_WORK_DAY、MODIFY_NUM、DEVICE_INFO、PUNCH_TYPE、STATE、MAC_ADDRESS 等字段,STATE 明确写了打卡状态:3 是上班迟到,4 是下班早退,5 是正常上班,6 是正常下班。
ATTENDANCE_HISTORY 更像历史归档表,ATTENDANCE_INFO 是当前打卡信息表。查询实时打卡状态用 ATTENDANCE_INFO,查历史记录用 ATTENDANCE_HISTORY。
-- 查询某人员某天的打卡记录及状态 SELECT OWNER_ID, SIGN_TIME, TYPE, SIGN, STATE, LONGITUDE, LATITUDE, DEVICE_INFO, MAC_ADDRESS FROM ATTENDANCE_INFO WHERE OWNER_ID = ? AND PUNCH_DATE = '2024-01-15' ORDER BY SIGN_TIME;逻辑说明:TYPE 字段区分签到来源,1 是签到,2 是签退,3 是外勤。STATE 字段直接给出打卡状态,不用再根据时间差计算。MAC_ADDRESS 存的是 WIFI Mac 地址,用于校验打卡位置。如果打卡记录缺失,先确认 ATTENDANCE_INFO 里有没有数据,再看 ATTENDANCE_HISTORY 里是否有归档记录。
注意:ATTENDANCE_INFO 的 SIGN 字段长度是 2000,比 ATTENDANCE_HISTORY 的 500 大很多,说明当前表存的地址信息更详细。迁移数据时要注意字段长度兼容。
4. 讨论区与组织变更:BBS 和 AI_ORG 系列表的排查要点
讨论区和组织变更记录是致远里相对独立但又容易出问题的模块。BBS 系列表存讨论主题、回复、板块信息,AI_ORG 系列表存组织变更记录。
4.1 BBS_ARTICLE 的匿名与点赞字段处理
BBS_ARTICLE 表里 ANONYMOUS_FLAG 是匿名标志,0 是正常,1 是匿名。ANONYMOUS_REPLY_FLAG 控制是否允许匿名回复,0 是不允许,1 是允许。PRAISE 字段是 TEXT,存的是点赞人员 ID 集合,PRAISE_SUM 是点赞总数。
STATE 字段是 0 正常、1 删除。查询讨论主题时,必须过滤 STATE = 0,否则会把已删除的主题也查出来。
-- 查询某板块下的正常讨论主题 SELECT ID, ARTICLE_NAME, ISSUE_USER_ID, ISSUE_TIME, REPLY_NUMBER, PRAISE_SUM, ELITE_FLAG, TOP_SEQUENCE FROM BBS_ARTICLE WHERE V3X_BBS_BOARD_ID = ? AND STATE = 0 ORDER BY TOP_SEQUENCE DESC, ISSUE_TIME DESC;参数说明:V3X_BBS_BOARD_ID 是板块 ID,STATE = 0 过滤已删除主题。TOP_SEQUENCE 是置顶序号,越大越靠前。ELITE_FLAG 是精华标志,0 正常,1 精华。如果讨论列表显示异常,先检查 STATE 字段,再看 TOP_SEQUENCE 和 TOP_NUMBER_GROUP、TOP_NUMBER_UNIT 的置顶逻辑。
4.2 AI_ORG_CHANGE_RECORD 与 AI_ORG_MEMBER_CHANGE 的变更追踪
AI_ORG_CHANGE_RECORD 存组织变更记录,OLD_ID、OLD_VALUE、NEW_ID、NEW_VALUE 记录变更前后的值。ORG_TYPE 区分变更类别:0 是部门,1 是岗位,2 是职务级别。AI_ORG_MEMBER_CHANGE 存人员变更记录,OLD_ACCOUNT_ID、NEW_ACCOUNT_ID、OLD_DEPT_ID、NEW_DEPT_ID、OLD_POST_ID、NEW_POST_ID、OLD_LEVEL_ID、NEW_LEVEL_ID 记录人员单位、部门、岗位、职务级别的变更前后值。
-- 查询某人员的组织变更历史 SELECT MEMBER_ID, OLD_ACCOUNT_ID, NEW_ACCOUNT_ID, OLD_DEPT_ID, NEW_DEPT_ID, OLD_POST_ID, NEW_POST_ID, OLD_LEVEL_ID, NEW_LEVEL_ID, CREATE_TIME FROM AI_ORG_MEMBER_CHANGE WHERE MEMBER_ID = ? ORDER BY CREATE_TIME DESC;逻辑说明:CREATE_TIME 是变更时间,按倒序排列能快速看到最近的变更。如果人员组织信息异常,先查这张表确认是否有未同步的变更记录。OLD_VALUE 和 NEW_VALUE 是 VARCHAR(500),存的是变更值的文本表示,适合做审计日志。
4.3 ATTENDANCE_TEAM 与 ATTENDANCE_AUTH_ENTITY 的权限校验
ATTENDANCE_TEAM 存考勤组信息,ATTENDANCE_AUTH_ENTITY 存考勤组的授权实体。ENTITY_TYPE 区分组织机构类型:3 是人员,1 是部门,0 是单位。ATTENDANCE_TEAM_ID 关联考勤组。
-- 查询某考勤组的授权实体 SELECT ae.ENTITY_ID, ae.ENTITY_TYPE, ae.ATTENDANCE_TEAM_ID, at.ATTENDANCE_TEAM_NAME FROM ATTENDANCE_AUTH_ENTITY ae JOIN ATTENDANCE_TEAM at ON ae.ATTENDANCE_TEAM_ID = at.ID WHERE ae.ATTENDANCE_TEAM_ID = ?;参数说明:ENTITY_TYPE 是 3 时,ENTITY_ID 对应人员 ID;是 1 时对应部门 ID;是 0 时对应单位 ID。如果考勤组人员显示不全,先检查这张表里有没有对应的授权记录,再看 ENTITY_TYPE 是否正确。
5. 避坑与排查:数据字典用错场景的五个血泪教训
5.1 扩展字段类型对不上导致查询报错
现象:查 ADDRESSBOOK 的 EXT_ATTR_11 想拿数字,结果返回 NULL 或报类型转换错误。原因:EXT_ATTR_11 是 DECIMAL(19,4),但实际存的是文本数字,或者字段根本没赋值。解决:先用 SELECT EXT_ATTR_11 FROM ADDRESSBOOK WHERE EXT_ATTR_11 IS NOT NULL LIMIT 10 看实际存的值,确认类型后再写查询。如果存的是文本,用 CAST 转换。
5.2 代理期限判断漏掉 CANCEL_FLAG
现象:查出来的代理关系明明已经取消了,但业务上还在生效。原因:只看了 START_DATE 和 END_DATE,没过滤 CANCEL_FLAG = 0。解决:查询条件里必须同时带上 CANCEL_FLAG = 0 和日期范围判断。CANCEL_DATE 是取消时间,CANCEL_FLAG 是取消标记,两个字段要一起看。
5.3 考勤统计表和原始打卡记录不一致
现象:ATTENDANCE_DAY_STATISTICS 里显示正常出勤,但 ATTENDANCE_HISTORY 里没有打卡记录。原因:统计表是定时任务生成的,可能还没跑完,或者打卡记录被归档到了 ATTENDANCE_HISTORY 但统计表没更新。解决:先查 ATTENDANCE_INFO 确认原始记录,再看统计表的 CREATE_TIME 和 MODIFY_TIME,判断是否是最新数据。如果是定时任务问题,手动触发统计更新。
5.4 BBS 讨论主题查询漏掉 STATE 过滤
现象:讨论区列表里出现了已删除的主题。原因:查询时没加 STATE = 0 条件。解决:所有 BBS_ARTICLE 和 BBS_ARTICLE_REPLY 的查询都要带上 STATE = 0。BBS_ARTICLE_REPLY 的 STATE 也是 0 正常、1 删除。如果列表还是不对,检查 TOP_SEQUENCE 和 TOP_NUMBER_GROUP、TOP_NUMBER_UNIT 的置顶逻辑。
5.5 组织变更记录查不到最新数据
现象:人员部门已经调整了,但 AI_ORG_MEMBER_CHANGE 里没有对应记录。原因:变更记录是异步写入的,可能有延迟,或者变更操作没触发记录写入。解决:先查 AI_ORG_CHANGE_RECORD 看有没有部门变更记录,再查 AI_ORG_MEMBER_CHANGE。如果都没有,检查变更操作是否走了正确的接口。CREATE_TIME 是变更时间,按时间倒序查最近记录。
6. 把数据字典变成可查询的本地知识库
数据字典的 PDF 或 Excel 看多了会烦,我一般会把它导进本地数据库,建一张字段元数据表,然后用 SQL 直接查。这样比翻文档快得多,而且能跟实际表结构做比对。
-- 创建字段元数据表 CREATE TABLE IF NOT EXISTS oa_dict_meta ( id INT AUTO_INCREMENT PRIMARY KEY, table_name VARCHAR(100) NOT NULL, column_name VARCHAR(100) NOT NULL, data_type VARCHAR(50), is_nullable VARCHAR(10), column_comment VARCHAR(500), module VARCHAR(50), UNIQUE KEY uk_table_column (table_name, column_name) ); -- 插入示例数据(实际使用时从字典文件批量导入) INSERT INTO oa_dict_meta (table_name, column_name, data_type, is_nullable, column_comment, module) VALUES ('ADDRESSBOOK', 'ID', 'BIGINT', 'TRUE', '主键', '通讯录'), ('ADDRESSBOOK', 'MEMBER_ID', 'BIGINT', 'FALSE', '人员 id', '通讯录'), ('ADDRESSBOOK', 'EXT_ATTR_1', 'VARCHAR(1024)', 'FALSE', '文本类型扩展字段 1', '通讯录'), ('AGENT', 'AGENT_ID', 'BIGINT', 'FALSE', '代理人 ID', '代理'), ('ATTENDANCE_DAY_STATISTICS', 'MEMBER_ID', 'BIGINT', 'FALSE', '人员 ID', '考勤');建好这张表后,查字段含义就是一句 SQL 的事。
-- 查询某个模块下所有字段 SELECT table_name, column_name, data_type, is_nullable, column_comment FROM oa_dict_meta WHERE module = '通讯录' ORDER BY table_name, column_name;参数说明:module 字段是我自己加的,用来按业务模块分类。实际导入时,可以从字典文件里解析出表名、字段名、类型、是否必填、注释,批量 INSERT。这样查字段比翻文档快,而且能跟 INFORMATION_SCHEMA 做比对,发现实际表结构和字典不一致的地方。
我一般还会加一个比对查询,把字典里的字段和实际数据库的字段做 FULL OUTER JOIN,找出字典里有但实际表没有的字段,或者实际表有但字典没收录的字段。这个在版本升级后特别有用,能快速发现表结构变更。
-- 比对字典和实际表结构的差异(MySQL 不支持 FULL OUTER JOIN,用 UNION 模拟) SELECT COALESCE(d.table_name, c.TABLE_NAME) AS table_name, COALESCE(d.column_name, c.COLUMN_NAME) AS column_name, d.data_type AS dict_type, c.DATA_TYPE AS actual_type, CASE WHEN d.column_name IS NULL THEN '实际表有,字典缺失' WHEN c.COLUMN_NAME IS NULL THEN '字典有,实际表缺失' WHEN d.data_type != c.DATA_TYPE THEN '类型不一致' ELSE '一致' END AS diff_status FROM oa_dict_meta d LEFT JOIN INFORMATION_SCHEMA.COLUMNS c ON d.table_name = c.TABLE_NAME AND d.column_name = c.COLUMN_NAME WHERE c.TABLE_SCHEMA = 'your_database_name' UNION SELECT c.TABLE_NAME, c.COLUMN_NAME, NULL, c.DATA_TYPE, '实际表有,字典缺失' FROM INFORMATION_SCHEMA.COLUMNS c LEFT JOIN oa_dict_meta d ON c.TABLE_NAME = d.table_name AND c.COLUMN_NAME = d.column_name WHERE c.TABLE_SCHEMA = 'your_database_name' AND d.column_name IS NULL;这段 SQL 跑完,差异一目了然。从那以后我每次拿到新版本的数据字典,都强制走一遍导入、比对、标注差异的流程,再开始写业务查询。希望帮到你。
本文还有配套的精品资源,点击获取