资讯详情

Odoo 17 数据字典实战指南:用 PostgreSQL 表结构快速看懂数据库

📅 2026/10/11 14:25:03 | 华诺云谱 👁 阅读
Odoo 17 数据字典实战指南:用 PostgreSQL 表结构快速看懂数据库
简介这是Odoo 17数据库结构的完整中文数据字典面向Odoo开发、实施与二次开发人员帮助快速理清官方核心应用的后端数据表关系。资源为一份PDF文档由Navicat生成并经过中文整理系统罗列数据库中public模式下的业务表涵盖财务、销售、采购、库存等标准模块的表与字段信息同时标注字段命名、类型及关联关系。涵盖从基础表到关联表的完整目录对理解Odoo的ER模型很有帮助由于Odoo通过ORM抽象了数据库结构很多初学者在排查数据流或编写自定义报表时常苦于找不到底层表这份字典按模块目录组织恰好能充当随手查阅的案头手册。压缩包内共1个PDF文件大小8.07MB体量轻便不占用过多空间目前已有133人学习/下载适合正在学习Odoo 17或准备进行模块定制、数据分析的开发者参考。1. 一份 Odoo 17 数据字典比官方文档更快让你看懂数据库接手 Odoo 17 项目的人最怕的不是功能不会配而是数据库像黑匣子。官方文档把模型讲得头头是道可真要写 SQL 报表或者排查一个字段报错时你面对的是 PostgreSQL 里几百张物理表字段到底叫什么、类型是什么、跟哪张表关联文档往往帮不上忙。这份已翻译为中文的 Odoo 17 数据字典就是用 Navicat 从 PostgreSQL 导出的表结构全集覆盖了以会计模块为主的 public schema 下大批业务表正好补上这个缺口。适合做二开、写财务报表、做数据迁移、以及刚接手 Odoo 项目需要快速摸清库结构的从业者。一句话它不能替代源码但能让你在写任何一条 SQL 之前先看清字段少走弯路。2. 读懂 Odoo 17 的表结构命名规律、关系表与主键策略2.1 先看命名规律半小时建立全局观打开这份数据字典第一感觉是表名又多又长尤其是一大串以account_开头的表。其实 Odoo 的物理表命名非常机械表名 所属模块名 模型名的下划线形式。以account.move模型为例生成物理表就是account_moveaccount.move.line对应account_move_lineaccount.journal对应account_journal。也就是说看到account_前缀就能直接判断这张表来自会计模块。我拿到这类数据字典的第一件事是把表按前缀分组建立一张速览表。以下是从这份字典里可以直接抄走的清单思路表名前缀大致模块归属典型表举例account_会计与财务account_move / account_journal / account_paymentaccount_analytic_分析会计成本中心account_analytic_account / account_analytic_lineaccount_bank_statement银行对账单account_bank_statement / account_bank_statement_lineaccount_fiscal_position税位与税务规则account_fiscal_position / account_fiscal_position_taxaccount_payment_term付款条款account_payment_term / account_payment_term_lineaccount_reconcile_自动对账规则account_reconcile_model / account_reconcile_model_lineaccount_tax税与税分配account_tax / account_account_tax_default_relaccount_full_reconcile完全对账account_full_reconcileaccount_partial_reconcile部分对账account_partial_reconcile为什么这张表有用因为它决定了你排查问题的入口。比如报表里发现某个客户余额不对很多人第一反应去翻account_payment实际上未核销的应收余额全部沉淀在account_move_line里你如果按模块前缀去定位方向就不会跑偏。还有一类表值得单独拿出来看以_rel结尾的关系表比如account_account_account_journal_rel、account_account_tag_account_move_line_rel、account_move_account_move_send_rel。这类表对应 Odoo 模型里的 Many2many 字段表里通常只有两个外键列极少有业务含义。看数据字典时把它们和普通业务表区分开能省很多时间。区分方法很简单有主键 ID 且字段多的是业务表字段只有两三个且全是_rel的直接归类为纯关联表。判断一个表是不是关系表或业务表可以看它有没有create_uid、write_date这类审计字段——真正的业务对象基本都有纯关系表往往连id都没有。2.2 字段级别列名、类型与注释怎么对着功能读表看明白之后要落到字段。数据字典里每张表会列出字段名、类型、是否可空、默认值和注释这对写 SQL 帮助最直接。以 Odoo 17 会计模块最核心的account_move为例这张表就是“凭证”或者说“发票 手工分录”的统一载体。关键字段可以按下表理解字段名类型用途说明move_typevarchar凭证类型entry 手工分录、out_invoice 客户发票、in_invoice 供应商发票、out_refund 客户退款statevarchar状态draft 未过账、posted 已过账、cancel 已取消journal_idint8所属日记账关联 account_journalpartner_idint8往来单位关联 res_partnerinvoice_datedate发票日期手工分录里可不填amount_untaxednumeric未税金额amount_taxnumeric税额amount_totalnumeric含税总额读懂字段名之后一个重要的习惯是看类型。Odoo 里金额字段几乎全是numeric小数精度取决于货币的 decimal places编码类字段像code通常是varchar且带唯一索引日期时间字段是timestamp。比如account_move_line表里的date是date类型而create_date是timestamp用错类型去查报表时常常莫名其妙查不到当天数据这是新手最容易犯的错。再就是对字段的“翻译”要保持警惕。数据字典翻译的是物理表注释不是 Odoo 界面显示文本。看到reconciled这种字段被译成“已调节”或“已对账”需要回到业务场景里理解它是判断这笔分录行是否已经完成对账核销的布尔标记。只有结合“对账”这个业务动作去理解字段后面写应收账龄报表才不会搞错取数逻辑。2.3 关系表与外键看懂数据字典没画出来的线Navicat 导出的数据字典通常会列出索引与主键但 Odoo 有一个坑大部分表之间没有真正的物理外键约束。也就是说你在这份字典里看不到字段关联关系的连线图但表与表之间的逻辑关系藏在字段命名里几乎全部遵循“xxx_id指向哪张表”的规则。比如account_move里的journal_id指向account_journal的idaccount_move_line里的move_id指向account_moveaccount_payment里的move_id则指向付款生成的凭证。这是我说的“看字段后缀判断关联”凡是_id结尾的字段基本都能在另一张表里找到主键对应。再比如account_account_account_journal_rel这个表名拆开是account_account加account_journal中间用_rel连接说明这是一个“科目与日记账多对多关系”的表。实际业务含义是某些日记账限定只能使用特定会计科目比如银行日记账只能用银行科目。如果你在写 SQL 时想找出“某个科目在哪些日记账里可用”直接关联这张关系表比翻界面更快。关系表的字段通常只有两列列名往往是人名化的比如account_account_id和account_journal_id对应到代码里就是 Many2many 两端的字段。看到这里我建议你在数据字典上做一个小标记把这几个_rel表单独列一组以后写联表查询时凡是涉及多对多过滤都优先想到它们。提示Odoo 的 ORM 会自动维护_rel表千万不要手动往这类表里插数据也别在视图里直接展示很容易造成关联数据丢失且不自知。3. 把数据字典用起来反查模型、核对字段、写 SQL 的三个落地场景3.1 场景一升级或安装模块报“字段不存在”用字典比翻日志更快实际开发里最常见的报错是装模块或者升级模块时页面直接弹出column account_move_line.xxx does not exist。这条报错虽然给了表名和字段名但很多时候你根本不知道这个字段是本来就该有、还是代码里写错模型了。我的排查习惯是直接打开数据字典定位到对应表搜索这个字段名然后做三个判断第一数据字典里根本没有这个字段说明当前库里没有安装对应模块或者字段名写错优先检查模型定义里的字段名。第二字段存在但类型对不上比如代码里定义的是Datetime字典里显示date这是字段类型不匹配导致的数据库约束问题。第三字段存在但前缀不对比如把sale_order的字段写到account_move里字典能立刻帮你看出这两张表风马牛不相及。写完代码之后还能用一条 SQL 做快速验证这条 SQL 可以反复复用SELECT column_name, data_type, is_nullable FROM information_schema.columns WHERE table_name account_move_line AND column_name reconciled;这段查询从 PostgreSQL 系统表里取指定表的字段信息。table_name换成你怀疑出问题的物理表名column_name换成报错里提到的字段名。返回有记录说明字段存在没有记录说明模型字段没建上。相比打开 Navicat 看图形界面这条 SQL 在任何客户端里都能跑省去来回切换的功夫。确认字段存在但类型不匹配的情况比如把date当成timestamp用会出现在日期边界问题上这时去 Odoo 源码里找到对应模型定义把字段类型改一致再-u升级模块让 ORM 自动同步。不要在数据库里直接改字段类型因为 Odoo 的 ORM 缓存会认为表结构和模型定义不一致改完数据库反而更容易把整个模块搞挂。3.2 场景二写财务 SQL 报表先核这三张表做 Odoo 二开绕不开财务报表。最常碰的物理表就三张account_move凭证头、account_move_line凭证行、account_partial_reconcile部分对账记录。很多人一开始写应收账龄就翻车原因是不清楚account_move只存了凭证摘要和总额真正的借贷明细全在account_move_line里。一个典型的“已过账客户发票借项合计”查询可以这么写SELECT l.partner_id, l.account_id, m.name AS move_name, m.invoice_date, l.debit, l.credit, l.balance FROM account_move_line l JOIN account_move m ON l.move_id m.id WHERE m.move_type out_invoice AND m.state posted AND l.account_id 12345 ORDER BY m.invoice_date DESC;这里先解释逻辑account_move_line是行级流水debit是借方金额credit是贷方金额balance是系统按“借减贷”算好的余额move_type out_invoice过滤出客户发票state posted过滤掉草稿和已取消凭证l.account_id指定应收科目。之所以不直接查account_move的amount_total是因为一张凭证里可能有多行对应不同科目报表要让科目余额平就必须从行表出发。参数说明l.account_id换成你要查的会计科目 ID这个 ID 可以从数据字典里account_account表的id字段查到如果要查供应商应付把move_type改成in_invoice。需要包含未过账数据时去掉AND m.state posted但注意草稿凭证里金额可能后续改动报表统计一般只认已过账。还有一个容易算错的地方是“对账”。某一行balance为零并不代表已对账只有reconciled字段为true才是真正核销完毕。想统计未回款金额核心是找reconciled false且balance ! 0的分录行。如果想把部分对账的明细也拉出来才需要再关联account_partial_reconcile看金额拆分。这一层关系数据字典里没有画箭头但字段名已经提示了account_move_line上的matched_partial以及account_partial_reconcile里的debit_move_id、credit_move_id就是把对账明细分摊开的关键。3.3 场景三数据迁移前用数据字典做字段映射底稿从旧 ERP 迁到 Odoo 17最忌一上来就写导入脚本。字段跑不通的原因九成是两边字段名和类型没对齐。这份中文数据字典可以直接当成字段映射表的底稿省去先翻模型再手抄字段的功夫。我的做法是选一张核心表比如account_move_line把数据字典里该表的字段列复制到 Excel然后加三列源系统字段、转换规则、是否导入。字段级映射只需要保留少量关键列模板大概是这样Odoo 字段类型源系统字段转换规则partner_idint8客户编码先查 res_partner 的 idaccount_idint8科目编码按 account_account.code 反查 iddebit / creditnumeric借贷金额直接映射datedate凭证日期源为文本 yyyyMMdd转 daterefvarchar摘要直接映射move_idint8凭证号先导入 account_move回填 id这里有个迁移时的高频问题很多新手看到id字段就想把旧系统主键直接带过来结果一导就撞主键冲突。Odoo 的物理表主键虽然叫id但它完全允许你重新生成真正要保证业务唯一的是类似account_account.code科目编码、res_partner的 VAT 这类业务字段。迁移前先看数据字典里哪些字段带唯一索引那才是你映射方案真正要对齐的锚点。4. 避坑指南Navicat 生成的中文数据字典这五个坑最耽误事4.1 坑一注释不是全覆盖翻译和实际界面用词对不上现象数据字典里某些字段的注释是空的或者翻译得生硬比如reconciled被译成“已调节”analytic_tag被译成“分析标签”跟界面上看到的中文标签完全对不上。原因Navicat 导出的字典注释来源是 PostgreSQL 里的COMMENT ON COLUMN。但 Odoo 字段的中文标签是写在模型_(...)里的并不一定同步到数据库注释所以字典里的翻译是导出的那一刻手工或半自动生成的存在缺口。解决遇到注释为空或看不懂的字段回到 Odoo 源码看模型定义同时结合界面操作理解。更省事的做法是记住“注释仅供参考”真正判断字段用途靠字段名 类型 值分布。比如看到一个state字段直接SELECT DISTINCT state FROM ...看有几种取值远比注释可靠。4.2 坑二数据字典是特定账号的导出快照跟你实际库不一定一致现象按数据字典里的表名去自己库里查发现表不存在或者字段数量对不上。原因这份字典来自特定数据库的导出正文目录里能看到大量account_accrued_orders_wizard、account_reconcile_model_line这类表说明导出时这个库启用了完整会计相关模块。而你自己搭的 Odoo 17 可能只装了部分模块模块没装物理表自然不存在。解决把数据字典当“参考地图”使用。先通过“设置 → 已安装模块”对比源库装了哪些模块再决定哪些章节能用。如果字段对不上以information_schema查到的实际结构为准不要在没了解模块差异之前就怀疑字典错了。4.3 坑三排查字段时拿生产库直接跑 ALTER容易埋雷现象发现某张表缺字段直接在 Navicat 里手工执行ALTER TABLE ... ADD COLUMN结果 Odoo 前台页面报错或者后续升级模块时提示字段类型冲突。原因Odoo 的 ORM 在启动时会对比模型定义与物理表结构并尝试同步。手工加了字段但模型定义里没有对应字段升级模块时 ORM 不会删它却可能在后续迁移时因类型不匹配报错反过来模型有字段而手工删了列ORM 启动时又会自动建回去。解决只要涉及结构变更一律通过修改模型定义然后odoo-bin -u module升级来完成。数据字典只用来确认现状不做变更入口。需要临时实验时在副本库上操作确认无误再上正式环境。4.4 坑四把物理主键 id 当成业务编号用现象写报表时直接拿partner_id去界面上对客户编号发现对不上或者迁移时把旧系统流水号硬塞进id字段导致关联混乱。原因Odoo 里id就是 PostgreSQL 自增主键没有业务意义。真正可读的业务编号往往在name、code、reference等字段里比如account_journal.code是日记账编码account_account.code是科目编码。数据字典字段列表里能直接看到这些字段但如果不养成“先看唯一索引”的习惯很容易默认 id 可用。解决查询用表时先看数据字典中哪些字段有唯一约束把这些字段作为可能的业务主键写迁移脚本时用旧业务编码反查新系统的 id再建关联。切忌直接把旧 id 搬过来充当物理主键。4.5 坑五把数据字典当成需求文档结果读不懂业务现象字典看了好几遍字段都知道但就是不理解“为什么这张表会有这个状态”或者不知道一个字段什么时候被写入。原因数据字典是静态结构只描述“有什么表、有什么字段、类型是什么”不描述“这些字段在业务流程里如何流转”。比如account_move.state从 draft 到 posted 再到 cancel这个流转规则在 Python 代码里不看代码永远理解不了也猜不到为什么有些记录没有invoice_date。解决数据字典用来定位源码和日志用来理解。我习惯是先在字典里找到表再去源码搜对应模型看api.onchange、write、action_post等方法把字段变化串起来。工具配合源码才能避免拿着地图找不到路的窘境。5. 进阶用 psql 把数据字典二次加工成自己的速查表Navicat 导出的字典是一份静态文档但数据库结构是活的。我一般会在拿到字典之后用几条 SQL 把它转成自己常用的速查表这样线上线下能保持一致。第一条搜某个字段关键词找出哪些表包含该字段。比如想查所有含“备注/说明”字段的表SELECT table_name, column_name, data_type FROM information_schema.columns WHERE column_name IN (name, ref, note, comment) AND table_schema public ORDER BY table_name;这段查询的价值在于跨表搜索。information_schema.columns是 PostgreSQL 的系统视图column_name IN (...)可以换成你自己关心的字段名集合比如amount_untaxed、balance。改表名或字段名时这条 SQL 能在30秒内告诉你影响范围比肉眼翻几百页字典快得多。第二条生成一份所有业务表的字段数量统计快速判断哪些表是主表、哪些是多对多关系表SELECT table_name, count(*) AS column_count FROM information_schema.columns WHERE table_schema public GROUP BY table_name ORDER BY column_count DESC;结果里字段数量极小比如 5 以下的表大概率是_rel关系表字段数量 20 以上的基本是核心业务表。拿到这份名单后我会重点再核对一次哪些表是迁移、报表的高频对象把这些表单独做成一个 Excel 工作簿。第三个技巧是验证字段时的“后悔药”写法。在测试库上核对结构或尝试更新数据时用事务包住再回滚避免手滑BEGIN; SELECT count(*) FROM account_move_line WHERE reconciled false; -- 如果发现结果不是预期直接回滚不产生任何数据变更 ROLLBACK;这里BEGIN开启事务ROLLBACK撤销本事务内所有操作。即使中途跑了一条UPDATE只要还没COMMIT都能安全撤销。把这条习惯带进日常排查能避免不少“手一抖全表更新”的事故。从那以后我每次接手新的 Odoo 项目都会先拿到一份数据字典然后花半小时跑一遍上面的字段搜索和表统计再开始写业务 SQL。这一套流程帮我避开了太多因为表结构不清楚而返工的问题。数据字典是死的查询习惯是活的希望这份中文版 Odoo 17 数据字典和这篇使用思路能帮你在接手的项目里少踩几个坑。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