和其他語言一樣,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的一部分。現在定義好了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)