用户定义类型 #
一、UDT概述 #
1.1 什么是UDT #
用户定义类型(UDT)允许创建自定义的复合数据类型。
text
UDT结构示例:
address类型
├── street: TEXT
├── city: TEXT
├── state: TEXT
└── zip_code: TEXT
使用:
{
street: '朝阳路100号',
city: '北京',
state: '北京',
zip_code: '100000'
}
1.2 UDT特点 #
text
UDT特点:
优点
├── 封装相关字段
├── 提高代码可读性
├── 支持嵌套
└── 可在集合中使用
限制
├── 需要FROZEN才能修改
├── 不能自引用
└── 修改有限制
二、创建UDT #
2.1 基本语法 #
sql
CREATE TYPE [IF NOT EXISTS] [keyspace_name.]type_name (
field_name data_type,
field_name data_type,
...
);
2.2 创建示例 #
sql
-- 创建地址类型
CREATE TYPE address (
street TEXT,
city TEXT,
state TEXT,
zip_code TEXT,
country TEXT
);
-- 创建联系方式类型
CREATE TYPE contact (
phone TEXT,
email TEXT,
wechat TEXT
);
-- 创建嵌套UDT
CREATE TYPE full_address (
location FROZEN<address>,
contact FROZEN<contact>,
is_primary BOOLEAN
);
三、使用UDT #
3.1 创建表 #
sql
-- 使用UDT创建表
CREATE TABLE users (
user_id UUID PRIMARY KEY,
name TEXT,
home_address FROZEN<address>,
work_address FROZEN<address>,
contacts LIST<FROZEN<contact>>
);
3.2 插入数据 #
sql
-- 插入UDT数据
INSERT INTO users (user_id, name, home_address)
VALUES (
uuid(),
'张三',
{
street: '朝阳路100号',
city: '北京',
state: '北京',
zip_code: '100000',
country: '中国'
}
);
-- 插入嵌套UDT
INSERT INTO users (user_id, name, home_address, contacts)
VALUES (
uuid(),
'李四',
{street: '海淀路200号', city: '北京', state: '北京', zip_code: '100080', country: '中国'},
[{phone: '13800138000', email: 'li@example.com', wechat: 'wx_li'}]
);
3.3 更新数据 #
sql
-- 更新整个UDT
UPDATE users
SET home_address = {
street: '新地址',
city: '上海',
state: '上海',
zip_code: '200000',
country: '中国'
}
WHERE user_id = ?;
-- 更新UDT中的单个字段(需要非FROZEN)
-- 注意:FROZEN UDT不能部分更新
3.4 查询数据 #
sql
-- 查询整个UDT
SELECT user_id, name, home_address FROM users WHERE user_id = ?;
-- 查询UDT中的特定字段
SELECT user_id, home_address.city, home_address.country
FROM users
WHERE user_id = ?;
四、FROZEN关键字 #
4.1 FROZEN的作用 #
text
FROZEN作用:
序列化
├── UDT序列化为单个值
├── 整体读取和写入
└── 不能部分更新
用途
├── 作为主键的一部分
├── 在集合中使用
└── 嵌套UDT
4.2 FROZEN vs 非FROZEN #
sql
-- FROZEN UDT
CREATE TABLE frozen_example (
user_id UUID PRIMARY KEY,
address FROZEN<address>
);
-- 非FROZEN UDT(可以部分更新)
CREATE TABLE non_frozen_example (
user_id UUID PRIMARY KEY,
address address
);
-- 非FROZEN可以更新单个字段
UPDATE non_frozen_example
SET address.city = '上海'
WHERE user_id = ?;
-- FROZEN必须整体更新
UPDATE frozen_example
SET address = {street: '...', city: '上海', ...}
WHERE user_id = ?;
五、UDT集合 #
5.1 UDT在集合中 #
sql
-- UDT List
CREATE TABLE user_addresses (
user_id UUID PRIMARY KEY,
addresses LIST<FROZEN<address>>
);
INSERT INTO user_addresses (user_id, addresses)
VALUES (
uuid(),
[
{street: '地址1', city: '北京', state: '北京', zip_code: '100000', country: '中国'},
{street: '地址2', city: '上海', state: '上海', zip_code: '200000', country: '中国'}
]
);
-- UDT Set
CREATE TABLE unique_contacts (
user_id UUID PRIMARY KEY,
contacts SET<FROZEN<contact>>
);
-- UDT Map值
CREATE TABLE user_contacts (
user_id UUID PRIMARY KEY,
contacts MAP<TEXT, FROZEN<contact>>
);
INSERT INTO user_contacts (user_id, contacts)
VALUES (
uuid(),
{
'home': {phone: '13800138000', email: 'home@example.com', wechat: 'wx_home'},
'work': {phone: '13900139000', email: 'work@example.com', wechat: 'wx_work'}
}
);
六、修改UDT #
6.1 添加字段 #
sql
-- 添加新字段
ALTER TYPE address ADD country TEXT;
-- 新字段默认值为NULL
-- 已有数据的country字段为NULL
6.2 重命名字段 #
sql
-- 重命名字段
ALTER TYPE address RENAME zip_code TO postal_code;
6.3 修改限制 #
text
UDT修改限制:
可以
├── 添加新字段
├── 重命名字段
└── 添加新UDT
不能
├── 删除字段
├── 修改字段类型
├── 修改字段顺序
└── 删除UDT(如果被使用)
七、删除UDT #
7.1 删除语法 #
sql
-- 删除UDT
DROP TYPE address;
-- 使用IF EXISTS
DROP TYPE IF EXISTS address;
7.2 删除限制 #
text
删除限制:
不能删除
├── 被表使用的UDT
├── 被其他UDT引用的UDT
└── 被函数使用的UDT
需要先
├── 删除使用该UDT的表
├── 删除引用该UDT的其他UDT
└── 删除使用该UDT的函数
八、最佳实践 #
8.1 设计建议 #
text
UDT设计建议:
适合
├── 相关字段组合
├── 复用数据结构
├── 提高可读性
└── 嵌套数据
不适合
├── 大量字段
├── 频繁部分更新
└── 独立查询的字段
8.2 命名规范 #
sql
-- 推荐命名
CREATE TYPE user_address ...
CREATE TYPE order_item ...
CREATE TYPE product_price ...
-- 类型名大写开头
-- 字段名小写下划线
九、总结 #
UDT要点:
- 封装字段:将相关字段组合在一起
- FROZEN:冻结后才能在集合中使用
- 嵌套支持:UDT可以嵌套其他UDT
- 修改限制:只能添加字段和重命名
- 删除限制:被使用时不能删除
- 提高可读性:使数据模型更清晰
下一步,让我们学习计数器!
最后更新:2026-03-27