TYPE IS RECORD 的基本语法为 TYPE 类型名 IS RECORD (字段名 类型 [DEFAULT 值] [NOT NULL]);,支持标量、%TYPE、嵌套记录,作用域限于当前块或包;不可整体比较或判空,赋值为值拷贝;INSERT/UPDATE 中可用但须字段顺序严格匹配。
怎么写 TYPE IS RECORD 的基本语法
直接用
关键字加
块就能定义,字段名、类型、默认值、
约束都写在括号里,不依赖表结构也能用。
名称自己起,作用域只在当前 PL/SQL 块(比如
段)或包内,不能跨过程直接复用
字段类型支持标量(
)、引用(
)、甚至嵌套记录(另一个
类型)
可以给字段设默认值:
,但注意:只有声明变量时才生效,
或赋值后不会回填默认值
带
的字段,一旦没初始化或赋值就访问,会报
什么时候该用 RECORD 而不是 %ROWTYPE
当你要组合的字段来自多张表、视图、计算列,或者根本没对应物理表时,
就不管用了,必须手写
。
比如封装接口入参:一个订单操作要传
、
(查码表得来)、
(
计算),这三者不在同一张表里
又比如做轻量 DTO:把查询结果加工成含描述字段(如
替代
)的结构,避免后续反复
是“照抄表结构”,字段增删会导致 RECORD 定义失效;而自定义 RECORD 更稳定,改字段只需同步改一处声明
赋值和比较的常见翻车点
支持整体赋值(
),但绝不支持整体比较或判空——这是新手最常栽跟头的地方。
❌ 错误写法:
→ 编译失败,报
✅ 正确做法:逐字段比,
❌ 不能写
→ 语法错误,记录类型没有整体空值语义
✅ 判空只能字段级:
注意:整体赋值是值拷贝,修改
不会影响
;但若 RECORD 里有
或对象类型,行为会不同(极少见,一般避开)
能不能在 INSERT / UPDATE 里直接用 RECORD 变量
能,但有严格限制:必须字段顺序、数量、类型完全匹配目标表,且不能含虚拟列或只读列。
插入:用
,前提是
的字段顺序和
的列顺序一致(不是名字匹配)
更新整行:用
,同样要求字段顺序对齐;如果只想更新部分字段,还是老实用
别指望用 RECORD 绕过约束:如果表有
列而
对应字段是
,DML 一样报错
性能上无额外开销,本质还是展开成字段列表,但可读性提升明显——尤其字段多、逻辑分组清晰时
真正麻烦的是嵌套 RECORD 或动态字段数场景,这时候就得换
对象类型,或者干脆用关联数组(
)+ 批量 DML。但日常单行结构封装,
已经够稳、够快、够直白。
typeis recordnot nullTYPEDECLAREVARCHAR2(50)employees.salary%TYPERECORDtimeout NUMBER DEFAULT 30SELECT INTONOT NULLORA-06502: PL/SQL: numeric or value error%ROWTYPETYPE IS RECORDorder_idstatus_codeprocessed_atSYSDATEdept_namedept_idJOIN%ROWTYPERECORDr2 := r1IF r1 = r2 THEN ...PLS-00306: wrong number or types of argumentsIF r1.id = r2.id AND r1.name = r2.name THEN ...IF r1 IS NULL THENIF r1.id IS NULL OR r1.name IS NULL THENr2r1REF CURSORINSERT INTO t VALUES v_recv_rectUPDATE t SET ROW = v_rec WHERE ...SET col1 = v_rec.col1, col2 = v_rec.col2NOT NULLv_recNULLCREATE TYPETABLE OF RECORDTYPE ... IS RECORD