Cassandra 查询语言 (CQL) v3.4.3
\{toc:maxLevel=3}
CQL 语法
前言
本文档描述了 Cassandra 查询语言 (CQL) 版本 3。CQL v3 与 CQL v2 不向后兼容,并且在许多方面与之不同。请注意,本文档描述了语言的最新版本。但是,更改部分提供了 CQL v3 不同版本之间的差异。
CQL v3 提供了一个非常接近 SQL 的模型,其含义是数据被放入包含行和列的表中。因此,在本文档中使用时,这些术语(表、行和列)具有与 SQL 中相同的定义。但请注意,它们并不引用 Cassandra 内部实现以及 Thrift 和 CQL v2 API 中的行和列的概念。
惯例
为了帮助指定 CQL 语法,我们将在本文档中使用以下惯例
-
语言规则将以类似 BNF 的符号表示
bc(syntax). ::= TERMINAL
-
非终结符符号将使用
<尖括号>
。 -
作为 BNF 的其他快捷符号,我们将使用传统的正则表达式符号(
?
、+
和*
)来表示给定符号是可选的和/或可以重复。我们还允许括号对符号进行分组,并使用[<字符>]
符号来表示<字符>
中的任何一个。 -
语法是为了文档目的而提供的,并省略了一些小细节。例如,
CREATE TABLE
语句中的最后一个列定义是可选的,但如果存在,则受支持,即使本文档中提供的语法表明不受支持。 -
示例代码将以代码块的形式提供
bc(sample). SELECT sample_usage FROM cql;
-
在正文中对关键字或 CQL 代码片段的引用将以
固定宽度字体
显示。
标识符和关键字
CQL 语言使用标识符(或名称)来标识表、列和其他对象。标识符是一个与正则表达式
匹配的标记。[a-zA-Z0-9_]
*
许多这样的标识符(如 SELECT
或 WITH
)是关键字。它们对语言具有固定的含义,并且大多数是保留的。这些关键字的列表可以在 附录 A 中找到。
标识符和(未加引号的)关键字不区分大小写。因此,SELECT
与 select
或 sElEcT
相同,例如,myId
与 myid
或 MYID
相同。经常使用的一种惯例(特别是本文档的示例)是为关键字使用大写,为其他标识符使用小写。
还有一种标识符,称为带引号的标识符,它通过用双引号 ("
) 括起任意字符序列来定义。带引号的标识符永远不是关键字。因此,"select"
不是保留关键字,可用于引用列,而 select
会引发解析错误。此外,与不带引号的标识符和关键字相反,带引号的标识符区分大小写("My Quoted Id"
与 "my quoted id"
不同)。与
匹配的全小写带引号标识符等效于通过删除双引号获得的不带引号标识符(因此,[a-zA-Z0-9_]
*"myid"
等效于 myid
和 myId
,但不同于 "myId"
)。在带引号的标识符内,可以重复双引号字符以对其进行转义,因此 "foo "" bar"
是一个有效的标识符。
警告:带引号的标识符允许声明具有任意名称的列,这些名称有时会与服务器使用的特定名称冲突。例如,在使用条件更新时,服务器将响应包含名为 "[applied]"
的特殊结果的结果集。如果你已声明具有此类名称的列,这可能会混淆某些工具,因此应避免这样做。通常,应优先使用不带引号的标识符,但如果你使用带引号的标识符,则强烈建议避免任何用方括号括起来的名称(如 "[applied]"
)和任何看起来像函数调用的名称(如 "f(x)"
)。
常量
CQL 定义了以下类型的常量:字符串、整数、浮点数、布尔值、UUID 和 blob
-
字符串常量是用单引号 (
'
) 括起来的任意字符序列。可以通过重复单引号在字符串中包含单引号,例如'It''s raining today'
。这些不能与使用双引号的带引号标识符混淆。 -
整数常量由
'-'?[0-9]+
定义。 -
浮点数常量由
'-'?[0-9]+('.'[0-9]*)?([eE][+-]?[0-9+])?
定义。除此之外,NaN
和Infinity
也是浮点数常量。 -
布尔常量为
true
或false
,不区分大小写(即True
是一个有效的布尔常量)。 -
UUID 常量由
hex{8}-hex{4}-hex{4}-hex{4}-hex{12}
定义,其中hex
是十六进制字符,例如[0-9a-fA-F]
,{4}
是此类字符的数量。 -
blob 常量是由
0[xX](hex)+
定义的十六进制数字,其中hex
是十六进制字符,例如[0-9a-fA-F]
。
有关如何对这些常量进行类型化,请参阅 数据类型部分。
项
CQL 有项的概念,它表示 CQL 支持的值的类型。项由以下定义
term::= constant | literal | function_call | arithmetic_operation | type_hint | bind_marker
literal::= collection_literal | vector_literal | udt_literal | tuple_literal
function_call::= identifier '(' [ term (',' term)* ] ')'
arithmetic_operation::= '-' term | term ('+' | '-' | '*' | '/' | '%') term
type_hint::= '(' cql_type ')' term
bind_marker::= '?' | ':' identifier
因此,项之一是
注释
CQL 中的注释是以双破折号 (--
) 或双斜杠 (//
) 开头的行。
多行注释也通过在 /
和 /
中包含支持(但不支持嵌套)。
bc(sample).
— 这是一个注释
/* 这是
多行注释 */
语句
CQL 由语句组成。与 SQL 中一样,这些语句可以分为 3 类
-
数据定义语句,允许设置和更改数据存储方式。
-
数据操作语句,允许更改数据
-
查询,用于查找数据
所有语句都以分号 (;
) 结尾,但在处理单个语句时可以省略该分号。支持的语句在以下部分中进行描述。在描述所述语句的语法时,我们将重复使用下面定义的非终结符号
bc(syntax)..
::= 任何带引号或不带引号的标识符,不包括保留关键字
::= ( `.')?
::= 字符串常量
::= 整数常量
::= 浮点数常量
::= |
::= uuid 常量
::= 布尔常量
::= blob 常量
::=
|
|
|
|
::= ?'
,' )*)? `)'
| `:'
::=
|
|
| `(' ( (
::=
|
|
::= `\{' ( `:' ( `,' `:' )* )? `}'
::= `\{' ( ( `,' )* )? `}'
::= `[' ( ( `,' )* )? `]'
::=
::= (AND )*
::= =' ( | | )
p.
请注意,上述语法并非所有可能的产生式在实践中都是有效的。最值得注意的是,目前不允许在 <collection-literal>
中使用 <variable>
和嵌套 <collection-literal>
。
<variable>
可以是匿名的(问号 (?
))或命名的(标识符前加 :
)。两者都为 预处理语句 声明绑定变量。匿名变量和命名变量之间的唯一区别是命名变量更容易引用(具体方式取决于所使用的客户端驱动程序)。
<properties>
产生式由创建和更改键空间和表的语句使用。每个 <property>
都是一个简单属性,在这种情况下它只具有一个值,或一个映射属性,在这种情况下它的值是一个对子选项进行分组的映射。以下将其中一个或另一个称为属性的类型(简单或映射)。
<tablename>
将用于标识表。这是一个表示表名的标识符,可以由键空间名称前缀。如果提供了键空间名称,则允许在当前活动键空间之外的另一个键空间中标识表(当前活动键空间通过 USE
语句设置)。
有关支持的 <function>
,请参阅 函数 部分。
字符串可以用单引号或两个美元字符括起来。引入第二个语法是为了允许包含单引号的字符串。此类字符串的典型候选对象是用户定义函数的源代码片段。
样本
bc(sample)..
`some string value'
双美元字符串可以包含单引号 ’
p.
数据定义
CREATE KEYSPACE
语法
bc(syntax)..
::= CREATE KEYSPACE (IF NOT EXISTS)? WITH
p.
样本
bc(sample)..
CREATE KEYSPACE Excelsior
WITH replication = \{’class’: `SimpleStrategy', `replication_factor' : 3};
CREATE KEYSPACE Excalibur
WITH replication = \{’class’: NetworkTopologyStrategy', `DC1' : 1, `DC2' : 3}
语句创建一个新的顶级键空间。键空间是一个定义复制策略和一组表的某些选项的命名空间。有效的键空间名称是仅由字母数字字符组成的标识符,其长度小于或等于 32。请注意,作为标识符,键空间名称不区分大小写:对区分大小写的键空间名称使用带引号的标识符。
AND durable_writes = false;
p.
`CREATE KEYSPACE
CREATE KEYSPACE
支持的 <properties>
为
名称 | 类型 | 是否必须 | 默认值 | 说明 |
---|---|---|---|---|
|
映射 |
是 |
用于键空间的复制策略和选项。 |
|
|
简单 |
否 |
true |
是否对该键空间上的更新使用提交日志(自行承担禁用此选项的风险!)。 |
replication
<property>
是必须的。它至少必须包含定义要使用的复制策略类的 'class'
子选项。其余子选项取决于该复制策略类。默认情况下,Cassandra 支持以下 'class'
-
'SimpleStrategy'
:一个简单的策略,为整个集群定义了一个简单的复制因子。支持的唯一子选项是'replication_factor'
,用于定义该复制因子,并且是必须的。 -
'NetworkTopologyStrategy'
:一个复制策略,允许为每个数据中心独立设置复制因子。其余子选项是键值对,其中每次键都是数据中心名称,值是该数据中心复制因子。
尝试创建已存在的键空间将返回错误,除非使用了 IF NOT EXISTS
选项。如果使用了该选项,如果键空间已存在,则该语句将为无操作。
USE
语法
bc(语法)。::= USE
样本
bc(示例)。USE myApp;
USE
语句将现有键空间名称作为参数,并将其设置为每个连接当前工作键空间。除非另有说明,否则所有后续键空间特定操作将在所选键空间的上下文中执行,直到发出另一个 USE 语句或连接终止。
ALTER KEYSPACE
语法
bc(syntax)..
::= ALTER KEYSPACE (IF EXISTS)? WITH
p.
样本
bc(sample)..
ALTER KEYSPACE Excelsior
WITH replication = \{’class’: `SimpleStrategy', `replication_factor' : 4};
ALTER KEYSPACE
语句更改现有键空间的属性。支持的 <properties>
与 CREATE KEYSPACE
语句相同。
DROP KEYSPACE
语法
bc(语法)。::= DROP KEYSPACE ( IF EXISTS )?
样本
bc(示例)。DROP KEYSPACE myApp;
DROP KEYSPACE
语句会导致立即不可逆地删除现有键空间,包括其中的所有列族以及这些列族中包含的所有数据。
如果键空间不存在,该语句将返回一个错误,除非使用了 IF EXISTS
,在这种情况下,操作将为无操作。
CREATE TABLE
语法
bc(syntax)..
::= CREATE ( TABLE | COLUMNFAMILY ) ( IF NOT EXISTS )?
`(' ( `,' )* `)'
( WITH ( AND )* )?
::= ( STATIC )? ( PRIMARY KEY )?
| PRIMARY KEY `(' ( `,' )* `)'
::=
| (' (
,' )* `)'
::=
| COMPACT STORAGE
| CLUSTERING ORDER
p.
样本
bc(sample)..
CREATE TABLE monkeySpecies (
species text PRIMARY KEY,
common_name text,
population varint,
average_size int
) WITH comment=`Important biological records';
CREATE TABLE timeline (
userid uuid,
posted_month int,
posted_time uuid,
body text,
posted_by text,
PRIMARY KEY (userid, posted_month, posted_time)
) WITH compaction = \{ class' : `LeveledCompactionStrategy' };
语句创建一个新表。每个此类表都是一组行(通常表示相关实体),它为这些行定义了许多属性。表由 名称 定义,它定义构成表行的列,并具有多个 选项。请注意,
p.
`CREATE TABLECREATE COLUMNFAMILY
语法作为 CREATE TABLE
的别名(出于历史原因)受到支持。
尝试创建已存在的表将返回一个错误,除非使用了 IF NOT EXISTS
选项。如果使用了该选项,如果表已存在,该语句将为无操作。
<tablename>
有效的表名称与有效的 键空间名称 相同(长达 32 个字符的字母数字标识符)。如果仅提供了表名称,则在当前键空间(参见 USE
)中创建表,但如果它由现有键空间名称作为前缀(参见 <tablename>
语法),它将在指定的键空间中创建(但不会更改当前键空间)。
<column-definition>
CREATE TABLE
语句定义表行可以拥有的列。列由其名称(标识符)和类型定义(有关允许的类型及其属性的更多详细信息,请参见 数据类型 部分)。
在表中,行由其 PRIMARY KEY
(或更简单的键)唯一标识,因此所有表定义必须定义一个 PRIMARY KEY(且仅定义一个)。PRIMARY KEY
由表中定义的一个或多个列组成。如果 PRIMARY KEY
仅为一列,则可以在列定义后直接指定该列。否则,必须通过在 PRIMARY KEY
后跟括号中由逗号分隔的组成键的列名称列表来指定它。请注意
bc(sample).
CREATE TABLE t (
k int PRIMARY KEY,
other text
)
等效于
bc(sample).
CREATE TABLE t (
k int,
other text,
PRIMARY KEY (k)
)
分区键和聚类列
在 CQL 中,为 PRIMARY KEY
定义列的顺序很重要。键的第一列称为分区键。它具有以下属性:所有共享相同分区键的行(实际上甚至跨表)都存储在同一物理节点上。此外,对给定表共享相同分区键的行进行插入/更新/删除操作时,这些操作将以原子方式和隔离方式执行。请注意,可以有复合分区键,即使用额外的圆括号集来定义形成分区键的列,从而形成由多列组成的分区键。
PRIMARY KEY
定义的剩余列(如果有)称为__聚类列。在给定的物理节点上,给定分区键的行按聚类列产生的顺序存储,从而使按该聚类顺序检索行特别高效(请参阅 SELECT
)。
STATIC
列
在表定义中,某些列可以声明为 STATIC
。静态列将由属于同一分区(具有相同分区键)的所有行“共享”。例如,在
bc(sample).
CREATE TABLE test (
pk int,
t int,
v text,
s text static,
PRIMARY KEY (pk, t)
);
INSERT INTO test(pk, t, v, s) VALUES (0, 0, `val0', `static0');
INSERT INTO test(pk, t, v, s) VALUES (0, 1, `val1', `static1');
SELECT * FROM test WHERE pk=0 AND t=0;
最后一个查询将返回 'static1'
作为 s
的值,因为 s
是静态的,因此第二次插入修改了这个“共享”值。但是请注意,静态列仅在给定的分区内是静态的,如果在上面的示例中两行来自不同的分区(即如果它们具有不同的 `pk` 值),则第二次插入不会修改第一行的 s
值。
允许静态列时会应用一些限制
-
具有
COMPACT STORAGE
选项的表(请参阅下文)不能有它们 -
没有聚类列的表不能有静态列(在没有聚类列的表中,每个分区只有一行,因此每列本质上都是静态的)。
-
只有非
PRIMARY KEY
列可以是静态的
<option>
CREATE TABLE
语句支持许多选项,这些选项控制新表的配置。可以在 WITH
关键字后指定这些选项。
第一个选项是 COMPACT STORAGE
。此选项主要针对在 CQL3 之前创建的定义向后兼容(有关更多详细信息,请参阅 www.datastax.com/dev/blog/thrift-to-cql3)。此选项还提供了稍微紧凑一些的磁盘数据布局,但代价是降低了表的灵活性和可扩展性。最值得注意的是,COMPACT STORAGE
表不能有集合或静态列,并且具有至少一个聚类列的 COMPACT STORAGE
表仅支持一列(而不是 0 或多于 1 列)不属于 PRIMARY KEY
定义(这尤其意味着您不能在创建后添加或删除列)。由于这些原因,除了上面提到的向后兼容性原因之外,不建议在其他情况下使用 COMPACT STORAGE
。
另一个选项是 CLUSTERING ORDER
。它允许定义磁盘上的行顺序。它采用聚类列名称的列表,其中每个名称都带有磁盘上的顺序(升序或降序)。请注意,此选项会影响 在 SELECT
期间允许哪些 ORDER BY
。
表创建支持以下其他 <property>
选项 | 类型 | 默认值 | 说明 |
---|---|---|---|
|
简单 |
无 |
自由格式、可读的注释。 |
|
简单 |
864000 |
在垃圾回收墓碑(删除标记)之前等待的时间。 |
|
简单 |
0.00075 |
sstable 布隆过滤器的目标误报概率。将调整布隆过滤器的尺寸以提供所提供的概率(因此降低该值会影响布隆过滤器在内存和磁盘中的尺寸) |
|
简单 |
0 |
表中默认的过期时间(``TTL''),单位为秒。 |
|
映射 |
见下文 |
压缩选项,请参见下文。 |
|
映射 |
见下文 |
压缩选项,请参见下文。 |
|
映射 |
见下文 |
缓存选项,请参见下文。 |
|
简单 |
1.0 |
此选项定义了在读取过程中检查校验和以检测位腐烂并防止损坏传播到其他副本的概率。默认值为 1,即在每次读取数据块时应用校验和。设置为 0 以禁用校验和检查,例如设置为 0.5 以检查每次读取。 由于技术限制,我们目前仅对压缩文件应用此选项。如果表中未启用压缩,则不会验证任何校验和。 |
压缩选项
compaction
属性至少必须定义 'class'
子选项,该选项定义要使用的压缩策略类。默认支持的类是 'SizeTieredCompactionStrategy'
、'LeveledCompactionStrategy'
和 'TimeWindowCompactionStrategy'
。可以通过将完整类名指定为字符串常量来提供自定义策略。其余子选项取决于所选的类。默认类支持的子选项是
选项 | 支持的压缩策略 | 默认值 | 说明 |
---|---|---|---|
|
all |
true |
一个布尔值,表示是否应启用压缩。 |
|
all |
0.2 |
一个比率,如果 sstable 中可 GC 的墓碑超过所有包含列的该比率,则将压缩该 sstable(不带其他 sstable),以清除这些墓碑。 |
|
all |
1 天 |
在考虑 sstable 创建时间的 |
|
all |
false |
将此设置为 true 将启用更激进的墓碑压缩 - 单个 sstable 墓碑压缩将在不检查其成功可能性有多大的情况下运行。 |
|
SizeTieredCompactionStrategy |
50MB |
按大小分层的策略将要压缩的 SSTable 分组到存储桶中。存储桶对大小相差不到 50% 的 SSTable 进行分组。但是,对于小尺寸,这会导致分桶过于细化。 |
|
SizeTieredCompactionStrategy |
4 |
启动小压缩所需的最小 SSTable 数量。 |
|
SizeTieredCompactionStrategy |
32 |
一个小的压缩处理的最大 SSTable 数量。 |
|
SizeTieredCompactionStrategy |
0.5 |
如果 sstable 的大小在 [average_size * |
|
SizeTieredCompactionStrategy |
1.5 |
大小分层将 sstable 视为在同一存储桶中,如果其大小在 [average_size * |
|
LeveledCompactionStrategy |
5MB |
分层策略中 sstable 的目标大小(以 MB 为单位)。请注意,虽然 sstable 大小应保持小于或等于 |
|
TimeWindowCompactionStrategy |
MICROSECONDS |
插入数据时使用的 timestamp 分辨率,可以是 MILLISECONDS、MICROSECONDS 等(Java TimeUnit 应可理解) - 除非您使用 USING TIMESTAMP(或直接在客户端中使用等效项)进行突变,否则不要更改此项。 |
|
TimeWindowCompactionStrategy |
DAYS |
用于窗口大小的 Java TimeUnit,与 |
|
TimeWindowCompactionStrategy |
1 |
组成时间窗口的 |
|
TimeWindowCompactionStrategy |
false |
过期 sstable 将被删除,而无需检查其数据是否正在对其他 sstable 进行影子备份。这是一个潜在的危险选项,可能导致数据丢失或已删除的数据重新出现,超出了 |
压缩选项
对于 compression
属性,以下子选项可用
选项 | 默认值 | 说明 | |||
---|---|---|---|---|---|
|
LZ4Compressor |
要使用的压缩算法。默认压缩器为:LZ4Compressor、SnappyCompressor 和 DeflateCompressor。使用 |
|||
|
true |
默认情况下启用压缩。要禁用它,请将 |
|
64KB |
磁盘上的 SSTable 按块进行压缩(以允许随机读取)。这定义了所述块的大小(以 KB 为单位)。较大的值可能会提高压缩率,但会增加从磁盘读取数据的最小大小。 |
ALTER TABLE
语法
bc(syntax)..
::= ALTER (TABLE | COLUMNFAMILY) (IF EXISTS)?
::= ADD (IF NOT EXISTS)?
| ADD (IF NOT EXISTS)? ( ( , )* )
| DROP (IF EXISTS)?
| DROP (IF EXISTS)? ( ( , )* )
| RENAME (IF EXISTS)? TO (AND TO)*
| WITH ( AND )*
p.
样本
bc(sample)..
ALTER TABLE addamsFamily
ALTER TABLE addamsFamily
ADD gravesite varchar;
ALTER TABLE addamsFamily
WITH comment = A most excellent and useful column family';
p.
`ALTER` 语句用于操作表定义。它允许添加新列、删除现有列或更新表选项。与创建表一样,`ALTER COLUMNFAMILY` 被允许作为 `ALTER TABLE` 的别名。如果表不存在,该语句将返回一个错误,除非使用了 `IF EXISTS`,在这种情况下,该操作将是一个空操作。
<tablename>
是表名,前面可以加上键空间名称。<instruction>
定义要执行的更改
-
ADD
:向表中添加新列。新列的<identifier>
不能与现有列冲突。此外,不能向使用COMPACT STORAGE
选项定义的表中添加列。如果新列已经存在,该语句将返回一个错误,除非使用了 `IF NOT EXISTS`,在这种情况下,该操作将是一个空操作。 -
DROP
:从表中删除一列。已删除的列将立即在查询中不可用,并且将来不会包含在压缩的 sstable 中。如果重新添加一列,查询将不会返回在该列上次删除之前写入的值。假设时间戳表示实际时间,因此如果不是这种情况,则不应读取先前删除的列。不能从使用COMPACT STORAGE
选项定义的表中删除列。如果已删除的列不存在,该语句将返回一个错误,除非使用了 `IF EXISTS`,在这种情况下,该操作将是一个空操作。 -
RENAME
表的主键列。非主键列不能重命名。此外,不允许将列重命名为另一个已经存在的名称。重要的是要记住,重命名的列不应具有从属的二级索引。如果重命名的列不存在,该语句将返回一个错误,除非使用了 `IF EXISTS`,在这种情况下,该操作将是一个空操作。 -
WITH
:允许更新表的选项。支持的<option>
(和语法)与CREATE TABLE
语句相同,但COMPACT STORAGE
不受支持。请注意,设置任何compaction
子选项都会清除所有以前的compaction
选项,因此如果您想保留它们,则需要重新指定所有子选项。相同的注意事项适用于compression
子选项集。
CQL 类型兼容性
CQL 数据类型只能按以下表格转换。
数据类型可以更改为 | 数据类型 |
---|---|
timestamp |
bigint |
ascii, bigint, boolean, date, decimal, double, float, inet, int, smallint, text, time, timestamp, timeuuid, tinyint, uuid, varchar, varint |
blob |
int |
date |
ascii, varchar |
text |
bigint |
time |
bigint |
timestamp |
timeuuid |
uuid |
ascii, text |
varchar |
bigint, int, timestamp |
varint |
群集列有更严格的要求,只允许以下转换。
数据类型可以更改为 | 数据类型 |
---|---|
ascii, text, varchar |
blob |
ascii, varchar |
text |
ascii, text |
varchar |
DROP TABLE
语法
bc(syntax). ::= DROP TABLE ( IF EXISTS )?
样本
bc(sample). DROP TABLE worldSeriesAttendees;
DROP TABLE
语句会导致立即不可逆地删除一张表,包括其中包含的所有数据。对于表创建,允许将 DROP COLUMNFAMILY
作为 DROP TABLE
的别名。
如果表不存在,该语句将返回一个错误,除非使用 IF EXISTS
,在这种情况下,该操作将为无操作。
TRUNCATE
语法
bc(语法)。::= TRUNCATE (TABLE | COLUMNFAMILY)?
样本
bc(示例)。TRUNCATE superImportantData;
TRUNCATE
语句永久删除表中的所有数据。
CREATE INDEX
CREATE INDEX
语句用于为给定表中给定(现有)列创建新的二级索引。如果需要,可以在 ON
关键字之前指定索引本身的名称。
语法
bc(syntax)..
::= CREATE (CUSTOM)?INDEX (IF NOT EXISTS)?()?
ON `(' `)'
(USING (WITH OPTIONS = )?)?
::=
| keys( )
p.
样本
bc(sample).
CREATE INDEX userIndex ON NerdMovies (user);
CREATE INDEX ON Mutants (abilityId);
CREATE INDEX ON users (keys(favs));
CREATE INDEX ON users (age) USING 'sai';
CREATE CUSTOM INDEX ON users (email) USING `path.to.the.IndexClass';
CREATE CUSTOM INDEX ON users (email) USING `path.to.the.IndexClass' WITH OPTIONS = \{’storage’: `/mnt/ssd/indexes/'};
如果列中已存在数据,它将异步编入索引。创建索引后,列的新数据将在插入时自动编入索引。尝试创建已存在的索引将返回一个错误,除非使用了 IF NOT EXISTS
选项。如果使用了该选项,如果索引已存在,该语句将为无操作。
索引类型
USING
关键字可以选择指定索引类型。有两种内置类型
-
legacy_local_table - (默认)旧式二级索引,实现为隐藏的本地表
-
sai - “存储附加”索引,通过优化的 SSTable/Memtable 附加索引实现
要创建自定义索引,必须指定一个完全限定的类名。
映射键上的索引
在为映射列创建索引时,你可以编入索引的键或值。如果列标识符放置在 keys()
函数中,索引将位于映射键上,允许你在 WHERE
子句中使用 CONTAINS KEY
。否则,索引将位于映射值上。
DROP INDEX
语法
bc(语法)。::= DROP INDEX (IF EXISTS)?( `.' )?
样本
bc(sample)..
DROP INDEX userIndex;
DROP INDEX userkeyspace.address_index;
p.DROP INDEX
语句用于删除现有的二级索引。该语句的参数是索引名称,它可以选择指定索引的键空间。
如果索引不存在,该语句将返回一个错误,除非使用 IF EXISTS
,在这种情况下,该操作将为无操作。
CREATE MATERIALIZED VIEW
语法
bc(syntax)..
::= CREATE MATERIALIZED VIEW (IF NOT EXISTS)?AS
SELECT ( `(' ( `,' ) * `)' | `' )
FROM
(WHERE)?
PRIMARY KEY `(' ( `,' ) `)'
( WITH ( AND )* )?
p.
样本
bc(sample)..
CREATE MATERIALIZED VIEW monkeySpecies_by_population AS
SELECT *
FROM monkeySpecies
WHERE population IS NOT NULL AND species IS NOT NULL
PRIMARY KEY (population, species)
带注释=允许按种群查询,而不是物种';
p.
`CREATE MATERIALIZED VIEW` 语句创建一个新的物化视图。每个此类视图都是一组行,对应于 `SELECT` 语句中指定的底层或基础表中存在的行。无法直接更新物化视图,但对基础表的更新将导致视图中相应的更新。
尝试创建已存在的物化视图将返回错误,除非使用 `IF NOT EXISTS` 选项。如果使用该选项,如果物化视图已存在,该语句将为无操作。
WHERE
子句
<where-clause>
类似于 SELECT
语句的 where 子句,但有少许差异。首先,where 子句必须包含一个表达式,该表达式不允许视图主键中的列中存在 NULL
值。如果不需要其他限制,可以使用 IS NOT NULL
表达式来实现此目的。其次,只有基础表主键中的列才能使用除 IS NOT NULL
以外的表达式进行限制。(请注意,第二个限制将来可能会取消。)
ALTER MATERIALIZED VIEW
语法
bc(syntax). ::= ALTER MATERIALIZED VIEW
WITH ( AND )*
ALTER MATERIALIZED VIEW
语句允许更新选项;这些选项与 CREATE TABLE
的选项相同。
DROP MATERIALIZED VIEW
语法
bc(syntax). ::= DROP MATERIALIZED VIEW ( IF EXISTS )?
样本
bc(sample). DROP MATERIALIZED VIEW monkeySpecies_by_population;
DROP MATERIALIZED VIEW
语句用于删除现有的物化视图。
如果物化视图不存在,该语句将返回错误,除非使用了 IF EXISTS
,在这种情况下,该操作为无操作。
CREATE TYPE
语法
bc(syntax)..
::= CREATE TYPE ( IF NOT EXISTS )?
`(' ( `,' )* `)'
::= ( `.' )?
::=
样本
bc(sample)..
CREATE TYPE address (
street_name text,
street_number int,
city text,
state text,
zip int
)
CREATE TYPE work_and_home_addresses (
home_address address,
work_address address
)
p.CREATE TYPE
语句创建一个新的用户定义类型。每个类型都是一组已命名、已键入的字段。字段类型可以是任何有效类型,包括集合和其他现有的用户定义类型。
尝试创建已存在的类型将导致错误,除非使用 IF NOT EXISTS
选项。如果使用该选项,如果类型已存在,该语句将为无操作。
<typename>
有效的类型名称是标识符。不能使用现有的 CQL 类型和 保留类型名称。
如果仅提供类型名称,则使用当前键空间创建类型(请参见 USE
)。如果它前面带有现有的键空间名称,则在指定键空间中创建类型,而不是在当前键空间中创建类型。
ALTER TYPE
语法
bc(syntax)..
::= ALTER TYPE (IF EXISTS)?
::= ADD (IF NOT EXISTS)?
| RENAME (IF EXISTS)? TO ( AND TO )*
p.
样本
bc(sample)..
ALTER TYPE address ADD country text
ALTER TYPE address RENAME zip TO zipcode AND street_name TO street
p.ALTER TYPE
语句用于操作类型定义。它允许添加新字段、重命名现有字段或更改现有字段的类型。如果类型不存在,该语句将返回错误,除非使用了 IF EXISTS
,在这种情况下,该操作为无操作。
DROP TYPE
语法
bc(syntax)..
::= DROP TYPE ( IF EXISTS )?
p.DROP TYPE
语句会导致立即永久删除类型。尝试删除仍在被其他类型或表使用的类型将导致错误。
如果类型不存在,将返回错误,除非使用了 IF EXISTS
,在这种情况下,操作为无操作。
CREATE TRIGGER
语法
bc(syntax)..
::= CREATE TRIGGER ( IF NOT EXISTS )? ( )?
ON
USING
样本
bc(sample).
CREATE TRIGGER myTrigger ON myTable USING `org.apache.cassandra.triggers.InvertedIndex';
构成触发器的实际逻辑可以用任何 Java (JVM) 语言编写,并且存在于数据库外部。将触发器代码放在 Cassandra 安装目录的 lib/triggers
子目录中,它会在集群启动期间加载,并存在于参与集群的每个节点上。在表上定义的触发器会在请求的 DML 语句发生之前触发,从而确保事务的原子性。
DROP TRIGGER
语法
bc(syntax)..
::= DROP TRIGGER ( IF EXISTS )? ( )?
ON
p.
样本
bc(sample).
DROP TRIGGER myTrigger ON myTable;
DROP TRIGGER
语句删除使用 CREATE TRIGGER
创建的触发器的注册。
CREATE FUNCTION
语法
bc(syntax)..
::= CREATE ( OR REPLACE )?
FUNCTION ( IF NOT EXISTS )?
( `.' )?
`(' ( `,' )* `)'
( CALLED | RETURNS NULL ) ON NULL INPUT
RETURNS
LANGUAGE
AS
样本
bc(sample).
CREATE OR REPLACE FUNCTION somefunction
( somearg int, anotherarg text, complexarg frozen, listarg list )
RETURNS NULL ON NULL INPUT
RETURNS text
LANGUAGE java
AS + ;
CREATE FUNCTION akeyspace.fname IF NOT EXISTS
( someArg int )
CALLED ON NULL INPUT
RETURNS text
LANGUAGE java
AS + ;
CREATE FUNCTION
创建或替换用户定义函数。
函数签名
签名用于区分各个函数。签名包括
-
完全限定的函数名 - 即 键空间 加上 函数名
-
所有参数类型的连接列表
请注意,键空间名称、函数名称和参数类型受默认命名约定和大写/小写敏感规则的约束。
带有可选 OR REPLACE
关键字的 CREATE FUNCTION
要么创建函数,要么用具有相同签名的现有函数替换它。如果没有 OR REPLACE
的 CREATE FUNCTION
会在已经存在具有相同签名的函数时失败。
必须为每个函数定义使用 null
值时的调用行为。有两个选项
-
RETURNS NULL ON NULL INPUT
声明如果任何输入参数为null
,函数将始终返回null
。 -
CALLED ON NULL INPUT
声明函数将始终执行。
如果使用了可选的 IF NOT EXISTS
关键字,则只有在具有相同签名的其他函数不存在时才会创建函数。
OR REPLACE
和 IF NOT EXIST
不能一起使用。
函数属于键空间。如果在 <function-name>
中未指定键空间,则使用当前键空间(即使用 USE
语句指定的键空间)。无法在某个系统键空间中创建用户自定义函数。
有关详细信息,请参阅 用户自定义函数 部分。
DROP FUNCTION
语法
bc(syntax)..
::= DROP FUNCTION ( IF EXISTS )?
( `.' )?
( `(' ( `,' )* `)' )?
样本
bc(sample).
DROP FUNCTION myfunction;
DROP FUNCTION mykeyspace.afunction;
DROP FUNCTION afunction ( int );
DROP FUNCTION afunction ( text );
DROP FUNCTION
语句删除使用 CREATE FUNCTION
创建的函数。
如果存在多个同名但签名不同的函数(重载函数),则必须指定要删除函数的参数类型(签名)。
带有可选 IF EXISTS
关键字的 DROP FUNCTION
会在函数存在时删除该函数。
CREATE AGGREGATE
语法
bc(syntax)..
::= CREATE ( OR REPLACE )?
AGGREGATE ( IF NOT EXISTS )?
( `.' )?
`(' ( `,' )* `)'
SFUNC
STYPE
( FINALFUNC )?
( INITCOND )?
p.
样本
bc(sample).
CREATE AGGREGATE myaggregate ( val text )
SFUNC myaggregate_state
STYPE text
FINALFUNC myaggregate_final
INITCOND `foo';
有关完整示例,请参阅 用户自定义聚合 部分。
CREATE AGGREGATE
创建或替换用户自定义聚合。
带有可选 OR REPLACE
关键字的 CREATE AGGREGATE
既可以创建聚合,也可以替换具有相同签名的现有聚合。如果已存在具有相同签名的聚合,则不带 OR REPLACE
的 CREATE AGGREGATE
会失败。
带有可选 IF NOT EXISTS
关键字的 CREATE AGGREGATE
会在聚合不存在时创建聚合。
OR REPLACE
和 IF NOT EXIST
不能一起使用。
聚合属于键空间。如果在 <aggregate-name>
中未指定键空间,则使用当前键空间(即使用 USE
语句指定的键空间)。无法在某个系统键空间中创建用户自定义聚合。
STYPE
定义状态值类型,必须指定。
可选的 INITCOND
定义聚合的初始状态值。其默认值为 null
。对于使用 RETURNS NULL ON NULL INPUT
声明的状态函数,必须指定非 null
的 INITCOND
。
SFUNC
引用一个现有函数,以用作状态修改函数。状态函数的第一个参数类型必须与 STYPE
匹配。状态函数的其余参数类型必须与聚合函数的参数类型匹配。对于使用 RETURNS NULL ON NULL INPUT
声明并使用 null
调用的状态函数,不会更新状态。
可选的 FINALFUNC
在返回聚合结果之前调用。它必须只接受一个类型为 STYPE
的参数。FINALFUNC
的返回类型可以是不同的类型。使用 RETURNS NULL ON NULL INPUT
声明的最终函数表示如果最后一个状态为 null
,则聚合的返回值将为 null
。
如果未定义 FINALFUNC
,聚合函数的总体返回类型为 STYPE
。如果定义了 FINALFUNC
,它就是该函数的返回类型。
请参阅 用户定义聚合 部分以了解更多信息。
DROP AGGREGATE
语法
bc(syntax)..
::= DROP AGGREGATE ( IF EXISTS )?
( `.' )?
( `(' ( `,' )* `)' )?
p.
样本
bc(sample).
DROP AGGREGATE myAggregate;
DROP AGGREGATE myKeyspace.anAggregate;
DROP AGGREGATE someAggregate ( int );
DROP AGGREGATE someAggregate ( text );
DROP AGGREGATE
语句删除使用 CREATE AGGREGATE
创建的聚合。如果有多个具有相同名称但签名不同的聚合(重载的聚合),则必须指定要删除的聚合的参数类型。
带有可选 IF EXISTS
关键字的 DROP AGGREGATE
会删除存在的聚合,如果具有该签名的函数不存在,则不执行任何操作。
数据操作
INSERT
语法
bc(syntax)..
::= INSERT INTO
( ( VALUES )
| ( JSON ))
( IF NOT EXISTS )?
( USING ( AND )* )?
::= `(' ( `,' )* `)'
::= `(' ( `,' )* `)'
::= TIMESTAMP
| TTL
p.
样本
bc(sample)..
INSERT INTO NerdMovies (movie, director, main_actor, year)
VALUES (`Serenity', `Joss Whedon', `Nathan Fillion', 2005)
USING TTL 86400;
INSERT INTO NerdMovies JSON \{
语句为表中的给定行写入一列或多列。请注意,由于行由其 movie'':
Serenity'', director'':
Joss Whedon'', ``year'': 2005}'
p.
`INSERTPRIMARY KEY
标识,因此必须至少指定组成它的列。使用 VALUES
语法时,必须提供要插入到的列列表。使用 JSON
语法时,它们是可选的。有关更多详细信息,请参阅 INSERT JSON
部分。
请注意,与 SQL 不同,INSERT
默认情况下不会检查行的先前存在:如果之前不存在行,则创建行,否则更新行。此外,没有办法知道发生了创建还是更新。
但是,可以使用 IF NOT EXISTS
条件仅在插入之前不存在行时才插入。但请注意,使用 IF NOT EXISTS
会产生不可忽略的性能开销(在内部,将使用 Paxos),因此应谨慎使用。
INSERT
的所有更新都以原子方式和隔离方式应用。
UPDATE
语法
bc(syntax)..
::= UPDATE
( USING ( AND )* )?
SET ( `,' )*
WHERE
( IF ( AND condition )* )?
::= ='
+' | `-') ( | | )
| `=' (
| `=' `+'
| `[' `]' `='
| `.' `='
::=
| CONTAINS (KEY)?
| IN
| `[' `]'
| `[' `]' IN
| `.'
| `.' IN
::= `<' | `⇐' | `=' | `!=' | `>=' | `>'
::= ( | `(' ( ( `,' )* )? `)')
::= ( AND )*
::= ='
,' )*
| `(' ()' `='
,' )*
| IN `(' ( ( `,' )* )? `)'
| IN
| `(' ()' IN `(' ( ( `,' )* )? `)'
,' )* `)' IN
| `(' (
::= TIMESTAMP
| TTL
p.
样本
bc(sample)..
UPDATE NerdMovies USING TTL 400
SET director = `Joss Whedon',
main_actor = `Nathan Fillion',
year = 2005
WHERE movie = `Serenity';
UPDATE UserActions SET total = total + 2 WHERE user = B70DE1D0-9908-4AE3-BE34-5573E5B09F14 AND action = click';
p.
`UPDATE` 语句为表中的给定行写入一个或多个列。<where-clause>
用于选择要更新的行,并且必须包括构成 PRIMARY KEY
的所有列。其他列值通过 SET
关键字后的 <assignment>
指定。
请注意,与 SQL 不同,UPDATE
默认情况下不检查行的先前存在(除非通过使用 <condition>
,请参见下文):如果之前不存在行,则创建该行,否则更新该行。此外,没有办法知道是否发生了创建或更新。
然而,可以通过 IF
对某些列使用条件,在这种情况下,除非满足条件,否则不会更新行。但是,请注意,使用 IF
条件会产生不可忽略的性能开销(在内部,Paxos 将被使用),因此应谨慎使用。
在 UPDATE
语句中,同一分区键内的所有更新都会以原子方式和隔离方式应用。
<assignment>
的 c = c + 3
形式用于递增/递减计数器。'='
符号后的标识符必须与 '='
符号前的标识符相同(仅支持对计数器进行递增/递减,不支持分配特定值)。
<assignment>
的 id = id + <collection-literal>
和 id[value1] = value2
形式适用于集合。有关更多详细信息,请参阅 相关部分。
<assignemt>
的 id.field = <term>
形式用于设置非冻结用户定义类型上单个字段的值。
<options>
UPDATE
和 INSERT
语句支持以下选项
-
TIMESTAMP
:设置操作的时间戳。如果未指定,协调器将在语句执行开始时使用当前时间(以微秒为单位)作为时间戳。这通常是一个合适的默认值。 -
TTL
:为插入的值指定可选的生存时间(以秒为单位)。如果设置,插入的值将在指定时间后自动从数据库中删除。请注意,TTL 涉及插入的值,而不是列本身。这意味着对列的任何后续更新也将重置 TTL(重置为该更新中指定的任何 TTL)。默认情况下,值永不过期。TTL 为 0 等效于没有 TTL。如果表具有 default_time_to_live,则 TTL 为 0 将删除插入或更新的值的 TTL。
DELETE
语法
bc(syntax)..
::= DELETE ( ( `,' )* )?
FROM
( USING TIMESTAMP )?
WHERE
( IF ( EXISTS | ( ( AND )*) ) )?
::=
| `[' `]'
| `.'
::= ( AND )*
::=
| (' (
,' )* )'
,' )*
| IN `(' ( ( `,' )* )? `)'
| IN
| `(' ()' IN `(' ( ( `,' )* )? `)'
,' )* `)' IN
| `(' (
::= `=' | `<' | `>' | `⇐' | `>='
::= ( | `(' ( ( `,' )* )? `)')
::= ( | `!=')
| CONTAINS (KEY)?
| IN
| `[' `]' ( | `!=')
| `[' `]' IN
| `.' ( | `!=')
| `.' IN
样本
bc(sample)..
DELETE FROM NerdMovies USING TIMESTAMP 1240003134 WHERE movie = `Serenity';
DELETE phone FROM Users WHERE userid IN (C73DE1D3-AF08-40F3-B124-3FF3E5109F22, B70DE1D0-9908-4AE3-BE34-5573E5B09F14);
p.DELETE
语句删除列和行。如果在 DELETE
关键字后直接提供列名,则仅从 <where-clause>
指示的行中删除这些列。<selection>
中的 id[value]
语法用于非冻结集合(有关更多详细信息,请参阅 集合部分)。id.field
语法用于删除非冻结用户定义类型。否则,将删除整行。<where-clause>
指定要删除哪些行。可以使用 IN
子句通过一条语句删除多行。可以使用不等式运算符(例如 >=
)删除一系列行。
DELETE
支持 TIMESTAMP
选项,其语义与 UPDATE
语句相同。
在 DELETE
语句中,同一分区键内的所有删除操作都会以原子方式和隔离方式应用。
可以通过使用 IF
子句对 DELETE
操作进行条件设置,类似于 UPDATE
和 INSERT
语句。但是,与 INSERT
和 UPDATE
语句一样,这将产生不可忽略的性能成本(在内部,将使用 Paxos),因此应谨慎使用。
BATCH
语法
bc(syntax)..
::= BEGIN ( UNLOGGED | COUNTER ) BATCH
( USING ( AND )* )?
( `;' )*
APPLY BATCH
::=
|
|
::= TIMESTAMP
p.
样本
bc(sample).
BEGIN BATCH
INSERT INTO users (userid, password, name) VALUES (`user2', `ch@ngem3b', `second user');
UPDATE users SET password = `ps22dhds' WHERE userid = `user3';
INSERT INTO users (userid, password) VALUES (`user4', `ch@ngem3c');
DELETE name FROM users WHERE userid = `user1';
APPLY BATCH;
BATCH
语句将多个修改语句(插入/更新和删除)组合到一条语句中。它有几个用途
-
在批处理多个更新时,它可以节省客户端和服务器(有时是服务器协调器和副本)之间的网络往返。
-
属于给定分区键的
BATCH
中的所有更新都以隔离方式执行。 -
默认情况下,批处理中的所有操作都作为
LOGGED
执行,以确保所有突变最终完成(或没有一个完成)。有关更多详细信息,请参阅UNLOGGED
的注释。
请注意
-
BATCH
语句只能包含UPDATE
、INSERT
和DELETE
语句。 -
批处理不是 SQL 事务的完全类似物。
-
如果未为每个操作指定时间戳,则所有操作都将使用相同的时间戳应用。由于 Cassandra 在 时间戳相同时进行冲突解决程序,因此操作的应用顺序可能与在
BATCH
语句中列出的顺序不同。要强制执行特定的操作顺序,您必须指定每个操作的时间戳。
UNLOGGED
默认情况下,Cassandra 使用批处理日志来确保批处理中的所有操作最终完成,或者没有一个操作完成(但请注意,操作仅在单个分区内隔离)。
当批处理跨越多个分区时,批处理原子性会产生性能损失。如果您不想承担此损失,则可以使用 UNLOGGED
选项告诉 Cassandra 跳过批处理日志。如果使用了 UNLOGGED
选项,则失败的批处理可能会使补丁仅部分应用。
<option>
BATCH
同时支持 TIMESTAMP
选项,其语义与 UPDATE
语句中描述的语义类似(时间戳适用于批次中的所有语句)。但是,如果使用,则 不得 在批次中的语句中使用 TIMESTAMP
。
查询
SELECT
语法
bc(syntax)..
::= SELECT ( JSON )?
FROM
( WHERE )?
( GROUP BY )?
( ORDER BY )?
( PER PARTITION LIMIT )?
( LIMIT )?
( ALLOW FILTERING )?
::= DISTINCT?
::= (AS )? ( `,' (AS )? )*
| `*'
::=
|
| WRITETIME (' `)'
,' ))? `)'
| MAXWRITETIME `(' `)'
| COUNT `(' `' `)'
| TTL `(' `)'
| CAST `(' AS `)'
| `(' ( (
| `.'
| `[' `]'
| `[' ? .. ? `]'
::= ( AND )*
::=
| (' (
,' )* )'
,' )* `)' IN `(' ( ( `,' )* )? `)'
| IN `(' ( ( `,' )* )? `)'
| `(' (
| TOKEN `(' ( `,' )* `)'
::= =' | `<' | `>' | `⇐' | `>=' | CONTAINS | CONTAINS KEY
,' )*
::= (
::= ( ,' )*
,' )* `)'
::= ( ASC | DESC )?
::= `(' (
p.
样本
bc(sample)..
SELECT name, occupation FROM users WHERE userid IN (199, 200, 207);
SELECT JSON name, occupation FROM users WHERE userid = 199;
SELECT name AS user_name, occupation AS user_occupation FROM users;
SELECT time, value
FROM events
WHERE event_type = `myEvent'
AND time > `2011-02-03'
AND time ⇐ `2012-01-01'
SELECT COUNT (*) FROM users;
SELECT COUNT (*) AS user_count FROM users;
SELECT
语句读取表中一行或多行的一列或多列。它返回一个行结果集,其中每行包含与查询相对应的列集合。如果使用 JSON
关键字,则每行的结果将只包含一个名为 `json'' 的列。有关详细信息,请参阅 `SELECT JSON
部分。
<select-clause>
<select-clause>
确定需要在结果集中查询和返回哪些列。它由逗号分隔的列表或通配符 (*
) 组成,以选择为表定义的所有列。请注意,对于通配符 SELECT
查询,返回的列的顺序未指定,并且不能保证在 Cassandra 版本之间保持稳定。
<selector>
是要检索的列名或一个或多个 <term>
的 <function>
。允许的函数与 <term>
相同,并在 函数部分 中进行了描述。除了这些通用函数之外,WRITETIME
和 MAXWRITETIME
(分别为 TTL
)函数允许选择列插入的时间戳(分别为列的生存时间(以秒为单位)(或如果列没有设置过期时间,则为 null))和 CAST
函数可用于将一种数据类型转换为另一种数据类型。WRITETIME
和 TTL
函数不能用于多单元格列,例如非冻结集合或非冻结用户定义类型。
此外,可以使用 [ <term> ]
选择映射和集合的各个值。对于映射,如果存在这样的条目,这将返回与键对应的值。对于集合,如果存在,这将返回所选的键,因此主要是一种检查元素是否存在的方法。还可以使用 `[ <term> … <term> `] 选择集合或映射的切片,其中可以省略两个边界。
可以使用 AS
关键字对任何 <selector>
进行别名处理(请参见示例)。请注意,<where-clause>
和 <order-by>
子句应按其原始名称引用列,而不是按其别名引用列。
COUNT
关键字可以与括在 *
中的括号一起使用。如果是这样,查询将返回单个结果:与查询匹配的行数。请注意,COUNT(1)
受支持作为别名。
<where-clause>
<where-clause>
指定必须查询哪些行。它由 PRIMARY KEY
的一部分的列上的关系组成,和/或在它们上定义了 辅助索引。
并非所有关系都允许在查询中。例如,分区键上的非相等关系(其中 IN
被视为相等关系)不受支持(但请参见下面使用 TOKEN
方法对分区键执行非相等查询)。此外,对于给定的分区键,群集列会引起行的排序,并且对它们的限制关系只能选择一组连续的(对于排序)行。例如,给定
bc(sample).
CREATE TABLE posts (
userid text,
blog_title text,
posted_at timestamp,
entry_title text,
content text,
category int,
PRIMARY KEY (userid, blog_title, posted_at)
)
允许以下查询
bc(sample).
SELECT entry_title, content FROM posts WHERE userid=`john doe' AND blog_title=`John'`s Blog' AND posted_at >= `2012-01-01' AND posted_at < `2012-01-31'
但以下查询不允许,因为它没有选择一组连续的行(并且我们假设没有设置辅助索引)
bc(sample).
SELECT entry_title, content FROM posts WHERE userid=`john doe' AND posted_at >= `2012-01-01' AND posted_at < `2012-01-31'
在指定关系时,可以在 PARTITION KEY
列上使用 TOKEN
函数进行查询。在这种情况下,将根据其 PARTITION_KEY
的令牌而不是值来选择行。请注意,键的令牌取决于所使用的分区器,特别是 RandomPartitioner 不会产生有意义的顺序。还要注意,排序分区器始终按字节对令牌值进行排序(因此,即使分区键的类型为 int,token(-1) > token(0)
)。示例
bc(sample).
SELECT * FROM posts WHERE token(userid) > token(`tom') AND token(userid) < token(`bob')
此外,IN
关系仅允许在分区键的最后一列和完整主键的最后一列上使用。
还可以使用元组表示法将关系中的`group'' `CLUSTERING COLUMNS`
组合在一起。例如
bc(sample).
SELECT * FROM posts WHERE userid=`john doe' AND (blog_title, posted_at) > (`John'`s Blog', `2012-01-01')
将请求在群集顺序中将`John’s Blog'' 作为 `blog_tile`
和2012-01-01' 作为 `posted_at`
的记录之后排序的所有行。特别是,只要它们的blog_title > 'John''s Blog'
,就会返回post_at ⇐ '2012-01-01'
的记录,而对于
bc(sample).
SELECT * FROM posts WHERE userid=`john doe' AND blog_title > `John'`s Blog' AND posted_at > `2012-01-01'
元组表示法还可以用于CLUSTERING COLUMNS
上的IN
子句
bc(sample).
SELECT * FROM posts WHERE userid=`john doe' AND (blog_title, posted_at) IN `John'`s Blog', `2012-01-01), (’Extreme Chess', `2014-06-01'
CONTAINS
运算符只能用于集合列(列表、集合和映射)。对于映射,CONTAINS
适用于映射值。CONTAINS KEY
运算符只能用于映射列,并适用于映射键。
<order-by>
ORDER BY
选项允许选择返回结果的顺序。它以列名列表作为参数,以及列的顺序(ASC
表示升序,DESC
表示降序,省略顺序等同于ASC
)。当前可能的顺序是有限的(取决于表CLUSTERING ORDER
)
-
如果表在没有任何特定
CLUSTERING ORDER
的情况下被定义,那么允许的顺序是群集列引起的顺序及其逆序。 -
否则,允许的顺序是
CLUSTERING ORDER
选项的顺序及其逆序。
<group-by>
GROUP BY
选项允许将所有对于一组列共享相同值的选择行浓缩到一行中。
使用GROUP BY
选项,只能在分区键级别或群集列级别对行进行分组。因此,GROUP BY
选项只接受主键顺序中的主键列名作为参数。如果主键列受到相等性限制,则不需要它出现在GROUP BY
子句中。
聚合函数将为每个组生成一个单独的值。如果没有指定GROUP BY
子句,聚合函数将为所有行生成一个值。
如果在包含GROUP BY
的语句中选择列而没有聚合函数,则将返回每个组中遇到的第一个值。
LIMIT
和PER PARTITION LIMIT
SELECT
语句的LIMIT
选项限制查询返回的行数,而PER PARTITION LIMIT
选项限制查询为给定分区返回的行数。请注意,两种类型的限制都可以在同一个语句中使用。
ALLOW FILTERING
默认情况下,CQL只允许不涉及filtering'' 服务器端的select查询,即我们知道所有(实时)读取的记录将(部分)返回在结果集中。其原因是这些
非过滤''查询具有可预测的性能,因为它们将在与查询返回的数据量成正比的时间内执行(可以通过LIMIT
控制)。
ALLOW FILTERING
选项允许明确允许(一些)需要过滤的查询。请注意,使用 ALLOW FILTERING
的查询可能因此具有不可预测的性能(对于上述定义),即,即使是选择少量记录的查询也可能表现出取决于集群中存储的数据总量的性能。
例如,考虑以下包含用户个人资料及其出生年份(带有辅助索引)和居住国家的表
bc(sample)..
CREATE TABLE users (
username text PRIMARY KEY,
firstname text,
lastname text,
birth_year int,
country text
)
CREATE INDEX ON users(birth_year);
p.
那么以下查询有效
bc(sample).
SELECT * FROM users;
SELECT firstname, lastname FROM users WHERE birth_year = 1981;
因为在这两种情况下,Cassandra 保证这些查询的性能将与返回的数据量成正比。特别是,如果没有用户出生于 1981 年,则第二个查询的性能将不取决于数据库中存储的用户个人资料的数量(至少不是直接取决于:由于辅助索引实现考虑因素,此查询可能仍然取决于集群中的节点数,而节点数间接取决于存储的数据量。然而,节点数将始终比存储的用户个人资料的数量低多个数量级)。当然,这两个查询实际上都可能返回非常大的结果集,但始终可以通过添加 LIMIT
来控制返回的数据量。
但是,将拒绝以下查询
bc(sample).
SELECT firstname, lastname FROM users WHERE birth_year = 1981 AND country = `FR';
因为 Cassandra 无法保证即使查询结果很小,它也不必扫描大量数据。通常,它将扫描所有出生于 1981 年的用户索引条目,即使实际上只有少数用户来自法国。但是,如果您`知道自己在做什么'',您可以使用 `ALLOW FILTERING
强制执行此查询,因此以下查询有效
bc(sample).
SELECT firstname, lastname FROM users WHERE birth_year = 1981 AND country = `FR' ALLOW FILTERING;
数据库角色
CREATE ROLE
语法
bc(syntax)..
::= CREATE ROLE ( IF NOT EXISTS )? ( WITH ( AND )* )?
::= PASSWORD =
| LOGIN =
| SUPERUSER =
| OPTIONS =
p.
样本
bc(sample).
CREATE ROLE new_role;
CREATE ROLE alice WITH PASSWORD = `password_a' AND LOGIN = true;
CREATE ROLE bob WITH PASSWORD = `password_b' AND LOGIN = true AND SUPERUSER = true;
CREATE ROLE carlos WITH OPTIONS = \{ `custom_option1' : `option1_value', `custom_option2' : 99 };
默认情况下,角色不拥有LOGIN
权限或SUPERUSER
状态。
数据库资源上的权限授予角色;资源类型包括键空间、表、函数和角色本身。可以将角色授予其他角色以创建分层权限结构;在这些层次结构中,权限和SUPERUSER
状态被继承,但LOGIN
权限不被继承。
如果角色具有LOGIN
权限,则客户端在连接时可以识别为该角色。在该连接期间,客户端将获得授予该角色的任何角色和权限。
只有具有数据库角色资源的CREATE
权限的客户端才能发出CREATE ROLE
请求(请参见下面的相关部分),除非客户端是SUPERUSER
。Cassandra 中的角色管理是可插拔的,并且自定义实现可能仅支持所列选项的子集。
如果角色名称包含非字母数字字符,则应引用角色名称。
ALTER ROLE
语法
bc(syntax)..
::= ALTER ROLE (IF EXISTS)? ( WITH ( AND )* )?
::= PASSWORD =
| LOGIN =
| SUPERUSER =
| OPTIONS =
p.
样本
bc(sample).
ALTER ROLE bob WITH PASSWORD = `PASSWORD_B' AND SUPERUSER = false;
如果角色不存在,该语句将返回错误,除非使用 IF EXISTS
,在这种情况下,该操作将为 no-op。
执行 ALTER ROLE
语句的条件
-
客户端必须具有
SUPERUSER
状态才能更改其他角色的SUPERUSER
状态 -
客户端不能更改其当前持有的任何角色的
SUPERUSER
状态 -
客户端只能修改其在登录时标识的角色的某些属性(例如
PASSWORD
) -
要修改角色的属性,客户端必须被授予该角色的
ALTER
权限
DROP ROLE
语法
bc(syntax)..
::= DROP ROLE ( IF EXISTS )?
p.
样本
bc(sample).
DROP ROLE alice;
DROP ROLE IF EXISTS bob;
DROP ROLE
要求客户端对相关角色拥有 DROP
权限。此外,客户端不能 DROP
其在登录时标识的角色。最后,只有具有 SUPERUSER
状态的客户端才能 DROP
另一个 SUPERUSER
角色。
尝试删除不存在的角色会导致无效的查询条件,除非使用 IF EXISTS
选项。如果使用该选项且角色不存在,则该语句将为 no-op。
GRANT ROLE
语法
bc(syntax)。
::= GRANT TO
样本
bc(sample).
GRANT report_writer TO alice;
此语句将 report_writer
角色授予 alice
。授予 report_writer
的任何权限也将被 alice
获取。
角色被建模为有向无环图,因此不允许循环授予。以下示例会导致错误条件
bc(sample).
GRANT role_a TO role_b;
GRANT role_b TO role_a;
bc(sample).
GRANT role_a TO role_b;
GRANT role_b TO role_c;
GRANT role_c TO role_a;
REVOKE ROLE
语法
bc(syntax)。
::= REVOKE FROM
样本
bc(sample).
REVOKE report_writer FROM alice;
此语句撤销 alice
的 report_writer
角色。alice
通过 report_writer
角色获取的任何权限也将被撤销。
CREATE USER
在 Cassandra 2.2 中引入角色之前,身份验证和授权基于 USER
的概念。为了向后兼容,保留了旧语法,以 USER
为中心的语句成为 ROLE
为基础的同义词。
语法
bc(syntax)..
::= 创建用户(如果不存在)? (使用密码)? ()?
::= 超级用户
| 非超级用户
p.
样本
bc(sample).
使用密码 `password_a` 创建用户 alice 为超级用户;
使用密码 `password_b` 创建用户 bob 为非超级用户;
创建用户
等同于 创建角色
,其中 登录
选项为 true
。因此,以下语句对等效
bc(sample)..
使用密码 `password_a` 创建用户 alice 为超级用户;
使用密码 = `password_a` 和登录 = true 以及超级用户 = true 创建角色 alice;
如果不存在,则使用密码 `password_a` 创建用户 alice 为超级用户;
如果不存在,则使用密码 = `password_a` 和登录 = true 以及超级用户 = true 创建角色 alice;
使用密码 `password_a` 创建用户 alice 为非超级用户;
使用密码 = `password_a` 和登录 = true 以及超级用户 = false 创建角色 alice;
使用密码 `password_a` 创建用户 alice 为非超级用户;
CREATE ROLE alice WITH PASSWORD = `password_a' AND LOGIN = true;
使用密码 `password_a` 创建用户 alice;
CREATE ROLE alice WITH PASSWORD = `password_a' AND LOGIN = true;
p.
数据库标识
数据控制
权限
资源的权限授予角色;Cassandra 中有几种不同类型的资源,每种类型都以分层方式建模
-
数据资源、键空间和表的层次结构具有以下结构:
所有键空间
→键空间
→表
-
函数资源具有以下结构:
所有函数
→键空间
→函数
-
表示角色的资源具有以下结构:
所有角色
→角色
-
表示 JMX ObjectName 的资源(映射到 MBean/MXBean 集)具有以下结构:
所有 MBEAN
→MBEAN
权限可以在这些层次结构的任何级别授予,并且向下流动。因此,在链中较高的资源上授予权限会自动在所有较低资源上授予相同的权限。例如,在 KEYSPACE
上授予 SELECT
会自动在该 KEYSPACE
中的所有 TABLES
上授予该权限。同样,在 ALL FUNCTIONS
上授予权限会授予每个已定义函数权限,无论其作用域在哪个键空间中。也可以在作用域为特定键空间的所有函数上授予权限。
对权限的修改对现有客户端会话可见;也就是说,在权限更改后不必重新建立连接。
可用权限的完整集合是
-
CREATE
-
ALTER
-
DROP
-
SELECT
-
MODIFY
-
AUTHORIZE
-
DESCRIBE
-
EXECUTE
-
UNMASK
-
SELECT_MASKED
并非所有权限都适用于每种类型的资源。例如,EXECUTE
仅与函数或 mbean 相关;在表示表的资源上授予 EXECUTE
是没有意义的。尝试对无法应用权限的资源GRANT
权限会导致错误响应。以下说明了哪些权限可以授予哪些类型的资源,以及该权限启用了哪些语句。
权限 | 资源 | 操作 | |||
---|---|---|---|---|---|
|
|
|
|||
|
|
在指定的键空间中 |
|||
|
|
在任何键空间中 |
|||
|
|
在键空间中 |
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
替换任何现有 |
|||
|
|
替换键空间中存在的 |
|||
|
|
替换任何现有 |
|||
|
|
在任何角色上 |
|||
|
|
|
|||
|
|
|
|||
|
|
在指定的键空间中 |
|||
|
|
|
|||
|
|
在任何键空间中 |
|||
|
|
在键空间中 |
|||
|
|
|
|||
|
|
在任何角色上 |
|||
|
|
|
|||
|
|
在任何表上 |
|||
|
|
在键空间中的任何表上 |
|||
|
|
在指定的表上 |
|||
|
|
调用任何 mbean 上的 getter 方法 |
|||
|
|
调用与通配符模式匹配的任何 mbean 上的 getter 方法 |
|||
|
|
调用已命名 mbean 上的 getter 方法 |
|||
|
|
在任何表上 |
|||
|
|
在键空间中的任何表上 |
|
|
|
|
|
调用任何 mbean 上的 setter 方法 |
|||
|
|
调用与通配符模式匹配的任何 mbean 上的 setter 方法 |
|||
|
|
调用已命名 mbean 上的 setter 方法 |
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
@ALL MBEANS |
从平台的 MBeanServer 检索有关任何 mbean 的元数据 |
|||
|
@MBEANS |
从平台的 MBeanServer 检索有关与通配符模式匹配的任何 mbean 的元数据 |
|||
|
@MBEAN |
从平台的 MBeanServer 检索有关已命名 mbean 的元数据 |
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
在任何 mbean 上执行操作 |
|||
|
|
在与通配符模式匹配的任何 mbean 上执行操作 |
|||
|
|
在已命名 mbean 上执行操作 |
|||
|
|
查看任何表上屏蔽列的清除内容 |
|||
|
|
查看键空间中任何表上屏蔽列的清除内容 |
|||
|
|
查看指定表上屏蔽列的清除内容 |
|||
|
|
|
|||
|
|
|
|||
|
|
|
GRANT PERMISSION
语法
bc(syntax)..
::= GRANT ( ALL ( PERMISSIONS )? | ( PERMISSION )? ) ON TO
::= CREATE | ALTER | DROP | SELECT | MODIFY | AUTHORIZE | DESCRIBE | UNMASK | SELECT_MASKED EXECUTE
::= ALL KEYSPACES
| KEYSPACE
| ( TABLE )?
| ALL ROLES
| ROLE
| ALL FUNCTIONS ( IN KEYSPACE )?
| FUNCTION
| ALL MBEANS
| ( MBEAN | MBEANS )
p.
样本
bc(sample).
GRANT SELECT ON ALL KEYSPACES TO data_reader;
这使具有角色 data_reader
的任何用户都有权限对所有键空间中的任何表执行 SELECT
语句
bc(sample).
GRANT MODIFY ON KEYSPACE keyspace1 TO data_writer;
这使具有角色 data_writer
的任何用户都有权限对 keyspace1
键空间中的所有表执行 UPDATE
、INSERT
、UPDATE
、DELETE
和 TRUNCATE
查询
bc(sample).
GRANT DROP ON keyspace1.table1 TO schema_owner;
这使具有 schema_owner
角色的任何用户都有权限 DROP
keyspace1.table1
。
bc(sample).
GRANT EXECUTE ON FUNCTION keyspace1.user_function( int ) TO report_writer;
这使具有 report_writer
角色的任何用户都有权限执行使用函数 keyspace1.user_function( int )
的 SELECT
、INSERT
和 UPDATE
查询
bc(sample).
授予 role_admin 对所有角色的 DESCRIBE 权限;
这将授予任何具有 role_admin
角色的用户使用 LIST ROLES
语句查看系统中任何和所有角色的权限
撤销权限
语法
bc(syntax)..
::= REVOKE ( ALL ( PERMISSIONS )? | ( PERMISSION )? ) ON FROM
::= CREATE | ALTER | DROP | SELECT | MODIFY | AUTHORIZE | DESCRIBE | UNMASK | SELECT_MASKED EXECUTE
::= ALL KEYSPACES
| KEYSPACE
| ( TABLE )?
| ALL ROLES
| ROLE
| ALL FUNCTIONS ( IN KEYSPACE )?
| FUNCTION
| ALL MBEANS
| ( MBEAN | MBEANS )
p.
样本
bc(sample)..
REVOKE SELECT ON ALL KEYSPACES FROM data_reader;
REVOKE MODIFY ON KEYSPACE keyspace1 FROM data_writer;
REVOKE DROP ON keyspace1.table1 FROM schema_owner;
REVOKE EXECUTE ON FUNCTION keyspace1.user_function( int ) FROM report_writer;
REVOKE DESCRIBE ON ALL ROLES FROM role_admin;
p.
列出权限
语法
bc(syntax)..
::= LIST ( ALL ( PERMISSIONS )? | )
( ON )?
( OF ( NORECURSIVE )? )?
::= ALL KEYSPACES
| KEYSPACE
| ( TABLE )?
| ALL ROLES
| ROLE
| ALL FUNCTIONS ( IN KEYSPACE )?
| FUNCTION
| ALL MBEANS
| ( MBEAN | MBEANS )
p.
样本
bc(sample).
LIST ALL PERMISSIONS OF alice;
显示授予 alice
的所有权限,包括从任何其他角色间接获得的权限。
bc(sample).
LIST ALL PERMISSIONS ON keyspace1.table1 OF bob;
显示授予 bob
的 keyspace1.table1
上的所有权限,包括从任何其他角色间接获得的权限。这也包括可以应用于 keyspace1.table1
的资源层次结构中的任何权限。例如,如果 bob
对 keyspace1
拥有 ALTER
权限,则该权限将包含在此查询的结果中。添加 NORECURSIVE
开关会将结果限制为仅直接授予 bob
或 bob
的角色的权限。
bc(sample).
LIST SELECT PERMISSIONS OF carlos;
显示授予 carlos
或 carlos
的任何角色的任何权限,仅限于对任何资源的 SELECT
权限。
数据类型
CQL 支持一组丰富的表中定义的列数据类型,包括集合类型。除了这些本机
和集合类型外,用户还可以提供自定义类型(通过扩展 AbstractType
的 JAVA 类,由
Cassandra 加载)。因此,类型的语法如下
bc(syntax)..
::=
|
|
| // 用于自定义类型。JAVA 类的完全限定名称
::= ascii
| bigint
| blob
| boolean
| counter
| date
| decimal
| double
| float
| inet
| int
| smallint
| text
| time
| timestamp
| timeuuid
| tinyint
| uuid
| varchar
| varint
::= list <' `>'
,' )* `>'
| set `<' `>'
| map `<' `,' `>'
::= tuple `<' (
p. 请注意,本机类型是关键字,因此不区分大小写。然而,它们不是保留关键字。
下表提供了有关本机数据类型的其他信息,以及每种类型支持的 常量 类型
类型 | 支持的常量 | 说明 |
---|---|---|
|
字符串 |
ASCII 字符串 |
|
整数 |
64 位有符号长整型 |
|
blob |
任意字节(无验证) |
|
布尔值 |
true 或 false |
|
整数 |
计数器列(64 位有符号值)。有关详细信息,请参见 计数器 |
|
整数、字符串 |
日期(无对应时间值)。有关详细信息,请参见下文的 使用日期。 |
|
整数、浮点数 |
可变精度十进制 |
|
整数 |
64 位 IEEE-754 浮点数 |
|
整数、浮点数 |
32 位 IEEE-754 浮点数 |
|
字符串 |
IP 地址。可以是 4 字节长(IPv4)或 16 字节长(IPv6)。没有 |
|
整数 |
32 位有符号 int |
|
整数 |
16 位有符号 int |
|
字符串 |
UTF8 编码字符串 |
|
整数、字符串 |
具有纳秒精度的时刻。有关详细信息,请参见下文的 使用时间。 |
|
整数、字符串 |
时间戳。字符串常量允许将时间戳作为日期输入,有关详细信息,请参见下文的 使用时间戳。 |
|
uuids |
类型 1 UUID。这通常用作“无冲突”时间戳。另请参见 Timeuuid 的函数 |
|
整数 |
8 位有符号 int |
|
uuids |
类型 1 或类型 4 UUID |
|
字符串 |
UTF8 编码字符串 |
|
整数 |
任意精度整数 |
有关如何使用集合类型的信息,请参见下文的 使用集合 部分。
使用时间戳
timestamp
类型的编码方式为 64 位有符号整数,表示自标准基准时间(称为“历元”)以来的毫秒数:1970 年 1 月 1 日格林威治标准时间 00:00:00。
时间戳可以在 CQL 中作为简单的长整数输入,给出如上定义的历元以来的毫秒数。
它们还可以作为字符串文字输入,采用以下任何 ISO 8601 格式,每个格式都表示时间和日期 2011 年 3 月 2 日格林威治标准时间上午 04:05:00。
-
2011-02-03 04:05+0000
-
2011-02-03 04:05:00+0000
-
2011-02-03 04:05:00.000+0000
-
2011-02-03T04:05+0000
-
2011-02-03T04:05:00+0000
-
2011-02-03T04:05:00.000+0000
上面的 +0000
是 RFC 822 4 位时区规范;+0000
指格林威治标准时间。美国太平洋标准时间是 -0800
。如果需要,可以省略时区——日期将被解释为协调 Cassandra 节点配置下的时区。
-
2011-02-03 04:05
-
2011-02-03 04:05:00
-
2011-02-03 04:05:00.000
-
2011-02-03T04:05
-
2011-02-03T04:05:00
-
2011-02-03T04:05:00.000
然而,依赖于预期的时间区配置显然存在困难,因此建议在可行的情况下始终为时间戳指定时区。
如果日期是唯一重要的部分,也可以省略一天中的时间
-
2011-02-03
-
2011-02-03+0000
在这种情况下,一天中的时间将默认为 00:00:00,在指定或默认时区中。
使用日期
date
类型的编码方式为 32 位无符号整数,表示以“历元”(范围的中心,2^31)为中心的日期数。历元是 1970 年 1 月 1 日
日期可以在 CQL 中作为如上定义的无符号整数输入。
它们还可以采用以下格式作为字符串文字输入
-
2014-01-01
使用时间
time
类型的编码方式为 64 位有符号整数,表示自午夜以来的纳秒数。
时间可以在 CQL 中作为简单的长整数输入,给出自午夜以来的纳秒数。
它们还可以作为字符串文字输入,采用以下任何格式
-
08:12:54
-
08:12:54.123
-
08:12:54.123456
-
08:12:54.123456789
计数器
counter
类型用于定义计数器列。计数器列是一列,其值是一个 64 位有符号整数,并且支持 2 个操作:增量和减量(有关语法,请参见 UPDATE
)。请注意,计数器的值不能设置。计数器在首次增量/减量之前不存在,并且首次增量/减量将之前的值为 0。支持删除计数器列,但有一些限制(有关详细信息,请参见 Cassandra Wiki)。
计数器类型的使用受到以下方式的限制
-
它不能用于作为表的
PRIMARY KEY
一部分的列。 -
包含计数器的表只能包含计数器。换句话说,表中
PRIMARY KEY
之外的所有列都具有计数器类型,或者没有列具有计数器类型。
使用集合
值得注意的特性
集合用于存储/反规范化相对较少的数据量。它们适用于诸如给定用户的电话号码''、
应用于电子邮件的标签''等事物。但是,当预计项目会无限增长(给定用户发送的所有消息''、
传感器注册的事件'',…)时,集合就不再合适,而应该使用特定表(带群集列)。具体来说,集合具有以下限制
-
集合总是整体读取(并且在内部不会分页读取)。
-
集合不能包含超过 65535 个元素。更准确地说,虽然可以插入超过 65535 个元素,但不能读取超过 65535 个第一个元素(有关详细信息,请参见 CASSANDRA-5428)。
-
虽然对集合和映射的插入操作在内部永远不会产生读写前操作,但对列表的一些操作会产生读写前操作(有关详细信息,请参见下面的列表部分)。因此,建议尽可能优先使用集合而不是列表。
请注意,虽然将来可能会放松其中一些限制,但集合用于反规范化少量数据的总体规则将保持不变。
映射
map
是一个 类型化 的键值对集合,其中键是唯一的。此外,请注意,映射在内部按其键排序,因此总是按该顺序返回。要创建 map
类型的列,请使用 map
关键字,后跟用尖括号括起来的逗号分隔的键和值类型。例如
bc(sample).
CREATE TABLE users (
id text PRIMARY KEY,
given text,
surname text,
favs map<text, text> // 文本键和文本值的映射
)
使用受 JSON 启发的语法编写 map
数据。要使用 INSERT
编写记录,请将整个映射指定为 JSON 样式关联数组。注意:此表单将始终替换整个映射。
bc(sample).
INSERT INTO users (id, given, surname, favs)
VALUES (`jsmith', `John', `Smith', \{ `fruit' : `apple', `band' : `Beatles' })
可以通过在UPDATE
语句中对映射列进行标注或添加新的映射文本来添加或更新(可能)存在的映射的键值
bc(sample).
UPDATE users SET favs[`author'] = `Ed Poe' WHERE id = `jsmith'
UPDATE users SET favs = favs + \{ `movie' : `Cassablanca' } WHERE id = `jsmith'
请注意,INSERT
和UPDATE
都允许使用TTL,但在两种情况下,TTL设置仅适用于新插入/更新的值。换句话说,
bc(sample).
UPDATE users USING TTL 10 SET favs[`color'] = `green' WHERE id = `jsmith'
只会将TTL应用于{ 'color' : 'green' }
记录,映射的其余部分不受影响。
使用以下方法删除映射记录
bc(sample).
DELETE favs[`author'] FROM users WHERE id = `jsmith'
集合
set
是唯一值的类型化集合。集合按其值排序。要创建类型为set
的列,请使用set
关键字,后跟用尖括号括起来的类型值。例如
bc(sample).
CREATE TABLE images (
name text PRIMARY KEY,
owner text,
date timestamp,
tags set
);
通过用逗号分隔集合值并在花括号中括起来来编写set
。注意:INSERT
始终会替换整个集合。
bc(sample).
INSERT INTO images (name, owner, date, tags)
VALUES (`cat.jpg', `jsmith', `now', \{ `kitten', `cat', `pet' });
可以通过向现有set
列添加/移除新集合值,使用UPDATE
来添加和移除集合的值。
bc(sample).
UPDATE images SET tags = tags + \{ `cute', `cuddly' } WHERE name = `cat.jpg';
UPDATE images SET tags = tags - \{ `lame' } WHERE name = `cat.jpg';
与映射一样,如果使用TTL,则仅适用于新插入/更新的值。
列表
list
是无唯一值的类型化集合,其中元素按其在列表中的位置排序。要创建类型为list
的列,请使用list
关键字,后跟用尖括号括起来的类型值。例如
bc(sample).
CREATE TABLE plays (
id text PRIMARY KEY,
game text,
players int,
scores list
)
请注意,如下所述,列表有一些限制和性能考虑因素需要考虑,并且建议在可能的情况下优先使用集合而不是列表。
使用JSON样式语法编写list
数据。要使用INSERT
编写记录,请将整个列表指定为JSON数组。注意:INSERT
始终会替换整个列表。
bc(sample).
INSERT INTO plays (id, game, players, scores)
VALUES (`123-afde', `quake', 3, [17, 4, 2]);
可以通过向现有list
列添加新的JSON样式数组,将值添加到列表(追加或前置)中。
bc(sample).
UPDATE plays SET players = 5, scores = scores + [ 14, 21 ] WHERE id = `123-afde';
UPDATE plays SET players = 5, scores = [ 12 ] + scores WHERE id = `123-afde';
需要注意的是,追加和前置不是幂等操作。这意味着如果在追加或前置期间操作超时,则并不总是可以安全地重试操作(因为这可能导致记录被追加或前置两次)。
列表还提供了以下操作:按列表中的位置设置元素、按列表中的位置删除元素以及删除列表中给定值的所有出现。但是,与所有其他集合操作相反,这三个操作在更新之前会引起内部读取,因此通常具有较慢的性能特征。这些操作具有以下语法
bc(sample).
UPDATE plays SET scores[1] = 7 WHERE id = `123-afde'; // 将 scores 的第 2 个元素设置为 7(如果 scores 少于 2 个元素,则会引发错误)
DELETE scores[1] FROM plays WHERE id = `123-afde'; // 删除 scores 的第 2 个元素(如果 scores 少于 2 个元素,则会引发错误)
UPDATE plays SET scores = scores - [ 12, 21 ] WHERE id = `123-afde'; // 从 scores 中删除所有 12 和 21 的出现
与映射一样,如果使用TTL,则仅适用于新插入/更新的值。
使用向量
向量是特定数据类型的非空值的固定大小序列。它们使用与列表相同的文字。
您可以使用以下方法定义、插入和更新向量
CREATE TABLE plays (
id text PRIMARY KEY,
game text,
players int,
scores vector<int, 3> // A vector of 3 integers
)
INSERT INTO plays (id, game, players, scores)
VALUES ('123-afde', 'quake', 3, [17, 4, 2]);
// Replace the existing vector entirely
UPDATE plays SET scores = [ 3, 9, 4] WHERE id = '123-afde';
请注意,无法更改向量的各个值,也无法选择向量的各个元素。
函数
CQL3 区分内置函数(所谓的“本机函数”)和 用户定义函数。CQL3 包含以下所述的几个本机函数
转换
cast
函数可用于将一种本机数据类型转换为另一种本机数据类型。
下表描述了 cast
函数支持的转换。Cassandra 会忽略将数据类型转换为其自身数据类型的任何转换。
从 | 到 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
转换严格依赖于 Java 的语义。例如,双精度值 1 将转换为文本值 `1.0'。
bc(sample).
SELECT avg(cast(count as double)) FROM myTable
令牌
token
函数允许计算给定分区键的令牌。token
函数的确切签名取决于所涉及的表和集群使用的分区器。
token
的参数类型取决于分区键列的类型。返回类型取决于正在使用的分区器
-
对于 Murmur3Partitioner,返回类型为
bigint
。 -
对于 RandomPartitioner,返回类型为
varint
。 -
对于 ByteOrderedPartitioner,返回类型为
blob
。
例如,在使用默认 Murmur3Partitioner 的集群中,如果表由以下内容定义:
bc(sample).
CREATE TABLE users (
userid text PRIMARY KEY,
username text,
…
)
那么 token
函数将采用类型为 text
的单个参数(在这种情况下,分区键为 userid
(没有聚类列,因此分区键与主键相同)),并且返回类型将为 bigint
。
Timeuuid 函数
now
now
函数不采用任何参数,并在协调器节点上生成一个新的唯一 timeuuid(在使用它的语句执行时)。请注意,此方法对于插入很有用,但在 WHERE
子句中基本上没有意义。例如,以下形式的查询
bc(sample).
SELECT * FROM myTable WHERE t = now()
根据设计永远不会返回任何结果,因为 now()
返回的值保证是唯一的。
min_timeuuid
和 max_timeuuid
min_timeuuid
(分别为 max_timeuuid
)函数采用 timestamp
值 t
(可以 是时间戳或日期字符串),并返回一个伪 timeuuid
,该 timeuuid
对应于具有时间戳 t
的最小(分别为最大)可能的 timeuuid
。例如
bc(sample).
SELECT * FROM myTable WHERE t > max_timeuuid(`2013-01-01 00:05+0000') AND t < min_timeuuid(`2013-02-02 10:00+0000')
将选择 timeuuid
列 t
严格早于 2013-01-01 00:05+0000' 但严格晚于 `2013-02-02 10:00+0000' 的所有行。请注意,`t >= max_timeuuid('2013-01-01 00:05+0000')
仍然不会选择在 2013-01-01 00:05+0000' 确切生成的 `timeuuid
,并且基本上等同于 `t > max_timeuuid('2013-01-01 00:05+0000')。
警告:我们称由 min_timeuuid
和 max_timeuuid
生成的值伪 UUID,因为它们不尊重 RFC 4122 指定的基于时间的 UUID 生成过程。特别是,这 2 个方法返回的值不会是唯一的。这意味着你应该仅将这些方法用于查询(如上面的示例)。插入这些方法的结果几乎肯定是个坏主意。
时间转换函数
提供许多函数来将 `timeuuid'' 转换为 `timestamp' 或 `date',或将 `timestamp' 或 `date' 转换为另一个 `native' 类型。
函数名称 | 输入类型 | 说明 |
---|---|---|
|
|
将 |
|
|
将 |
|
|
将 |
|
|
将 |
|
|
将 |
|
|
将 |
|
|
将 |
聚合
聚合函数作用于一组行。它们接收每行的值,并为整个集合返回一个值。
如果将“`正常'' 列、`标量函数''、`UDT'' 字段、`writetime''、`maxwritetime'' 或`ttl'' 与聚合函数一起选择,则为它们返回的值将是与查询匹配的第一行的值。
CQL3 区分内置聚合(所谓的“`本机聚合'')和用户定义的聚合。CQL3 包含几个本机聚合,如下所述
计数
count
函数可用于统计查询返回的行数。示例
bc(sample).
SELECT COUNT (*) FROM plays;
SELECT COUNT (1) FROM plays;
它还可用于统计给定列的非空值。示例
bc(sample).
SELECT COUNT (scores) FROM plays;
用户定义的函数
用户定义的函数允许在 Cassandra 中执行用户提供的代码。默认情况下,Cassandra 支持在Java和JavaScript中定义函数。在 3.0.11 中已删除对其他 JSR 223 兼容脚本语言(如 Python、Ruby 和 Scala)的支持。
UDF 是 Cassandra 架构的一部分。因此,它们会自动传播到群集中的所有节点。
UDF 可以“`重载'' - 即具有不同参数类型但函数名称相同的多个 UDF。示例
bc(sample).
CREATE FUNCTION sample ( arg int ) …;
CREATE FUNCTION sample ( arg text ) …;
用户定义的函数容易出现所选编程语言的所有常见问题。因此,实现应针对空指针异常、非法参数或任何其他潜在异常来源保持安全。函数执行期间发生的异常会导致整个语句失败。
将复杂类型(如集合、元组类型和用户定义的类型)用作参数和返回类型是有效的。元组类型和用户定义的类型由 DataStax Java 驱动程序的转换函数处理。有关处理元组类型和用户定义类型的详细信息,请参阅 Java 驱动程序的文档。
函数的参数可以是文字或术语。也可以使用已准备的语句占位符。
请注意,可以使用双引号字符串语法来括起 UDF 源代码。例如
bc(sample)..
CREATE FUNCTION some_function ( arg int )
RETURNS NULL ON NULL INPUT
RETURNS int
LANGUAGE java
AS return arg; ;
SELECT some_function(column) FROM atable …;
UPDATE atable SET col = some_function(?) …;
p.
bc(sample).
CREATE TYPE custom_type (txt text, i int);
CREATE FUNCTION fct_using_udt ( udtarg frozen )
RETURNS NULL ON NULL INPUT
RETURNS text
LANGUAGE java
AS return udtarg.getString(``txt''); ;
隐式可用的 udfContext
字段(或脚本 UDF 的绑定)提供了创建新 UDT 和元组值所需的功能。
bc(sample).
CREATE TYPE custom_type (txt text, i int);
CREATE FUNCTION fct_using_udt ( somearg int )
RETURNS NULL ON NULL INPUT
RETURNS custom_type
LANGUAGE java
AS + UDTValue udt = udfContext.newReturnUDTValue(); + udt.setString(``txt'', ``some string''); + udt.setInt(``i'', 42); + return udt; + ;
UDFContext
接口的定义可在 org.apache.cassandra.cql3.functions.UDFContext
的 Apache Cassandra 源代码中找到。
bc(sample).
public interface UDFContext
\{
UDTValue newArgUDTValue(String argName);
UDTValue newArgUDTValue(int argNum);
UDTValue newReturnUDTValue();
UDTValue newUDTValue(String udtName);
TupleValue newArgTupleValue(String argName);
TupleValue newArgTupleValue(int argNum);
TupleValue newReturnTupleValue();
TupleValue newTupleValue(String cqlDefinition);
}
Java UDF 已为定义的通用接口和类进行了一些导入。这些导入是
请注意,脚本 UDF 不提供这些便利导入。
bc(sample).
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.cassandra.cql3.functions.UDFContext;
import com.datastax.driver.core.TypeCodec;
import com.datastax.driver.core.TupleValue;
import com.datastax.driver.core.UDTValue;
请参阅 CREATE FUNCTION
和 DROP FUNCTION
。
用户自定义聚合
用户自定义聚合允许使用 UDF 创建自定义聚合函数。聚合函数的常见示例包括count、min 和 max。
每个聚合都需要一个初始状态(INITCOND
,默认为 null
)类型为 STYPE
。状态函数的第一个参数必须为 STYPE
类型。状态函数的其余参数必须与用户自定义聚合参数的类型匹配。状态函数对每一行调用一次,状态函数返回的值变为新状态。在处理完所有行后,将使用最后一个状态值作为其参数执行可选的 FINALFUNC
。
STYPE
是强制性的,以便能够区分状态和/或最终函数的可能重载版本(因为重载可能在创建聚合后出现)。
用户自定义聚合可用于 SELECT
语句。
用户自定义聚合的完整工作示例(假设已使用 USE
语句选择了键空间)
bc(sample)..
CREATE OR REPLACE FUNCTION averageState ( state tuple<int,bigint>, val int )
CALLED ON NULL INPUT
RETURNS tuple<int,bigint>
LANGUAGE java
AS ’
if (val != null) \{
state.setInt(0, state.getInt(0)+1);
state.setLong(1, state.getLong(1)+val.intValue());
}
return state;
’;
CREATE OR REPLACE FUNCTION averageFinal ( state tuple<int,bigint> )
CALLED ON NULL INPUT
RETURNS double
LANGUAGE java
AS ’
double r = 0;
if (state.getInt(0) == 0) return null;
r = state.getLong(1);
r /= state.getInt(0);
return Double.valueOf®;
’;
CREATE OR REPLACE AGGREGATE average ( int )
SFUNC averageState
STYPE tuple<int,bigint>
FINALFUNC averageFinal
INITCOND (0, 0);
CREATE TABLE atable (
pk int PRIMARY KEY,
val int);
INSERT INTO atable (pk, val) VALUES (1,1);
将 INSERT INTO atable (pk, val) VALUES (2,2);
将 INSERT INTO atable (pk, val) VALUES (3,3);
将 INSERT INTO atable (pk, val) VALUES (4,4);
SELECT average(val) FROM atable;
p.
请参见 CREATE AGGREGATE
和 DROP AGGREGATE
。
JSON 支持
Cassandra 2.2 为 SELECT
和 INSERT
语句引入了 JSON 支持。此支持不会从根本上改变 CQL API(例如,仍然强制执行架构),它只是提供了一种使用 JSON 文档的便捷方式。
SELECT JSON
对于 SELECT
语句,可以使用新的 JSON
关键字将每一行返回为一个单一的 JSON
编码映射。SELECT
语句行为的其余部分保持不变。
结果映射键与普通结果集中的列名相同。例如,类似于
和 SELECT JSON a, ttl(b) FROM …’' 的语句将生成一个键为
`"a""ttl(b)"
的映射。但是,有一个值得注意的例外:为了与 INSERT JSON
行为保持对称,大小写敏感且包含大写字母的列名将被双引号包围。例如,SELECT JSON myColumn FROM …’' 将生成一个映射键 `"\"myColumn\""
(注意转义引号)。
映射值将是结果集值的 JSON
编码表示(如下所述)。
INSERT JSON
对于 INSERT
语句,可以使用新的 JSON
关键字将 JSON
编码映射作为单行插入。JSON
映射的格式通常应与在同一表上执行 SELECT JSON
语句返回的格式相匹配。特别是,大小写敏感的列名应被双引号包围。例如,要插入到一个名为 myKey'' 和
value'' 的两列的表中,您需要执行以下操作
bc(sample).
将 INSERT INTO mytable JSON `\{\''myKey\
'': 0, ``value'': 0}'
从 JSON
映射中省略的任何列将默认为 NULL
值(这将导致创建墓碑)。
Cassandra 数据类型的 JSON 编码
在可能的情况下,Cassandra 将以其本机 JSON
表示形式表示和接受数据类型。Cassandra 还将接受与所有单字段类型的 CQL 文字格式匹配的字符串表示形式。例如,浮点数、整数、UUID 和日期可以用 CQL 文字字符串表示。但是,复合类型(例如集合、元组和用户定义类型)必须由本机 JSON
集合(映射和列表)或集合的 JSON 编码字符串表示形式表示。
下表描述了 Cassandra 将在 INSERT JSON
值(和 from_json()
参数)中接受的编码,以及 Cassandra 在为 SELECT JSON
语句(和 from_json()
)返回数据时将使用的格式
类型 | 接受的格式 | 返回格式 | 注释 |
---|---|---|---|
|
字符串 |
字符串 |
使用 JSON 的 |
|
整数、字符串 |
整数 |
字符串必须是有效的 64 位整数 |
|
字符串 |
字符串 |
字符串应为 0x 后跟偶数个十六进制数字 |
|
布尔值、字符串 |
boolean |
字符串必须为 |
|
字符串 |
字符串 |
日期格式为 |
|
整数、浮点数、字符串 |
float |
可能超出客户端解码器中的 32 或 64 位 IEEE-754 浮点精度 |
|
整数、浮点数、字符串 |
float |
字符串必须是有效的整数或浮点数 |
|
整数、浮点数、字符串 |
float |
字符串必须是有效的整数或浮点数 |
|
字符串 |
字符串 |
IPv4 或 IPv6 地址 |
|
整数、字符串 |
整数 |
字符串必须是有效的 32 位整数 |
|
列表、字符串 |
列表 |
使用 JSON 的本机列表表示法 |
|
映射、字符串 |
映射 |
使用 JSON 的本机映射表示法 |
|
整数、字符串 |
整数 |
字符串必须是有效的 16 位整数 |
|
列表、字符串 |
列表 |
使用 JSON 的本机列表表示法 |
|
字符串 |
字符串 |
使用 JSON 的 |
|
字符串 |
字符串 |
时间格式为 |
|
整数、字符串 |
字符串 |
时间戳。允许将字符串常量作为日期输入时间戳,有关更多信息,请参阅下面的 使用日期。返回格式为 |
|
字符串 |
字符串 |
类型 1 UUID。有关 UUID 格式,请参阅 常量 |
|
整数、字符串 |
整数 |
字符串必须是有效的 8 位整数 |
|
列表、字符串 |
列表 |
使用 JSON 的本机列表表示法 |
|
映射、字符串 |
映射 |
使用 JSON 的本机映射表示法,其中字段名称作为键 |
|
字符串 |
字符串 |
有关 UUID 格式,请参阅 常量 |
|
字符串 |
字符串 |
使用 JSON 的 |
|
整数、字符串 |
整数 |
可变长度;可能溢出客户端解码器中的 32 或 64 位整数 |
附录 A:CQL 关键字
CQL 区分保留关键字和非保留关键字。保留关键字不能用作标识符,它们真正保留给该语言(但可以用双引号将保留关键字括起来,以将其用作标识符)。然而,非保留关键字仅在特定上下文中具有特定含义,但在其他情况下可以用作标识符。这些非保留关键字存在的唯一理由是方便:当解析器始终可以轻松判断它们是作为关键字还是非关键字使用时,一些关键字是非保留的。
关键字 | 保留? |
---|---|
|
是 |
|
否 |
|
否 |
|
是 |
|
是 |
|
是 |
|
是 |
|
否 |
|
是 |
|
否 |
|
是 |
|
是 |
|
是 |
|
否 |
|
否 |
|
否 |
|
是 |
|
否 |
|
否 |
|
否 |
|
是 |
|
否 |
|
否 |
|
否 |
|
否 |
|
是 |
|
否 |
|
否 |
|
否 |
|
是 |
|
是 |
|
是 |
|
是 |
|
否 |
|
否 |
|
是 |
|
否 |
|
是 |
|
是 |
|
否 |
|
否 |
|
否 |
|
否 |
|
是 |
|
否 |
|
是 |
|
否 |
|
否 |
|
是 |
|
否 |
|
是 |
|
是 |
|
是 |
|
否 |
|
是 |
|
否 |
|
否 |
|
是 |
|
否 |
|
是 |
|
是 |
|
否 |
|
否 |
|
否 |
|
是 |
|
否 |
|
否 |
|
否 |
|
是 |
|
否 |
|
否 |
|
否 |
|
否 |
|
是 |
|
是 |
|
是 |
|
是 |
|
是 |
|
否 |
|
是 |
|
否 |
|
是 |
|
是 |
|
是 |
|
是 |
|
否 |
|
是 |
|
是 |
|
否 |
|
否 |
|
否 |
|
否 |
|
否 |
|
是 |
|
是 |
|
是 |
|
否 |
|
是 |
|
否 |
|
否 |
|
是 |
|
是 |
|
否 |
|
是 |
|
否 |
|
否 |
|
否 |
|
否 |
|
否 |
|
否 |
|
是 |
|
否 |
|
否 |
|
否 |
|
否 |
|
否 |
|
是 |
|
是 |
|
否 |
|
是 |
|
否 |
|
否 |
|
否 |
|
是 |
|
否 |
|
是 |
|
是 |
|
是 |
|
否 |
|
否 |
|
是 |
|
否 |
|
否 |
|
否 |
|
否 |
|
是 |
|
是 |
|
是 |
|
否 |
附录 B:CQL 保留类型
以下类型名称目前未被 CQL 使用,但已保留以备将来使用。用户定义类型不得使用保留类型名称作为其名称。
类型 |
---|
|
|
|
|
|
|
|
更改
以下描述了 CQL 各个版本中的更改。
3.4.3
-
支持
GROUP BY
。参见<group-by>
(参见 CASSANDRA-10707)。
3.4.2
-
支持选择集合的元素和切片 (CASSANDRA-7396)。
3.4.2
-
INSERT/UPDATE options
对于具有 default_time_to_live 的表,指定 TTL 为 0 将从插入或更新的值中移除 TTL -
ALTER TABLE
ADD
和DROP
现在允许添加/移除多列 -
新的
PER PARTITION LIMIT
选项(参见 CASSANDRA-7017)。 -
用户定义函数 现在可以通过新的
UDFContext
接口实例化UDTValue
和TupleValue
实例(参见 CASSANDRA-10818)。 -
`用户定义类型''#createTypeStmt 现在可以存储为非冻结形式,允许在 `UPDATE`
语句 和DELETE
语句 中更新和删除各个字段,分别。(CASSANDRA-7423)
3.4.1
-
添加
CAST
函数。参见Cast
。
3.3.0
-
添加新的 聚合
-
现在通过
CREATE FUNCTION
和DROP FUNCTION
支持用户定义函数。 -
现在通过
CREATE AGGREGATE
和DROP AGGREGATE
支持用户定义聚合。 -
允许双美元符号括起来的字符串文字作为单引号括起来的字符串的替代。
-
引入角色来取代基于用户的身份验证和访问控制
-
已添加
JSON
支持 -
已添加
Tinyint
和Smallint
数据类型 -
添加新的时间转换函数,并弃用
dateOf
和unixTimestampOf
。参见时间转换函数
3.2.0
-
现在通过
CREATE TYPE
、ALTER TYPE
和DROP TYPE
支持用户定义类型 -
CREATE INDEX
现在支持索引集合列,包括通过keys()
函数索引映射集合的键 -
可以使用新的
CONTAINS
和CONTAINS KEY
运算符查询集合上的索引 -
添加元组类型以保存固定长度的类型化位置字段集(请参阅 类型 部分)
-
DROP INDEX
现在支持选择性指定键空间
3.1.7
-
SELECT
语句现在支持使用组合聚类列上的IN
子句在单个分区中选择多行。请参阅 SELECT WHERE 子句。 -
IF NOT EXISTS
和IF EXISTS
语法现在分别受CREATE USER
和DROP USER
语句支持。
3.1.6
-
已添加一个新的
uuid
方法。 -
支持
DELETE … IF EXISTS
语法。
3.1.5
-
现在可以在关系中对聚类列进行分组,请参阅 SELECT WHERE 子句。
-
添加了对
STATIC
列的支持,请参阅 CREATE TABLE 中的 static。
3.1.4
-
CREATE INDEX
现在允许在创建 CUSTOM 索引时指定选项(请参阅 CREATE INDEX 参考 )。
3.1.3
-
已将毫秒精度格式添加到时间戳解析器(请参阅 使用日期 )。
3.1.2
-
NaN
和Infinity
已被添加为有效的浮点数常量。它们现在是保留关键字。在不太可能将它们用作列标识符(或键空间/表标识符)的情况下,现在需要用双引号将它们引起来(请参阅 引用标识符 )。
3.1.1
-
SELECT
语句现在允许列出分区键(使用DISTINCT
修饰符)。请参阅 CASSANDRA-4536。 -
现在在
WHERE
子句中支持c IN ?
语法。在这种情况下,绑定变量的预期值将是c
类型的列表。 -
现在可以使用命名绑定变量(使用
:name
代替?
)。
3.1.0
-
ALTER TABLE
DROP
选项已重新启用 CQL3 表,现在具有新的语义:以前由已删除列使用的空间现在将最终回收(压缩后)。除非使用具有微秒精度的时戳,否则不应重新添加以前删除的列(有关更多详细信息,请参阅 CASSANDRA-3919)。 -
SELECT
语句现在支持选择子句中的别名。不支持 WHERE 和 ORDER BY 子句中的别名。有关详细信息,请参阅 选择部分。 -
KEYSPACE
、TABLE
和INDEX
的CREATE
语句现在支持IF NOT EXISTS
条件。类似地,DROP
语句支持IF EXISTS
条件。 -
INSERT
语句选择性地支持IF NOT EXISTS
条件,UPDATE
支持IF
条件。
3.0.5
-
SELECT
、UPDATE
和DELETE
语句现在允许空IN
关系(请参阅 CASSANDRA-5626)。
3.0.3
-
已添加对自定义辅助索引的支持。
3.0.2
-
已修复常量的类型验证。例如,该实现过去允许将
'2'
作为int
列的有效值(将其解释为2
的等效值),或将42
作为有效的blob
值(在这种情况下,将42
解释为 blob 的十六进制表示形式)。现在不再是这样,常量的类型验证现在更加严格。有关哪些常量允许用于哪种类型的详细信息,请参阅数据类型部分。 -
前一点中修复的类型验证已导致引入blob 常量以允许输入 blob。请注意,虽然此版本仍支持将 blob 输入为字符串常量(以允许更平滑地过渡到 blob 常量),但现在已弃用(特别是数据类型部分未将字符串常量列为有效的 blob)并且将被未来版本删除。如果您将字符串用作 blob,则应尽快更新您的客户端代码以切换 blob 常量。
-
还引入了一些将本机类型转换为 blob 的函数。此外,现在还允许在选择子句中使用令牌函数。有关详细信息,请参阅函数部分。
3.0.1
-
日期字符串(和时间戳)不再被接受为有效的
timeuuid
值。这样做是一个错误,因为日期字符串不是有效的timeuuid
,因此导致令人困惑的行为。但是,已添加以下新方法来帮助使用timeuuid
:now
、minTimeuuid
、maxTimeuuid
、dateOf
和unixTimestampOf
。有关更多详细信息,请参阅专门介绍这些方法的部分。 -
`浮点常量''#constants 现在支持指数表示法。换句话说,`4.2E10` 现在是一个有效的浮点值。
版本控制
CQL 语言的版本控制遵循语义版本控制准则。版本采用 X.Y.Z 形式,其中 X、Y 和 Z 是分别表示主版本、次版本和修补程序级别的整数值。Cassandra 发布版本与 CQL 语言版本之间没有相关性。
版本 | 说明 |
---|---|
主版本 |
当引入向后不兼容的更改时,必须增加主版本。这种情况很少发生。 |
次版本 |
当引入新的但向后兼容的功能时,会增加次版本。 |
修补程序 |
当修复错误时,会增加修补程序版本。 |