【发布时间】:2020-12-16 13:04:37
【问题描述】:
我知道冻结 UDT 列中的字段是不可能的,并且需要更新整个记录,在这种情况下,这是否意味着无法更新冻结的 UDT 列,并且如果存在冻结 UDT 列的字段更新的情况,在这种情况下,必须插入新记录并删除旧记录?
【问题讨论】:
我知道冻结 UDT 列中的字段是不可能的,并且需要更新整个记录,在这种情况下,这是否意味着无法更新冻结的 UDT 列,并且如果存在冻结 UDT 列的字段更新的情况,在这种情况下,必须插入新记录并删除旧记录?
【问题讨论】:
您是正确的,您不能更新冻结的 UDT 列的单个字段,但您可以更新整个列的值。您不需要删除以前的记录。直接更新字段就好了。让我用我在Astra 上创建的示例进行说明。
这是一个存储用户地址的用户定义类型:
CREATE TYPE address (
number int,
street text,
city text,
zip int
)
这是用户表的定义:
CREATE TABLE users (
name text PRIMARY KEY,
address frozen<address>
)
在此表中,有一个用户,其地址存储为:
cqlsh> SELECT * FROM users ;
name | address
-------+----------------------------------------------------------------
alice | {number: 100, street: 'Main Rd', city: 'Melbourne', zip: 3000}
假设门牌号不正确。如果我们尝试只更新街道号码字段:
cqlsh> UPDATE users SET address = {number: 456} WHERE name = 'alice';
我们最终会得到一个只有门牌号的地址:
cqlsh> SELECT * FROM users ;
name | address
-------+----------------------------------------------------
alice | {number: 456, street: null, city: null, zip: null}
这是因为整个值(不仅仅是街道编号字段)都被更新覆盖了。更新街道号码的正确方法是为地址的所有字段显式设置一个值:
cqlsh> UPDATE users SET address = {number: 456, street: 'Main Rd', city: 'Melbourne', zip: 3000} WHERE name = 'alice';
所以我们最终得到:
cqlsh> SELECT * FROM users ;
name | address
-------+----------------------------------------------------------------
alice | {number: 456, street: 'Main Rd', city: 'Melbourne', zip: 3000}
干杯!
【讨论】:
您可以更新已冻结的 UDT 列,但您需要为该 UDT 内的字段插入所有值。所以你只能对该列进行正常更新
UPDATE table SET udt_col = new_value WHERE pk = ....
无需先删除某些内容,等等。
基本上,冻结值只是通过序列化 UDT 或集合获得的 blob,并存储为行内的一个单元格并具有单个时间戳。这与非冻结值不同,在非冻结值中,不同的 UDT/集合可以存储在不同的位置,并具有不同的时间戳。
【讨论】:
null 覆盖...因此,如果要更新一个字段,则需要读取当前版本,更新其中的字段,然后将更新后的值放回去