KES数据库Schema 治理与业务对象分层设计
2026/6/12 18:48:09 网站建设 项目流程

本文是本系列第 4 篇。上一篇已经创建了专栏业务数据库kb_shop,本文继续在其中规划业务模式,让客户、商品、订单等对象有清晰的归属。

引言

上一篇文章已经创建了专栏业务库kb_shop,解决了业务对象应该放在哪个数据库中的问题。但一个数据库内部仍然可能包含大量表、视图、函数和辅助对象,如果全部放进默认的public模式,随着文章推进和对象增多,结构会很快变得混乱。

本文进一步讨论 KingbaseES 中的 Schema 治理。我们会把kb_shop划分为salesinventoryops三个模式,用它们分别承载销售、库存和运维辅助对象。这样做不仅是为了目录清晰,更是为了后续权限控制、对象检索、查询编写和备份维护更加接近真实项目。

很多数据库新手会把所有表都建在public模式下。刚开始只有一两张表时看不出问题,但业务对象一多,就容易出现命名混乱、权限边界不清、查询路径不明确等问题。

KingbaseES 支持模式,也就是 schema。模式可以理解为数据库内部的“逻辑分区”:

数据库 kb_shop ├─ sales 客户、订单、订单明细 ├─ inventory 商品、库存 ├─ ops 运维检查、脚本执行记录 └─ public 默认模式,尽量少放业务对象

本文目标:

  1. kb_shop中创建多个业务模式。
  2. 理解search_path的作用。
  3. 学会使用完整对象名访问表。
  4. 建立本系列后续文章的对象命名规范。

文章目录

    • 引言
    • Schema 是数据库对象治理的第一层边界
    • 一、连接 kb_shop
    • 二、查看当前已有模式
    • 三、创建业务模式
    • 四、理解 search_path
    • 五、完整对象名更适合文章演示
    • 六、创建一个 ops 检查表
    • 七、设置数据库级默认 search_path
    • 八、对象命名规范
    • 九、常见问题排查
      • 问题 1:报错 schema does not exist
      • 问题 2:查询表时报 relation does not exist
      • 问题 3:search_path 设置了但没有生效
      • 问题 4:不确定某张表在哪个模式
    • 十、本文小结

Schema 是数据库对象治理的第一层边界

Schema 通常翻译为“模式”。在一个数据库中,模式用于组织表、视图、函数等数据库对象。它既不是独立数据库,也不是简单文件夹,而是一种数据库内部的命名空间和权限边界。

为什么不能所有对象都放进public?核心原因有三点:

问题全放在 public 的后果使用 Schema 的收益
命名冲突不同业务模块容易出现同名表通过sales.customercrm.customer区分
权限粗糙很难只授权某一类业务对象可以按模式授予访问范围
维护困难对象多后缺乏业务分层DBA 和开发能快速定位对象归属

在企业系统中,模式设计往往对应业务模块设计。销售对象、库存对象、运维对象分开管理,能够让后续权限控制、备份策略、脚本维护和问题排查更加清晰。

本文将kb_shop划分为salesinventoryops,本质上是在做数据库对象治理。这个设计会贯穿后续文章:客户和订单归属于sales,商品和库存归属于inventory,检查和辅助表归属于ops

一、连接 kb_shop

打开命令提示符,进入工具目录:

cd /d D:\Tools\Kingbase\ES\Server\bin

连接kb_shop

ksql -U system -d kb_shop -h localhost -p 54321

确认当前数据库:

SELECTcurrent_database()AScurrent_db,current_userASlogin_user;

预期结果:

二、查看当前已有模式

执行:

\dnksql中查看模式列表的快捷命令。相比直接查询系统视图,它更适合日常交互式检查;而 SQL 查询更适合写进脚本或报表。两种方式并不冲突,前者便捷,后者可编程。

\dn

通常会看到public等模式。

也可以使用 SQL 查询:

SELECTschema_nameFROMinformation_schema.schemataORDERBYschema_name;

这两种方式都可以。\dn适合日常命令行查看,SQL 查询适合写脚本和报表。

三、创建业务模式

为了后续文章形成清晰结构,我们创建 3 个模式:

这一步不是为了“多分几个目录”,而是提前建立业务边界。sales负责销售域对象,inventory负责库存域对象,ops负责运维辅助对象。后续讲权限时,就可以做到只给某个用户访问某个模式,而不是把整个数据库都开放出去。

模式名用途
sales客户、订单、订单明细等销售业务对象
inventory商品、库存等库存业务对象
ops巡检、脚本记录、辅助管理对象

执行:

CREATESCHEMAIFNOTEXISTSsales;CREATESCHEMAIFNOTEXISTSinventory;CREATESCHEMAIFNOTEXISTSops;

再次查看:

\dn

可以看到:

为了让对象用途更清楚,可以加备注:

COMMENTONSCHEMAsalesIS'Customer and order business objects';COMMENTONSCHEMAinventoryIS'Product and stock business objects';COMMENTONSCHEMAopsIS'Operation check and helper objects';

四、理解 search_path

创建了模式后,会遇到一个问题:如果执行下面的 SQL:

SELECT*FROMcustomer;

数据库应该去哪一个模式下找customer表?

这就涉及search_path

