To aid in specifying the CQL syntax, we will use the following conventions in this document:
[ item ]
) for optional items, *
and +
for repeated items (where +
imply at least one).re(<some regular expression>)
.CREATE TABLE
statement is optional but supported if present even though the grammar in
this document suggests otherwise. Also, not everything accepted by the grammar is necessarily valid CQL.fixed-width font
.The CQL language uses identifiers (or names) to identify tables, columns and other objects. An identifier is a token
matching the regular expression [a-zA-Z][a-zA-Z0-9_]*
.
A number of such identifiers, like SELECT
or WITH
, are keywords. They have a fixed meaning for the language
and most are reserved. The list of those keywords can be found in Appendix A: CQL Keywords.
Identifiers and (unquoted) keywords are case insensitive. Thus SELECT
is the same than select
or sElEcT
, and
myId
is the same than myid
or MYID
. A convention often used (in particular by the samples of this
documentation) is to use upper case for keywords and lower case for other identifiers.
There is a second kind of identifiers called quoted identifiers defined by enclosing an arbitrary sequence of
characters (non empty) in double-quotes("
). Quoted identifiers are never keywords. Thus "select"
is not a
reserved keyword and can be used to refer to a column (note that using this is particularly advised), while select
would raise a parsing error. Also, contrarily to unquoted identifiers and keywords, quoted identifiers are case
sensitive ("My Quoted Id"
is different from "my quoted id"
). A fully lowercase quoted identifier that matches
[a-zA-Z][a-zA-Z0-9_]*
is however equivalent to the unquoted identifier obtained by removing the double-quote (so
"myid"
is equivalent to myid
and to myId
but different from "myId"
). Inside a quoted identifier, the
double-quote character can be repeated to escape it, so "foo "" bar"
is a valid identifier.
Note
quoted identifiers allows to declare columns with arbitrary names, and those can sometime clash with
specific names used by the server. For instance, when using conditional update, the server will respond with a
result-set containing a special result named "[applied]"
. If you’ve declared a column with such a name, this
could potentially confuse some tools and should be avoided. In general, unquoted identifiers should be preferred but
if you use quoted identifiers, it is strongly advised to avoid any name enclosed by squared brackets (like
"[applied]"
) and any name that looks like a function call (like "f(x)"
).
More formally, we have:
identifier ::=unquoted_identifier
|quoted_identifier
unquoted_identifier ::= re('[a-zA-Z][a-zA-Z0-9_]*') quoted_identifier ::= '"' (any character where " can appear if doubled)+ '"'
CQL defines the following kind of constants:
constant ::=string
|integer
|float
|boolean
|uuid
|blob
| NULL string ::= '\'' (any character where ' can appear if doubled)+ '\'' '$$' (any character other than '$$') '$$' integer ::= re('-?[0-9]+') float ::= re('-?[0-9]+(\.[0-9]*)?([eE][+-]?[0-9+])?') | NAN | INFINITY boolean ::= TRUE | FALSE uuid ::=hex
{8}-hex
{4}-hex
{4}-hex
{4}-hex
{12} hex ::= re("[0-9a-fA-F]") blob ::= '0' ('x' | 'X')hex
+
In other words:
'
). A single-quote
can be included by repeating it, e.g. 'It''s raining today'
. Those are not to be confused with quoted
Identifiers and keywords that use double-quotes. Alternatively, a string can be defined by enclosing the arbitrary sequence
of characters by two dollar characters, in which case single-quote can be used without escaping ($$It's raining
today$$
). That latter form is often used when defining user-defined functions to avoid having to
escape single-quote characters in function body (as they are more likely to occur than $$
).NaN
and
Infinity
constants.0x
.NULL
constant denotes the absence of value.For how these constants are typed, see the Data Types section.
CQL has the notion of a term, which denotes the kind of values that CQL support. Terms are defined by:
term ::=constant
|literal
|function_call
|arithmetic_operation
|type_hint
|bind_marker
literal ::=collection_literal
|udt_literal
|tuple_literal
function_call ::=identifier
'(' [term
(','term
)* ] ')' arithmetic_operation ::= '-'term
|term
('+' | '-' | '*' | '/' | '%')term
type_hint ::= '('cql_type
`)` term bind_marker ::= '?' | ':'identifier
A term is thus one of:
?
) or named (:some_name
). The latter form provides a more
convenient way to refer to the variable for binding it and should generally be preferred.A comment in CQL is a line beginning by either double dashes (--
) or double slash (//
).
Multi-line comments are also supported through enclosure within /*
and */
(but nesting is not supported).
-- This is a comment
// This is a comment too
/* This is
a multi-line comment */
CQL consists of statements that can be divided in the following categories:
All the statements are listed below and are described in the rest of this documentation (see links above):
cql_statement ::=statement
[ ';' ] statement ::=ddl_statement
|dml_statement
|secondary_index_statement
|materialized_view_statement
|role_or_permission_statement
|udf_statement
|udt_statement
|trigger_statement
ddl_statement ::=use_statement
|create_keyspace_statement
|alter_keyspace_statement
|drop_keyspace_statement
|create_table_statement
|alter_table_statement
|drop_table_statement
|truncate_statement
dml_statement ::=select_statement
|insert_statement
|update_statement
|delete_statement
|batch_statement
secondary_index_statement ::=create_index_statement
|drop_index_statement
materialized_view_statement ::=create_materialized_view_statement
|drop_materialized_view_statement
role_or_permission_statement ::=create_role_statement
|alter_role_statement
|drop_role_statement
|grant_role_statement
|revoke_role_statement
|list_roles_statement
|grant_permission_statement
|revoke_permission_statement
|list_permissions_statement
|create_user_statement
|alter_user_statement
|drop_user_statement
|list_users_statement
udf_statement ::=create_function_statement
|drop_function_statement
|create_aggregate_statement
|drop_aggregate_statement
udt_statement ::=create_type_statement
|alter_type_statement
|drop_type_statement
trigger_statement ::=create_trigger_statement
|drop_trigger_statement
CQL supports prepared statements. Prepared statements are an optimization that allows to parse a query only once but execute it multiple times with different concrete values.
Any statement that uses at least one bind marker (see bind_marker
) will need to be prepared. After which the statement
can be executed by provided concrete values for each of its marker. The exact details of how a statement is prepared
and then executed depends on the CQL driver used and you should refer to your driver documentation.