和其他語言一樣,CQL也支持一系列靈活的數據類型,包括基本的數據類型,集合類型以及用戶自定義數據類(User-Defined Types, UDTs)。本文將介紹CQL支持的數據類型。
數字數據類型(Numeric Data Types)
CQL支持的數字數據類型包括整型和浮點型,這些數據類型和Java的標準數據類型類似。包括以下幾種:
int:32位有符號整型,和Java中的int類似;
bigint:64位長整型,和Java中的long類似;
smallint:16位有符號整型,和Java中的short類似,Apache Cassandra 2.2開始引入;
tinyint:8位有符號整型,和Java中的tinyint類似,Apache Cassandra 2.2開始引入;
varint:可變精度有符號整數,和Java中的java.math.BigInteger類似;
float:32位IEEE-754浮點型,和Java中的float類似;
double:64位IEEE-754浮點型,和Java中的double類似;
decimal:可變精度的decimal,和Java中的java.math.BigDecimal類似。
文本數據類型(Textual Data Types)
CQL中提供了兩種數據類型用于存放文本類型:
text, varchar:UTF-8編碼的字符串,這個在CQL中使用的比較普遍;
ascii:ASCII字符串。
時間和標識符數據類型(Time and Identity Data Types)
timestamp:時間可以使用64位有符號的整數表示,但是一般為了可讀性,我們會選擇支持ISO 8601標準的時間戳表示。建議在使用時間戳的時候都指定時區,而不是依賴系統的時區。
date, time:在Apache Cassandra 2.1版本之前只支持timestamp類型,里面包含了日期和時間;從Cassandra 2.2版本開始引入了date和time時間類型,分別表示日期和時間。和timestamp一樣,這個也是支持ISO 8601標準的。
uuid:通用唯一識別碼(universally unique identifier,UUID)是128位數據類型,其實現包含了很多種類型,其中最有名的為Type 1和Type 4。CQL中的uuid實現是Type 4 UUID,其實現完全是基于隨機數的。UUID的數據類似于ab7c46ac-c194-4c71-bb03-0f64986f3daa,uuid類型通常用作代理鍵,可以單獨使用,也可以與其他值組合使用。由于UUID的長度有限,因此并不能絕對保證它們是唯一的。我們可以在CQL中使用uuid() 獲取Type 4 UUID。
timeuuid:這個是Type 1 UUID,它的實現基于計算機的MAC地址,系統時間和用于防止重復的序列號。CQL中提供了now(), dateOf()以及unixTimestampOf()等函數來操作timeuuid數據類型。由于這些簡便的函數,timeuuid的使用頻率比uuid數據類型多。
集合數據類型
這種數據類型可以存儲集合數據類型,set里面的元素存儲是無序的,但是cql返回的數據是有序的。set里面可以存儲前面介紹的數據類型,也可以是用戶自定義數據類型,甚至是其他集合類型。
下述案例以存儲email信息為例,來說明set的使用:
cqlsh:test_keyspace> CREATE TABLE test_user (first_name text , last_name text,emails set<text>, PRIMARY KEY (first_name)) ;
cqlsh:test_keyspace> INSERT INTO test_user (first_name, last_name,emails) VALUES ('Wu', 'Shi',{'iteblog@iteblog.com'});
cqlsh:test_keyspace> SELECT * FROM test_user WHERE first_name = 'Wu';
first_name | emails | last_name
------------+-------------------------+-----------
Wu | {'iteblog@iteblog.com'} | Shi
(1 rows)
上述命令表示為first_name為Wu的數據添加了email信息。如果您還需要往里面加一些email信息,可以使用下述語法:
cqlsh:test_keyspace> UPDATE test_user SET emails = emails + {'cassandra@iteblog.com' } WHERE first_name = 'Wu';
cqlsh:test_keyspace> SELECT * FROM test_user WHERE first_name = 'Wu';
first_name | emails | last_name
------------+--------------------------------------------------+-----------
Wu | {'cassandra@iteblog.com', 'iteblog@iteblog.com'} | Shi
(1 rows)
first_name為Wu的記錄已經添加了兩條email信息了。如果您需要刪除email,可以使用下述語法:
cqlsh:test_keyspace> UPDATE test_user SET emails = emails - {'cassandra@iteblog.com'} WHERE first_name = 'Wu';
cqlsh:test_keyspace> SELECT * FROM test_user WHERE first_name = 'Wu';
first_name | emails | last_name
------------+-------------------------+-----------
Wu | {'iteblog@iteblog.com'} | Shi
(1 rows)
cqlsh:test_keyspace> UPDATE test_user SET emails ={} WHERE first_name = 'Wu';
cqlsh:test_keyspace> SELECT * FROM test_user WHERE first_name = 'Wu';
first_name | emails | last_name
------------+--------+-----------
Wu | null | Shi
(1 rows)
上述命令表示使用SET emails = emails - {'cassandra@iteblog.com'}
從用戶email列表里面刪除email,使用SET emails ={}
清空用戶的email。
list
list包含了有序的列表數據,默認情況下,數據是按照插入順序保存的。以test_user表為例,如果需要往該表中添加電話等信息,示例如下:
cqlsh:test_keyspace> ALTER TABLE test_user ADD phone list<text>;
cqlsh:test_keyspace> UPDATE test_user SET phone = ['1311234****' ] WHERE first_name = 'Wu';
cqlsh:test_keyspace> SELECT * FROM test_user WHERE first_name = 'Wu';
first_name | emails | last_name | phone
------------+--------+-----------+-----------------
Wu | null | Shi | ['1311234****']
(1 rows)
上述命令表示給first_name為Wu的記錄添加了電話信息。如果需要再添加電話信息,其操作和set添加信息類似,例如:
cqlsh:test_keyspace> UPDATE test_user SET phone = phone + ['1551111****' ] WHERE first_name = 'Wu';
cqlsh:test_keyspace> SELECT * FROM test_user WHERE first_name = 'Wu';
first_name | emails | last_name | phone
------------+--------+-----------+--------------------------------
Wu | null | Shi | ['1311234****', '1551111****']
(1 rows)
可以看出,新加入的電話號碼被放在list的后面了。如果使用下述語句,則可以往電話號碼的前面添加信息:
cqlsh:test_keyspace> UPDATE test_user SET phone = ['1334444****' ] + phone WHERE first_name = 'Wu';
cqlsh:test_keyspace> SELECT * FROM test_user WHERE first_name = 'Wu';
first_name | emails | last_name | phone
------------+--------+-----------+-----------------------------------------------
Wu | null | Shi | ['1334444****', '1311234****', '1551111****']
(1 rows)
您可以使用下標從list數據類型中修改數據:
cqlsh:test_keyspace> UPDATE test_user SET phone[1] = '1888888****' WHERE first_name = 'Wu';
cqlsh:test_keyspace> SELECT * FROM test_user WHERE first_name = 'Wu';
first_name | emails | last_name | phone
------------+--------+-----------+-----------------------------------------------
Wu | null | Shi | ['1334444****', '1888888****', '1551111****']
(1 rows)
下標為1的元素被修改了。也可以使用下標刪除數據:
cqlsh:test_keyspace> DELETE phone[2] from test_user WHERE first_name = 'Wu';
cqlsh:test_keyspace> SELECT * FROM test_user WHERE first_name = 'Wu';
first_name | emails | last_name | phone
------------+--------+-----------+--------------------------------
Wu | null | Shi | ['1334444****', '1888888****']
(1 rows)
當然,刪除元素也可以使用SET phone_numbers = phone_numbers - [ '1334444****' ]
。
map
map數據類型包含了key/value鍵值對。key和value可以是任何類型,除了counter類型。使用如下:
cqlsh:test_keyspace> ALTER TABLE test_user ADD login_sessions map<timeuuid, int>;
cqlsh:test_keyspace> UPDATE test_user SET login_sessions = {now(): 13, now(): 18} WHERE first_name = 'Wu';
cqlsh:test_keyspace> SELECT first_name, login_sessions FROM test_user WHERE first_name = 'Wu';
first_name | login_sessions
------------+--------------------------------------------------------------------------------------
Wu | {1cc61ff0-5f8b-11e9-ac3a-5336cd8118f6: 13, 1cc61ff1-5f8b-11e9-ac3a-5336cd8118f6: 18}
(1 rows)
其他簡單數據類型
boolean:取值只能為true/false,在cql中輸入的這兩個值無論大小如何寫法,其輸出都是True/False;
blob:二進制大對象(binary large object)是任意字節數組的術語簡稱。這個類型在存儲媒體或者其他二進制數據類型時很有用,Cassandra并不會檢查其中存儲的二進制數據是否有效。Cassandra中二進制大對象是以十六進制存儲的,如果想將任意的文本數據類型使用blob存儲,可以使用textAsBlob()函數實現。
inet:這個數據類型可以表示IPv4或IPv6網絡地址。cqlsh接受用于定義IPv4地址的任何合法格式,包括包含十進制,八進制或十六進制值的點或非點式表示。CQL統一輸出為192.168.XX.XX這種格式的IP地址。
counter:計數器數據類型是64位有符號整數,其值不能直接設置,而只能遞增或遞減。計數器類型的使用有一些特殊限制,它不能用作主鍵的一部分;如果使用計數器,則除primary key列之外的所有列都必須是計數器。
用戶自定義數據類型(User-Defined Types)
如果Cassandra中內置的數據類型無法滿足您的需求,您還可以使用自定義數據類型。例如,需要使用一個字段存儲用戶的地址信息,需要獲取地址的郵編、街道等信息。如果使用text來存儲是不能滿足我們的需求的,此時您可以自定義數據類型,示例如下:
cqlsh:test_keyspace> CREATE TYPE address (
... street text,
... city text,
... state text,
... zip_code int);
上述語句定義了address數據類型。需要注意的是,Cassandra中數據類型的定義是keyspace范圍的,表明 address數據類型只能在test_keyspace里面使用。如果您使用DESCRIBE KEYSPACE test_keyspace
,可以看到address數據類型屬于test_keyspace的一部分?,F在定義好了address數據類型,使用示例如下:
cqlsh:test_keyspace> ALTER TABLE test_user ADD addresses map<text, frozen<address>>;
cqlsh:test_keyspace> UPDATE test_user SET addresses = addresses + {'home': { street: 'shangdi 9', city: 'Beijing', state: 'Beijing', zip_code: 100080} } WHERE first_name = 'Wu';
cqlsh:test_keyspace> SELECT first_name, addresses FROM test_user WHERE first_name = 'Wu';
first_name | addresses
------------+--------------------------------------------------------------------------------------
Wu | {'home': {street: 'shangdi 9', city: 'Beijing', state: 'Beijing', zip_code: 100080}}
(1 rows)