用户定义类型 #

一、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要点:

  1. 封装字段:将相关字段组合在一起
  2. FROZEN:冻结后才能在集合中使用
  3. 嵌套支持:UDT可以嵌套其他UDT
  4. 修改限制:只能添加字段和重命名
  5. 删除限制:被使用时不能删除
  6. 提高可读性:使数据模型更清晰

下一步,让我们学习计数器!

最后更新:2026-03-27