查看当前搜索路径:

search_path决定了当 SQL 中没有写模式名时,数据库按什么顺序查找对象。它是方便工具,也是潜在风险。方便之处在于 SQL 可以写得短;风险在于不同会话的search_path不一致时,同一句 SQL 可能访问到不同对象。

SHOWsearch_path;

常见结果类似:

这表示当你不写模式名时,数据库会按顺序查找对象。

为了让后续操作更方便,可以在当前会话设置:

SETsearch_pathTOsales,inventory,ops,public;

再查看:

SHOWsearch_path;

此时如果执行:

SELECT*FROMcustomer;

数据库会优先在sales模式中寻找customer

五、完整对象名更适合文章演示

虽然search_path很方便,但在写技术文章、脚本和生产变更时,我更推荐使用完整对象名:

完整对象名能降低上下文依赖。尤其是文章和教程,读者的环境可能和我文章里写的不完全一致,使用sales.customer这样的写法,比只写customer更稳,也更能体现数据库对象归属。

sales.customer inventory.product ops.script_run_log

这样读者一眼就知道对象属于哪里,也能减少“当前搜索路径不一致”导致的报错。

例如后续创建客户表时,不写:

CREATETABLEcustomer(...);

而写:

CREATETABLEsales.customer(...);

查询也尽量写:

SELECT*FROMsales.customer;

这会让文章更稳定,读者复制 SQL 时也不容易受当前会话状态影响。

六、创建一个 ops 检查表

为了验证模式是否可用,我们先在ops模式下创建一张检查表。

CREATETABLEIFNOTEXISTSops.schema_check(idSERIALPRIMARYKEY,schema_nameVARCHAR(50)NOTNULL,check_resultVARCHAR(50)NOTNULL,checked_atTIMESTAMPDEFAULTCURRENT_TIMESTAMP);

插入检查记录:

INSERTINTOops.schema_check(schema_name,check_result)VALUES('sales','created'),('inventory','created'),('ops','created');

查询:

SELECTid,schema_name,check_result,checked_atFROMops.schema_checkORDERBYid;

预期结果类似:

七、设置数据库级默认 search_path

如果每次连接kb_shop后都手工执行:

SETsearch_pathTOsales,inventory,ops,public;

会比较麻烦。可以给数据库设置默认搜索路径:

ALTERDATABASEkb_shopSETsearch_pathTOsales,inventory,ops,public;

设置后,断开重连:

\q

重新连接:

ksql -U system -d kb_shop -h localhost -p 54321

再查看:

SHOWsearch_path;

如果结果中包含sales, inventory, ops, public,说明数据库级默认配置生效。

如果你不想设置数据库级默认值,也可以不执行这一步。后续文章会尽量使用完整对象名,避免依赖搜索路径。

八、对象命名规范

为了让后续文章风格统一,系列文章采用以下命名规则:

类型规则示例
数据库小写,下划线kb_shop
模式小写,业务含义明确salesinventory
小写,单数名词或业务短语customerproductcustomer_order
字段小写,下划线customer_idcreated_at
主键表名加_idproduct_id
检查约束ck_表_字段ck_product_price
唯一约束uk_表_字段uk_customer_phone
外键约束fk_子表_父表fk_order_customer

这种命名方式的好处是可读性高,后续排查约束报错时也更容易定位。

九、常见问题排查

问题 1:报错 schema does not exist

如果执行:

CREATETABLEsales.customer(...);

却提示schema "sales" does not exist,说明模式还没创建。

先执行:

CREATESCHEMAIFNOTEXISTSsales;

再建表。

问题 2:查询表时报 relation does not exist

可能原因是表在某个模式下,但查询时没有写完整对象名。

错误示例:

SELECT*FROMcustomer;

推荐写法:

SELECT*FROMsales.customer;

或者先设置:

SETsearch_pathTOsales,inventory,ops,public;

问题 3:search_path 设置了但没有生效

如果执行了:

ALTERDATABASEkb_shopSETsearch_pathTOsales,inventory,ops,public;

但当前窗口里SHOW search_path;仍然没变,原因通常是数据库级配置对新连接生效。

处理方式:

\q

重新连接后再查看。

问题 4:不确定某张表在哪个模式

可以查询系统信息:

SELECTtable_schema,table_nameFROMinformation_schema.tablesWHEREtable_name='schema_check'ORDERBYtable_schema;

如果后续对象多了,这个查询很实用。

十、本文小结

本文承接kb_shop数据库的创建,完成了数据库内部第一层对象治理:Schema 分层。通过salesinventoryops三个模式,我们把后续业务对象按照职责分开,避免所有表都堆在public中。

本文在kb_shop中完成了业务模式规划:

sales 客户、订单 inventory 商品、库存 ops 检查、辅助管理 public 默认模式,尽量少放业务对象

同时我们掌握了:

\dn CREATE SCHEMA COMMENT ON SCHEMA SHOW search_path SET search_path ALTER DATABASE ... SET search_path 完整对象名访问

下一篇会开始创建真正的业务表:客户表、商品表、订单表、订单明细表,并重点讲字段类型、主键、唯一约束、检查约束和外键约束。也就是说,第四篇完成了对象分层,第五篇会进入关系建模和数据完整性设计。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询