当前位置: 首页 > news >正文

读书笔记:什么是对象表?

我们的文章会在微信公众号IT民工的龙马人生和博客网站( www.htz.pw )同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢!
由于博客中有大量代码,通过页面浏览效果更佳。

本文为个人学习《Expert Oracle Database Architecture Techniques and Solutions for High Performance and Productivity(第四版本》一书过程中的笔记与理解分享,仅用于学习与交流,部分内容参考原书观点并结合>实际经验进行整理。若涉及版权问题,请联系删除或沟通处理。也请大家支持购买原版书籍。

什么是对象表?

想象一下,你平时建表像是用乐高积木一块块拼装(定义各个列),而对象表则是直接使用一个现成的、封装好的乐高模型(自定义类型)来建表。它是一种基于自定义类型(TYPE) 来创建的表,表的“列”实际上就是类型中定义的属性。

简单来说:

  • 普通建表CREATE TABLE t (x INT, y DATE, z VARCHAR2(25)); — 自己指定每一列。
  • 对象表建表CREATE TABLE t OF Some_Type; — 直接用一个现成的类型模板来生成表。

一个生动的例子

让我们通过一个“人”的例子来理解它。

第一步:定义“地址”类型
我们先定义一个“地址”的模板(类型),它包含城市、街道、州和邮编这些属性。

CREATE TYPE address_type AS OBJECT (city    VARCHAR2(30),street  VARCHAR2(30),state   VARCHAR2(2),zip     NUMBER
);

第二步:定义“人”类型
接着,我们定义一个“人”的模板。一个人有姓名、生日、家庭地址和工作地址。注意,家庭地址和工作地址本身就是我们刚定义的 address_type 类型。

CREATE TYPE person_type AS OBJECT (name          VARCHAR2(30),dob           DATE,home_address  address_type, -- 嵌套了地址类型work_address  address_type  -- 再次嵌套地址类型
);

第三步:创建对象表
现在,我们不用费力地列出所有列,直接用一个简单的命令就能创建一张“人”表。

CREATE TABLE people OF person_type;

查看这张表的结构,你会发现它看起来非常整洁,就像类型定义一样:

名称          空? 类型
------------ -- ------------------------
NAME           VARCHAR2(30)
DOB            DATE
HOME_ADDRESS   ADDRESS_TYPE
WORK_ADDRESS   ADDRESS_TYPE

第四步:使用对象表
向对象表插入数据时,需要使用类型的“构造函数”来组装数据:

INSERT INTO people VALUES ('Tom','15-mar-1965',address_type('Denver', '123 Main Street', 'Co', 12345), -- 构造家庭地址address_type('Redwood', '1 Oracle Way', 'Ca', 23456)    -- 构造工作地址
);

查询数据时,可以像普通列一样访问嵌套类型的属性,语法非常直观:

-- 查询这个人的家庭地址在哪座城市
SELECT name, p.home_address.city FROM people p;NAME       HOME_ADDRESS.CITY
---------- ------------------------------
Tom        Denver

幕后真相:魔法与代价

虽然对象表用起来很酷,但它的背后并不简单。Oracle 最终仍然是以传统的行和列来存储所有数据。当我们创建对象表时,Oracle 在幕后做了大量工作:

  • 添加隐藏列:系统会自动添加一些隐藏列来管理数据,比如 SYS_NC_OID$(一个16字节的系统生成对象ID)和 SYS_NC_ROWINFO$(一个能返回整行对象的魔法函数)。
  • 展开嵌套类型:我们的 ADDRESS_TYPE 被“拍平”了,它的每个属性(city, street, state, zip)都变成了表中一个独立的、名字由系统生成的隐藏列(如 SYS_NC00006$)。这是因为列名必须唯一,而嵌套类型可能被多次使用(比如家庭地址和工作地址)。
  • 创建唯一索引:系统会自动在 SYS_NC_OID$ 列上创建唯一索引。

这意味着:一张看起来只有 4 列的对象表,在底层可能实际上有 14 个(或更多)物理列。这些魔法操作会带来隐藏的复杂性、额外的索引和意想不到的伪列。


对象表 vs. 关系表 + 对象视图:如何选择?

对象表很强大,但它将物理存储和逻辑模型紧密耦合了。很多时候,一种更灵活、更可控的方法是:使用传统关系表存储数据,然后用对象视图(Object View)提供对象接口

这样做的好处:

  1. 完全控制存储:你知道数据具体是如何存储的,可以精细优化。
  2. 保持关系型访问:你的表仍然是标准的关系表,所有现有的工具、应用程序和报表都能无缝使用它,不受任何影响。
  3. 享受对象优势:需要通过编程(如PL/SQL)以对象方式操作数据的人,仍然可以通过对象视图来获得清晰、易用的对象接口。
  4. 避免“魔法”开销:你避免了系统自动生成的隐藏列和索引带来的潜在开销和复杂性。

实现方式示例:

-- 1. 创建传统的关系表,明确每一列
CREATE TABLE people_tab (name          VARCHAR2(30) PRIMARY KEY,dob           DATE,home_city     VARCHAR2(30),home_street   VARCHAR2(30),home_state    VARCHAR2(2),home_zip      NUMBER,work_city     VARCHAR2(30),work_street   VARCHAR2(30),work_state    VARCHAR2(2),work_zip      NUMBER
);-- 2. 创建一个对象视图,让它看起来和感觉上就像一个对象表
CREATE VIEW people OF person_type
WITH OBJECT IDENTIFIER (name) -- 指定主键name作为对象标识符
AS
SELECT name, dob,address_type(home_city, home_street, home_state, home_zip) home_address,address_type(work_city, work_street, work_state, work_zip) work_address
FROM people_tab;

现在,你可以像插入对象表一样向视图插入数据(对于复杂的视图,可能需要编写 INSTEAD OF 触发器来处理DML操作),同时底层的数据是以你最熟悉、最可控的关系形式存储的。


总结

  • 对象表是一种“语法糖”,它让你能用面向对象的方式定义和操作表,但底层仍然是关系存储。
  • 它带来了便利,但也伴随着隐藏的复杂性(自动生成的列、索引)。
  • 对象视图是一种更推荐的架构选择。它让你鱼和熊掌兼得:既保留了传统关系存储的简单性和兼容性,又为开发者提供了强大的对象操作接口。
  • 除非有强烈理由必须使用对象表作为物理存储,否则关系表 + 对象视图的组合通常能提供更大的灵活性和控制力,是实现对象-关系模型的最佳实践。

------------------作者介绍-----------------------
姓名:黄廷忠
现就职:Oracle中国高级服务团队
曾就职:OceanBase、云和恩墨、东方龙马等
电话、微信、QQ:18081072613
个人博客: (http://www.htz.pw)
CSDN地址: (https://blog.csdn.net/wwwhtzpw)
博客园地址: (https://www.cnblogs.com/www-htz-pw)

http://www.hskmm.com/?act=detail&tid=168

相关文章:

  • AI 服务路由策略:如何实现智能负载均衡
  • 在SQL语句中的别名
  • 多维度排序算法在企业级应用中的性能优化
  • 正则表达式在代码解析中的高级应用
  • vue3 项目中优雅的使用 SVG 图标(vite-plugin-svg-icons)
  • 自我介绍+软工5问
  • 车道线检测资料
  • 实现Jenkins不同账号只能看到各自任务的权限
  • 6 个最佳无代码 IT 资产管理工具推荐
  • python开发mcp入门
  • 建造者模式进阶:复杂AI服务的优雅构建
  • 代理模式在AI应用中的安全实践:AOP + 限流 + 权限控制
  • ​​高压差分探头:高电压测量的精密之眼​​
  • OCP认证烂大街了吗?别跟风问这个问题了
  • 全国连锁贸易公司数字化管理软件-优德普SAP零售行业解决方案
  • Win7、WinServer2008运行.net8.net4.8程序的解决方案
  • 虚机网络配置基础 - 小
  • 你的开发服务器在说谎-热重载与热重启的关键区别
  • 文件不只是数据-一份稳健的文件处理指南
  • 别再猜了-开始测量吧-一份实用的Web性能指南
  • 软工作业1
  • 避坑指南!Flutter 编译 Android 程序常见问题 + 解决方案,附安全加固技巧
  • [SQL] SQL Server 编写表脚本生成的SQL语句不包含索引以及触发器的解决方法
  • chrome高版本浏览器不兼容driver.execute_script(“return window.performance.getEntries()“)的解决方法
  • 移动端盒子元素实现左右可滑动且竖向页面可滑动
  • 双桶倒水的Python程序
  • 【API接口】最新可用天翼云盘解析接口
  • 搭建GZCTF平台及上传动态flag密码题目过程
  • 微信小程序触发订阅消息
  • TOR内置网桥失效 - Andy