SQL user guide
The User Guide describes how users can start up with SQL with Tarantool, and necessary concepts.
Heading | Введение |
---|---|
Getting Started | Typing SQL statements on a console |
Supported Syntax | For example what characters are allowed |
Concepts | tokens, literals, identifiers, operands, operators, expressions, statements |
Data type conversion | Casting, implicit or explicit |
Пояснения по установке и запуску сервера Tarantool приведены в других главах руководства по Tarantool.
To get started specifically with the SQL features, using Tarantool as a client, execute these requests:
box.cfg{}
box.execute([[VALUES ('hello');]])
The bottom of the screen should now look like this:
tarantool> box.execute([[VALUES ('hello');]])
---
- metadata:
- name: COLUMN_1
type: string
rows:
- ['hello']
...
That’s an SQL statement done with Tarantool.
Now you are ready to execute any SQL statements via the connection. For example
box.execute([[CREATE TABLE things (id INTEGER PRIMARY key,
remark STRING);]])
box.execute([[INSERT INTO things VALUES (55, 'Hello SQL world!');]])
box.execute([[SELECT * FROM things WHERE id > 0;]])
And you will see the results of the SQL query.
For the rest of this chapter, the
box.execute([[…]]) enclosure will not be shown.
Examples will simply say what a piece of syntax looks like, such as
SELECT 'hello';
and users should know that must be entered as
box.execute([[SELECT 'hello';]])
It is also legal to enclose SQL statements inside single or double quote marks instead of [[ … ]].
Keywords, for example CREATE or INSERT or VALUES, may be entered in either upper case or lower case.
Literal values, for example 55
or 'Hello SQL world!'
, should be entered without single quote marks
if they are numeric, and should be entered with single quote marks if they are strings.
Object names, for example table1 or column1, should usually be entered without double quote marks and are subject to some restrictions. They may be enclosed in double quote marks and in that case they are subject to fewer restrictions.
Almost all keywords are reserved, which means that they cannot be used as object names unless they are enclosed in double quote marks.
Comments may be between /*
and */
(bracketed)
or between --
and the end of a line (simple).
INSERT /* This is a bracketed comment */ INTO t VALUES (5);
INSERT INTO t VALUES (5); -- this is a simple comment
Выражения, например a + b
или a > b AND NOT a <= b
, могут содержать арифметические операторы + - / *
и операторы сравнения = > < <= >= LIKE
, а также могут использоваться вместе с AND OR NOT
, при этом круглые скобки необязательны.
In the SQL beginners“ guide there was discussion of:
What are: relational databases, tables, views, rows, and columns?
What are: transactions, write-ahead logs, commits and rollbacks?
What are: security considerations?
How to: add, delete, or update rows in tables?
How to: work inside transactions with commits and/or rollbacks?
How to: select, join, filter, group, and sort rows?
Tarantool has a «schema». A schema is a container for all database objects. A schema may be called a «database» in other DBMS implementations
Tarantool allows four types of «database objects» to be created within the schema: tables, triggers, indexes, and constraints. Within tables, there are «columns».
Almost all Tarantool SQL statements begin with a reserved-word «verb»
such as INSERT, and end optionally with a semicolon.
For example: INSERT INTO t VALUES (1);
A Tarantool SQL database and a Tarantool NoSQL database are the same thing. However, some operations are only possible with SQL, and others are only possible with NoSQL. Mixing SQL statements with NoSQL requests is allowed.
The token is the minimum SQL-syntax unit that Tarantool understands. These are the types of tokens:
Ключевые слова — официальные слова языка, например SELECT
.
Литералы — числовые или строковые константы, например 15.7
или 'Taranto'
.
Идентификаторы — имена объектов, например column55
или table_of_accounts
.
Операторы (строго говоря, неалфавитные операторы) — математические операторы, например * / + - ( ) , ; < = >=
.
Токены могут быть отделены друг от друга одним или несколькими разделителями.
* Символы-разделители: табуляция (U+0009), перевод строки (U+000A), вертикальная табуляция (U+000B), смена страницы (U+000C), возврат каретки (U+000D), пробел (U+0020), следующая строка (U+0085), а также все редкие символы классов Zl, Zp и Zs Юникода. Полный список символов вы найдете на странице https://github.com/tarantool/tarantool/issues/2371.
* Комментарии (начинаются с /*
и заканчиваются */
).
* Однострочные комментарии (начинаются с --
и заканчиваются переводом строки).
Разделители не нужны ни перед операторами, ни после них.
Разделители необходимы после ключевых слов, числовых значений или обычных идентификаторов, если только следующий токен не является оператором.
Таким образом, Tarantool может понять следующую серию из шести токенов:
SELECT'a'FROM/**/t;
Но для удобства чтения токены обычно разделяют пробелами:
SELECT 'a' FROM /**/ t;
There are eight kinds of literals: BOOLEAN INTEGER DOUBLE DECIMAL STRING VARBINARY MAP ARRAY.
BOOLEAN literals:
TRUE | FALSE | UNKNOWN
A literal has data type = BOOLEAN if it is the keyword TRUE or FALSE.
UNKNOWN is a synonym for NULL.
A literal may have type = BOOLEAN if it is the keyword NULL and there is no context to indicate a different data type.
INTEGER literals:
[plus-sign | minus-sign] digit [digit …]
or, for a hexadecimal integer literal,
[plus-sign | minus-sign] 0X | 0x hexadecimal-digit [hexadecimal-digit …]
Examples: 5, -5, +5, 55555, 0X55, 0x55
Hexadecimal 0X55 is equal to decimal 85.
A literal has data type = INTEGER if it contains only digits and is in
the range -9223372036854775808 to +18446744073709551615, integers outside that range are illegal.
DOUBLE literals:
[E|e [plus-sign | minus-sign] digit …]
Examples: 1E5, 1.1E5.
A literal has data type = DOUBLE if it contains «E».
DOUBLE literals are also known as floating-point literals or approximate-numeric literals.
To represent «Inf» (infinity), write a real numeric outside the double-precision numeric range, for example 1E309.
To represent «nan» (not a number), write an expression that does not result in a real numeric,
for example 0/0, using Tarantool/NoSQL. This will appear as NULL in Tarantool/SQL.
In an earlier version literals containing periods were considered to be NUMBER literals.
In a future version «nan» may not appear as NULL.
Prior to Tarantool v. 2.10.0, digits with periods such as .0 were considered to be DOUBLE literals,
but now they are considered to be DECIMAL literals.
DECIMAL literals:
[plus-sign | minus-sign] [digit [digit …]] period [digit [digit …]]
Examples: .0, 1.0, 12345678901234567890.123456789012345678
A literal has data type = DECIMAL if it contains a period, and does not contain «E».
DECIMAL literals may contain up to 38 digits; if there are more, then post-decimal digits may be subject to rounding.
In earlier Tarantool versions literals containing periods were considered to be
NUMBER or DECIMAL literals.
STRING literals:
[quote] [character …] [quote]
Examples: 'ABC'
, 'AB''C'
A literal has data type type = STRING
if it is a sequence of zero or more characters enclosed in single quotes.
The sequence ''
(two single quotes in a row) is treated as '
(a single quote) when enclosed in quotes,
that is, 'A''B'
is interpreted as A'B
.
VARBINARY literals:
X|x [quote] [hexadecimal-digit-pair …] [quote]
Example: X'414243'
, which will be displayed as 'ABC'
.
A literal has data type = VARBINARY
(«variable-length binary») if it is the letter X followed by quotes containing pairs of hexadecimal digits, representing byte values.
MAP literals:
[left curly bracket] key [colon] value [right curly bracket]
Examples: {'a':1}
, {1:'a'}
A map literal is a pair of curly brackets (also called «braces»)
enclosing a STRING or INTEGER or UUID literal (called the map «key»)
followed by a colon
followed by any type of literal (called the map «value»).
This is a minimal form of a MAP expression.
ARRAY literals:
[left square bracket] [literal] [right square bracket]
Examples: [1]
, ['a']
An ARRAY literal is a literal value which is enclosed inside square brackets.
This is a minimal form of an ARRAY expression.
Here are four ways to put non-ASCII characters,such as the Greek letter α alpha, in string literals:
First make sure that your shell program is set to accept characters as UTF-8. A simple way to check is
SELECT hex(cast('α' as VARBINARY));
If the result is CEB1 – which is the hexadecimal value for the UTF-8 representation of α – it is good.
- (1) Simply enclose the character inside
'...'
,
'α'
- (2) Find out what is the hexadecimal code for the UTF-8 representation of α, and enclose that inside
X'...'
, then cast to STRING becauseX'...'
literals are data type VARBINARY not STRING,
CAST(X'CEB1' AS STRING)
- (3) Find out what is the Unicode code point for α, and pass that to the CHAR function.
CHAR(945) /* remember that this is α as data type STRING not VARBINARY */
- (4) Enclose statements inside double quotes and include Lua escapes, for example
box.execute("SELECT '\206\177';")
One can use the concatenation operator ||
to combine characters made with any of these methods.
Limitations: (Issue#2344)
* LENGTH('A''B') = 3
which is correct, but on the Tarantool console the display from
SELECT A''B;
is A''B
, which is misleading.
* It is unfortunate that X'41'
is a byte sequence which looks the same as 'A'
,
but it is not the same. box.execute("select 'A' < X'41';")
is not legal at the moment.
This happens because TYPEOF(X'41')
yields 'varbinary'
.
Also it is illegal to say UPDATE ... SET string_column = X'41'
,
one must say UPDATE ... SET string_column = CAST(X'41' AS STRING);
.
All database objects – tables, triggers, indexes, columns, constraints, functions, collations – have identifiers.
An identifier should begin with a letter or underscore ('_'
) and should contain
only letters, digits, dollar signs ('$'
), or underscores.
The maximum number of bytes in an identifier is between 64982 and 65000.
For compatibility reasons, Tarantool recommends that an identifier should not have more than 30 characters.
Letters in identifiers do not have to come from the Latin alphabet, for example the Japanese syllabic ひ and the Cyrillic letter д are legal. But be aware that a Latin letter needs only one byte but a Cyrillic letter needs two bytes, so Cyrillic identifiers consume a tiny amount more space.
Certain words are reserved and should not be used for identifiers. The simple rule is: if a word means something in Tarantool SQL syntax, do not try to use it for an identifier. The current list of reserved words is:
ALL ALTER ANALYZE AND ANY ARRAY AS ASC ASENSITIVE AUTOINCREMENT BEGIN BETWEEN BINARY BLOB BOOL BOOLEAN BOTH BY CALL CASE CAST CHAR CHARACTER CHECK COLLATE COLUMN COMMIT CONDITION CONNECT CONSTRAINT CREATE CROSS CURRENT CURRENT_DATE CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER CURSOR DATE DATETIME DEC DECIMAL DECLARE DEFAULT DEFERRABLE DELETE DENSE_RANK DESC DESCRIBE DETERMINISTIC DISTINCT DOUBLE DROP EACH ELSE ELSEIF END ESCAPE EXCEPT EXISTS EXPLAIN FALSE FETCH FLOAT FOR FOREIGN FROM FULL FUNCTION GET GRANT GROUP HAVING IF IMMEDIATE IN INDEX INNER INOUT INSENSITIVE INSERT INT INTEGER INTERSECT INTO IS ITERATE JOIN LEADING LEAVE LEFT LIKE LIMIT LOCALTIME LOCALTIMESTAMP LOOP MAP MATCH NATURAL NOT NULL NUM NUMBER NUMERIC OF ON OR ORDER OUT OUTER OVER PARTIAL PARTITION PRAGMA PRECISION PRIMARY PROCEDURE RANGE RANK READS REAL RECURSIVE REFERENCES REGEXP RELEASE RENAME REPEAT REPLACE RESIGNAL RETURN REVOKE RIGHT ROLLBACK ROW ROWS ROW_NUMBER SAVEPOINT SCALAR SELECT SENSITIVE SEQSCAN SESSION SET SIGNAL SIMPLE SMALLINT SPECIFIC SQL START STRING SYSTEM TABLE TEXT THEN TO TRAILING TRANSACTION TRIGGER TRIM TRUE TRUNCATE UNION UNIQUE UNKNOWN UNSIGNED UPDATE USER USING UUID VALUES VARBINARY VARCHAR VIEW WHEN WHENEVER WHERE WHILE WITH
Identifiers may be enclosed in double quotes.
These are called quoted identifiers or «delimited identifiers»
(unquoted identifiers may be called «regular identifiers»).
The double quotes are not part of the identifier.
A delimited identifier may be a reserved word and may contain
any printable character. Tarantool converts letters in regular
identifiers to upper case before it accesses the database,
so for statements like
CREATE TABLE a (a INTEGER PRIMARY KEY);
or
SELECT a FROM a;
the table name is A and the column name is A.
However, Tarantool does not convert delimited identifiers
to upper case, so for statements like
CREATE TABLE "a" ("a" INTEGER PRIMARY KEY);
or
SELECT "a" FROM "a";
the table name is a and the column name is a.
The sequence ""
is treated as "
when enclosed in double quotes,
that is, "A""B"
is interpreted as "A"B"
.
Examples: things, t45, journal_entries_for_2017, ддд, "into"
Внутри некоторых инструкций к идентификаторам можно добавлять квалификаторы для исключения двусмысленности. Квалификатор — это идентификатор объекта более высокого уровня, за которым следует точка. Например, к столбцу column1
в таблице table1
можно обратиться как table1.column1
. Идентификатор, в том числе с добавленным квалификатором, — своего рода имя объекта. Например, в SELECT table1.column1, table2.column1 FROM table1, table2;
соответствующие квалификаторы дают понять, что первый используемый столбец — это column1
из table1
, а второй — column1
из table2
.
The rules are sometimes relaxed for compatibility reasons, for example some non-letter characters such as $ and « are legal in regular identifiers. However, it is better to assume that rules are never relaxed.
The following are examples of legal and illegal identifiers.
_A1 -- legal, begins with underscore and contains underscore | letter | digit
1_A -- illegal, begins with digit
A$« -- legal, but not recommended, try to stick with digits and letters and underscores
+ -- illegal, operator token
grant -- illegal, GRANT is a reserved word
"grant" -- legal, delimited identifiers may be reserved words
"_space" -- legal, but Tarantool already uses this name for a system space
"A"."X" -- legal, for columns only, inside statements where qualifiers may be necessary
'a' -- illegal, single quotes are for literals not identifiers
A123456789012345678901234567890 -- legal, identifiers can be long
ддд -- legal, and will be converted to upper case in identifiers
The following example shows that conversion to upper case affects regular identifiers but not delimited identifiers.
CREATE TABLE "q" ("q" INTEGER PRIMARY KEY);
SELECT * FROM q;
-- Result = "error: 'no such table: Q'.
An operand is something that can be operated on. Literals and column identifiers are operands. So are NULL and DEFAULT.
NULL and DEFAULT are keywords which represent values whose data types are not known until they are assigned or compared, so they are known by the technical term «contextually typed value specifications». (Exception: for the non-standard statement «SELECT NULL FROM table-name;» NULL has data type BOOLEAN.)
Every operand has a data type.
For literals, as seen earlier, the data type is usually determined by the format.
For identifiers, the data type is usually determined by the definition.
The usual determination may change because of context or because of explicit casting.
For some SQL data type names there are aliases.
An alias may be used for data definition.
For example VARCHAR(5) and TEXT are aliases of STRING and may appear in
CREATE TABLE table_name (column_name VARCHAR(5) PRIMARY KEY);
but Tarantool,
if asked, will report that the data type of column_name
is STRING.
For every SQL data type there is a corresponding NoSQL type, for example an SQL STRING is stored in a NoSQL space as type = „string“.
To avoid confusion in this manual, all references to SQL data type names are in upper case and all similar words which refer to NoSQL types or to other kinds of object are in lower case, for example:
- STRING is a data type name, but string is a general term;
- NUMBER — имя типа данных, а «numeric» и «числовое значение» — общие термины.
Although it is common to say that a VARBINARY value is a «binary string», this manual will not use that term and will instead say «byte sequence».
Here are all the SQL data types, their corresponding NoSQL types, their aliases, and minimum / maximum literal examples.
SQL type | NoSQL type | Aliases | Minimum | Maximum |
---|---|---|---|---|
BOOLEAN | boolean (логический) | BOOL | FALSE | TRUE |
INTEGER | integer (целое число) | INT | -9223372036854775808 | 18446744073709551615 |
UNSIGNED | unsigned | (none) | 0 | 18446744073709551615 |
DOUBLE | double (числа с двойной точностью) | (none) | -1.79769e308 | 1.79769e308 |
NUMBER | number | (none) | -1.79769e308 | 1.79769e308 |
DECIMAL | decimal | DEC | -9999999999999999999 9999999999999999999 |
9999999999999999999 9999999999999999999 |
STRING | строка | TEXT, VARCHAR(n) | '' |
'many-characters' |
VARBINARY | varbinary | (none) | X'' |
X'many-hex-digits' |
UUID | uuid | (none) | 00000000-0000-0000- 0000-000000000000 |
ffffffff-ffff-ffff- dfff-ffffffffffff |
DATETIME | datetime | (none) | ||
INTERVAL | interval | (none) | ||
SCALAR | (различные) | (none) | FALSE | максимальное значение UUID |
MAP | map | (none) | {} |
{big-key:big-value} |
ARRAY | array | (none) | [] | [many values] |
ANY | any | (none) | FALSE | [many values] |
BOOLEAN values are FALSE, TRUE, and UNKNOWN (which is the same as NULL). FALSE is less than TRUE.
Значения INTEGER — это числовые значения, которые не содержат десятичной точки и не представлены в экспоненциальной форме записи. Возможные значения: от -2^63
до +2^64
, а также NULL
.
Значения UNSIGNED — это числовые значения, которые не содержат десятичной точки и не представлены в экспоненциальной форме записи. Возможные значения: от 0
до +2^64
, а также NULL
.
Значения DOUBLE — это числовые значения, которые содержат десятичную точку (например, 0.5
) или представлены в экспоненциальной форме записи (например, 5E-1
). Диапазон возможных значений соответствует стандарту IEEE 754 чисел с плавающей точкой, а также включает в себя NULL
. Числа, выходящие за пределы диапазона DOUBLE, могут быть представлены как -inf
или inf
.
Значения NUMBER имеют тот же диапазон, что и значения DOUBLE, но могут быть и целыми числами. Для NUMBER не существует отдельного формата записи (значения типа 1.5
или 1E555
считаются DOUBLE), поэтому при необходимости используйте CAST, чтобы привести значение к типу NUMBER. См. также описание типа „number“ в NoSQL. Арифметические операции и встроенные арифметические функции с типами NUMBER не поддерживаются начиная с версии Tarantool 2.10.1.
DECIMAL values can contain up to 38 digits on either side of a decimal point.
and any arithmetic with DECIMAL values has exact results
(arithmetic with DOUBLE values could have approximate results instead of exact results).
Before Tarantool v. 2.10.0 there was no literal format for DECIMAL,
so it was necessary to use CAST to insist that a numeric
has data type DECIMAL, for example CAST(1.1 AS DECIMAL)
or
CAST('99999999999999999999999999999999999999' AS DECIMAL)
.
See the description of NoSQL type „decimal“.
DECIMAL support in SQL was added in Tarantool version 2.10.1.
STRING values are any sequence of zero or more characters encoded with UTF-8,
or NULL. The possible character values are the same as for the Unicode standard.
Byte sequences which are not valid UTF-8 characters are allowed but not recommended.
STRING literal values are enclosed within single quotes, for example 'literal'
.
If the VARCHAR alias is used for column definition, it must include a maximum
length, for example column_1 VARCHAR(40). However, the maximum length is ignored.
The data-type may be followed by [COLLATE collation-name].
VARBINARY values are any sequence of zero or more octets (bytes), or NULL.
VARBINARY literal values are expressed as X followed by pairs of hexadecimal
digits enclosed within single quotes, for example X'0044'
.
VARBINARY’s NoSQL equivalent is 'varbinary'
but not character string – the
MessagePack storage is MP_BIN (MsgPack binary).
Значения UUID (универсальные уникальные идентификаторы) — это 32 шестнадцатеричные цифры или NULL. Обычный формат UUID это строка, разделённая дефисами на пять групп в формате 8-4-4-4-12, например, '000024ac-7ca6-4ab2-bd75-34742ac91213'
. В MessagePack (расширение MP_EXT) для хранения UUID требуется 16 байт. Значения UUID могут быть созданы с помощью модуля uuid Tarantool/NoSQL или c помощью функций UUID(). Поддержка UUID в SQL была добавлена в версии Tarantool 2.9.1.
DATETIME. Introduced in v. 2.10.0. A datetime table field can be created by using this type, which is semantically equivalent to the standard TIMESTAMP WITH TIME ZONE type.
tarantool> create table T2(d datetime primary key);
---
- row_count: 1
...
tarantool> insert into t2 values ('2022-01-01');
---
- null
- 'Type mismatch: can not convert string(''2022-01-01'') to datetime'
...
tarantool> insert into t2 values (cast('2022-01-01' as datetime));
---
- row_count: 1
...
tarantool> select * from t2;
---
- metadata:
- name: D
type: datetime
rows:
- ['2022-01-01T00:00:00Z']
...
There is no implicit cast available from a string expression to a datetime expression (unlike convention used by majority of SQL vendors). In such cases, you need to use explicit cast from a string value to a datetime value (see the example above).
You can subtract datetime and datetime, datetime and interval, or add datetime and interval in any order (see examples of such arithmetics in the description of the INTERVAL type).
The built-in functions related to the DATETIME type are DATE_PART() and NOW()
INTERVAL. Introduced in v. 2.10.0. Similarly to the DATETIME type, you can define a column of the INTERVAL type.
tarantool> create table T(d datetime primary key, i interval);
---
- row_count: 1
...
tarantool> insert into T values (cast('2022-02-02T01:01' as datetime), cast({'year': 1, 'month': 1} as interval));
---
- row_count: 1
...
tarantool> select * from t;
---
- metadata:
- name: D
type: datetime
- name: I
type: interval
rows:
- ['2022-02-02T01:01:00Z', '+1 years, 1 months']
...
Unlike DATETIME, INTERVAL cannot be a part of an index.
There is no implicit cast available for conversions to an interval from a string or any other type. But there is explicit cast allowed from maps (see examples below).
Intervals can be used in arithmetic operations like +
or -
only with the datetime expression or another interval:
tarantool> select * from t
---
- metadata:
- name: D
type: datetime
- name: I
type: interval
rows:
- ['2022-02-02T01:01:00Z', '+1 years, 1 months']
...
tarantool> select d, d + i, d + cast({'year': 1, 'month': 2} as interval) from t
---
- metadata:
- name: D
type: datetime
- name: COLUMN_1
type: datetime
- name: COLUMN_2
type: datetime
rows:
- ['2022-02-02T01:01:00Z', '2023-03-02T01:01:00Z', '2023-04-02T01:01:00Z']
...
tarantool> select i + cast({'year': 1, 'month': 2} as interval) from t
---
- metadata:
- name: COLUMN_1
type: interval
rows:
- ['+2 years, 3 months']
...
There is the predefined list of known attributes for the map if you want to convert one to the INTERVAL expression:
year
month
week
day
hour
minute
second
nsec
tarantool> select cast({'year': 1, 'month': 1, 'week': 1, 'day': 1, 'hour': 1, 'min': 1, 'sec': 1} as interval)
---
- metadata:
- name: COLUMN_1
type: interval
rows:
- ['+1 years, 1 months, 1 weeks, 1 days, 1 hours, 1 minutes, 1 seconds']
...
tarantool> \set language lua
tarantool> v = {year = 1, month = 1, week = 1, day = 1, hour = 1,
> min = 1, sec = 1, nsec = 1, adjust = 'none'}
---
...
tarantool> box.execute('select cast(#v as interval);', {{['#v'] = v}})
---
- metadata:
- name: COLUMN_1
type: interval
rows:
- ['+1 years, 1 months, 1 weeks, 1 days, 1 hours, 1 minutes, 1.000000001 seconds']
...
SCALAR может использоваться в определениях столбцов. Отдельные значения столбца также могут иметь тип SCALAR. Подробную информацию вы найдете в разделе Определение столбцов — правила для типа данных SCALAR. Вместе с этим типом данных может использоваться [COLLATE название-сортировки]. До версии Tarantool 2.10.1 отдельные значения столбцов могли иметь один из перечисленных выше типов: BOOLEAN, INTEGER, DOUBLE, DECIMAL, STRING, VARBINARY или UUID. Начиная с версии Tarantool 2.10.1 все значения в столбце SCALAR имеют тип SCALAR.
MAP values are key:value combinations which can be produced with
MAP expressions.
Maps cannot be used in arithmetic or comparison (except IS [NOT] NULL
),
and the only
functions where they are allowed are CAST,
QUOTE,
TYPEOF, and functions involving NULL comparisons.
ARRAY values are lists which can be produced with
ARRAY expressions.
Arrays cannot be used in arithmetic or comparison (except IS [NOT] NULL
), and the only
functions where they are allowed are CAST,
QUOTE,
TYPEOF, and functions involving NULL comparisons.
ANY can be used for column definitions and the individual column values have type ANY. The difference between SCALAR and ANY is:
- SCALAR columns may not contain MAP or ARRAY values, but ANY columns may contain them.
- SCALAR values are comparable, while ANY values are not comparable.
Any value of any data type may be NULL. Ordinarily NULL will be cast to the data type of any operand it is being compared to or to the data type of the column it is in. If the data type of NULL cannot be determined from context, it is BOOLEAN.
Most of the SQL data types correspond to
Tarantool/NoSQL types with the same name.
In Tarantool versions before v. 2.10.0,
There were also some Tarantool/NoSQL data types which had no corresponding SQL data types.
In those versions, if Tarantool/SQL reads a Tarantool/NoSQL value of a type that has no SQL equivalent,
Tarantool/SQL could treat it as NULL or INTEGER or VARBINARY.
For example, SELECT "flags" FROM "_vspace";
would return a column whose type is 'map'
.
Such columns can only be manipulated in SQL by
invoking Lua functions.
An operator signifies what operation can be performed on operands.
Almost all operators are easy to recognize because they consist of one-character or two-character non-alphabetic tokens, except for six keyword operators (AND IN IS LIKE NOT OR).
Almost all operators are «dyadic», that is, they are performed on a pair of operands – the only operators that are performed on a single operand are NOT and ~ and (sometimes) -.
The result of an operation is a new operand. If the operator is a comparison operator then the result has data type BOOLEAN (TRUE or FALSE or UNKNOWN). Otherwise the result has the same data type as the original operands, except that: promotion to a broader type may occur to avoid overflow. Arithmetic with NULL operands will result in a NULL operand.
В списке операторов ниже пометка «(арифметическая операция)» указывает на то, что все операнды должны быть числовыми значениями (кроме NUMBER) и в результате тоже должно получиться число. Пометка «(сравнение)» указывает, что операнды должны иметь схожие типы данных и результат будет типа BOOLEAN. Пометка «(логическая операция)» указывает, что операнды должны быть типа BOOLEAN и результат также будет типа BOOLEAN. Если операция невозможна, выбрасывается исключение. Кроме того, существуют особые ситуации: их описание приводится после списка операторов. На месте указанных в примерах конкретных значений (литералов) могут с тем же успехом стоять идентификаторы столбцов.
Начиная с версии Tarantool 2.10.1 арифметические операнды не могут быть типа NUMBER.
+
addition (arithmetic)Add two numerics according to standard arithmetic rules. Example:
1 + 5
, result = 6.
-
subtraction (arithmetic)Subtract second numeric from first numeric according to standard arithmetic rules.
Example:
1 - 5
, result = -4.*
multiplication (arithmetic)Multiply two numerics according to standard arithmetic rules.
Example:
2 * 5
, result = 10./
division (arithmetic)Divide second numeric into first numeric according to standard arithmetic rules. Division by zero is not legal. Division of integers always results in rounding toward zero, use CAST to DOUBLE or to DECIMAL to get non-integer results.
Example:
5 / 2
, result = 2.%
modulus (arithmetic)Divide second numeric into first numeric according to standard arithmetic rules. The result is the remainder. Starting with Tarantool version 2.10.1, operands must be INTEGER or UNSIGNED.
Examples:
17 % 5
, result = 2;-123 % 4
, result = -3.<<
shift left (arithmetic)Shift the first numeric to the left N times, where N = the second numeric. For positive numerics, each 1-bit shift to the left is equivalent to multiplying times 2.
Example:
5 << 1
, result = 10.Примечание
Starting with Tarantool version 2.10.1, operands must be non-negative INTEGER or UNSIGNED.
>>
shift right (arithmetic)Shift the first numeric to the right N times, where N = the second numeric. For positive numerics, each 1-bit shift to the right is equivalent to dividing by 2.
Example:
5 >> 1
, result = 2.Примечание
Starting with Tarantool version 2.10.1, operands must be non-negative INTEGER or UNSIGNED.
&
and (arithmetic)Combine the two numerics, with 1 bits in the result if and only if both original numerics have 1 bits.
Example:
5 & 4
, result = 4.Примечание
Starting with Tarantool version 2.10.1, operands must be non-negative INTEGER or UNSIGNED.
|
or (arithmetic)Combine the two numerics, with 1 bits in the result if either original numeric has a 1 bit.
Example:
5 | 2
, result = 7.Примечание
Starting with Tarantool version 2.10.1, operands must be non-negative INTEGER or UNSIGNED.
~
negate (arithmetic), sometimes called bit inversionChange 0 bits to 1 bits, change 1 bits to 0 bits.
Example:
~5
, result = -6.Примечание
Starting with Tarantool version 2.10.1, the operand must be non-negative INTEGER or UNSIGNED.
<
less than (comparison)Return TRUE if the first operand is less than the second by arithmetic or collation rules.
Example for numerics:
5 < 2
, result = FALSEExample for strings:
'C' < ' '
, result = FALSE<=
less than or equal (comparison)Return TRUE if the first operand is less than or equal to the second by arithmetic or collation rules.
Example for numerics:
5 <= 5
, result = TRUEExample for strings:
'C' <= 'B'
, result = FALSE>
greater than (comparison)Return TRUE if the first operand is greater than the second by arithmetic or collation rules.
Example for numerics:
5 > -5
, result = TRUEExample for strings:
'C' > '!'
, result = TRUE>=
greater than or equal (comparison)Return TRUE if the first operand is greater than or equal to the second by arithmetic or collation rules.
Example for numerics:
0 >= 0
, result = TRUE Example for strings:'Z' >= 'Γ'
, result = FALSE
=
equal (assignment or comparison)After the word SET, «=» means the first operand gets the value from the second operand. In other contexts, «=» returns TRUE if operands are equal.
Example for assignment:
... SET column1 = 'a';
Example for numerics:
0 = 0
, result = TRUEExample for strings:
'1' = '2 '
, result = FALSE==
equal (assignment), or equal (comparison)This is a non-standard equivalent of «= equal (assignment or comparison)».
<>
not equal (comparison)Return TRUE if the first operand is not equal to the second by arithmetic or collation rules.
Example for strings:
'A' <> 'A '
is TRUE.!=
not equal (comparison)This is a non-standard equivalent of «<> not equal (comparison)».
[
,]
(indexed access operator)Array example:
['a', 'b', 'c'] [2]
(returns'b'
)Map example:
{'a' : 123, 7: 'asd'}['a']
(returns123
)See also: ARRAY index expression and MAP index expression.
IS NULL
andIS NOT NULL
(comparison)For IS NULL: Return TRUE if the first operand is NULL, otherwise return FALSE. Example: column1 IS NULL, result = TRUE if column1 contains NULL.
For IS NOT NULL: Return FALSE if the first operand is NULL, otherwise return TRUE. Example:
column1 IS NOT NULL
, result = FALSE if column1 contains NULL.
LIKE
(comparison)Perform a comparison of two string operands. If the second operand contains
'_'
, the'_'
matches any single character in the first operand. If the second operand contains'%'
, the'%'
matches 0 or more characters in the first operand. If it is necessary to search for either'_'
or'%'
within a string without treating it specially, an optional clause can be added, ESCAPE single-character-operand, for example'abc_' LIKE 'abcX_' ESCAPE 'X'
is TRUE becauseX'
means «following character is not special». Matching is also affected by the string’s collation.
BETWEEN
(comparison)x BETWEEN y AND z
is shorthand forx >= y AND x <= z
.NOT
negation (logic)Return TRUE if operand is FALSE return FALSE if operand is TRUE, else return UNKNOWN.
Example:
NOT (1 > 1)
, result = TRUE.IN
is equal to one of a list of operands (comparison)Return TRUE if first operand equals any of the operands in a parenthesized list.
Example:
1 IN (2,3,4,1,7)
, result = TRUE.AND
and (logic)Return TRUE if both operands are TRUE. Return UNKNOWN if both operands are UNKNOWN. Return UNKNOWN if one operand is TRUE and the other operand is UNKNOWN. Return FALSE if one operand is FALSE and the other operand is (UNKNOWN or TRUE or FALSE).
OR
or (logic)Return TRUE if either operand is TRUE. Return FALSE if both operands are FALSE. Return UNKNOWN if one operand is UNKNOWN and the other operand is (UNKNOWN or FALSE).
||
concatenate (string manipulation)Return the value of the first operand concatenated with the value of the second operand.
Example:
'A' || 'B'
, result ='AB'
.
The precedence of dyadic operators is:
||
* / %
+ -
<< >> & |
< <= > >=
= == != <> IS IS NOT IN LIKE
AND
OR
To ensure a desired precedence, use ()
parentheses.
If one of the operands has data type DOUBLE, Tarantool uses floating-point arithmetic. This means that exact results are not guaranteed and rounding may occur without warning. For example, 4.7777777777777778 = 4.7777777777777777 is TRUE.
The floating-point values inf and -inf are possible.
For example, SELECT 1e318, -1e318;
will return «inf, -inf».
Arithmetic on infinite values may cause NULL results,
for example SELECT 1e318 - 1e318;
is NULL and SELECT 1e318 * 0;
is NULL.
SQL operations never return the floating-point value -nan, although it may exist in data created by Tarantool’s NoSQL. In SQL, -nan is treated as NULL.
В предыдущих версиях Tarantool строка преобразовывалась в числовое значение, если она использовалась с арифметическим оператором и преобразование было возможно. Например, результатом выражения '7' + '7'
было 14
. Для операций сравнения строка '7'
преобразовывалась в значение 7
. Это называется неявным приведением. Оно было применимо для значений типа STRING и всех числовых типов данных. Начиная с версии Tarantool 2.10 неявное приведение в числа больше не поддерживается.
Ограничения (подробнее в Issue#2346 на GitHub):
* Некоторые ключевые слова, например MATCH и REGEXP, зарезервированы, но в текущих или будущих версиях Tarantool их пока не планируется использовать.
* 99999999999999999 << 210
возвращает 0
.
An expression is a chunk of syntax that causes return of a value. Expressions may contain literals, column-names, operators, and parentheses.
Therefore these are examples of expressions:
1
, 1 + 1 << 1
, (1 = 2) OR 4 > 3
, 'x' || 'y' || 'z'
.
Also there are two expressions that involve keywords:
value IS [NOT] NULL
: determine whether value is (not)NULL
.CASE ... WHEN ... THEN ... ELSE ... END
: set a series of conditions.
Usage: [ value ... ]
Examples: [1,2,3,4]
, [1,[2,3],4]
, ['a', "column_1", uuid()]
An expression has data type = ARRAY if it is a sequence of zero or more values
enclosed in square brackets ([
and ]
).
Often the values in the sequence are called «elements».
The element data type may be anything, including ARRAY – that is, ARRAYs may be nested.
Different elements may have different types.
The Lua equivalent type is „array“.
Usage: { key : value }
Literal examples: {'a':1}
, { "column_1" : X'1234' }
Non-literal examples: {"a":"a"}
, {UUID(): (SELECT 1) + 1}
, {1:'a123', 'two':uuid()}
An expression has data type = MAP if it is enclosed in curly brackets
(also called braces) {
and }
and contains a key for identification,
then a colon :
, then a value for what the key identifies.
The key data type must be INTEGER or STRING or UUID.
The value data type may be anything, including MAP – that is, MAPs may be nested.
The Lua equivalent type is „map“ but the syntax is slightly different,
for example the SQL value {'a': 1}
is represented in Lua as {a = 1}
.
Usage: array-value [square bracket] index [square bracket]
Example: ['a', 'b', 'c'] [2]
(this returns „b“)
As in other languages, an element of an array can be referenced with an integer inside square brackets. The returned value is of type ANY.
The SELECT
query below retrieves all score values stored in the second position of the scores
array field:
CREATE TABLE plays (user_id INTEGER PRIMARY KEY, scores ARRAY);
INSERT INTO plays VALUES (1, [23, 17, 55, 48]);
INSERT INTO plays VALUES (2, [12, 8, 20, 33]);
SELECT scores[2] FROM plays;
/* ---
rows:
- [17]
- [8]
... */
Usage: map-value [square bracket] index [square bracket]
Example: {'a' : 123, 7: 'asd'}['a']
(this returns 123). The returned value is of type ANY.
The SELECT
query below retrieves all values stored in the name
attribute of the info
map field:
CREATE TABLE bands (id INTEGER PRIMARY KEY, info MAP);
INSERT INTO bands VALUES (1, {'name': 'The Beatles', 'year': 1960});
INSERT INTO bands VALUES (2, {'name': 'The Doors', 'year': 1965});
SELECT info['name'] FROM bands;
/* ---
rows:
- ['The Beatles']
- ['The Doors']
... */
See also: subquery.
Определить, равны ли два значения или первое больше/меньше второго, помогают специальные правила. Они применяются при поиске, сортировке результатов в порядке возрастания значений в столбце, а также определении уникальности содержимого столбца. Результатом сравнения могут быть три значения типа BOOLEAN: TRUE
, FALSE
или UNKNOWN
. В любом сравнении, где ни один из операндов не является NULL
, операнды считаются различными, если результат сравнения равен FALSE
. Любой набор операндов, где все операнды отличаются друг от друга, считается уникальным.
Сравнение двух числовых значений:
* infinity = infinity вернет TRUE
;
* обычные числовые значения сравниваются по обычным арифметическим правилам.
When comparing any value to NULL:
(for examples in this paragraph assume that column1 in table T contains {NULL, NULL, 1, 2})
* value comparison-operator NULL is UNKNOWN (not TRUE and not FALSE), which affects «WHERE condition» because the condition must be TRUE, and does not affect «CHECK (condition)» because the condition must be either TRUE or UNKNOWN. Therefore SELECT * FROM T WHERE column1 > 0 OR column1 < 0 OR column1 = 0; returns only {1,2}, and the table can have been created with CREATE TABLE T (… column1 INTEGER, CHECK (column1 >= 0));
* for any operations that contain the keyword DISTINCT, NULLs are not distinct. Therefore SELECT DISTINCT column1 FROM T; will return {NULL,1,2}.
* for grouping, NULL values sort together. Therefore SELECT column1, COUNT(*) FROM T GROUP BY column1; will include a row {NULL, 2}.
* for ordering, NULL values sort together and are less than non-NULL values. Therefore SELECT column1 FROM T ORDER BY column1; returns {NULL, NULL, 1,2}.
* for evaluating a UNIQUE constraint or UNIQUE index, any number of NULLs is okay. Therefore CREATE UNIQUE INDEX i ON T (column1); will succeed.
When comparing any value (except an ARRAY or MAP or ANY) to a SCALAR:
* This is always legal, and the result depends on the underlying type of the value.
For example, if COLUMN1 is defined as SCALAR, and a value in the column is „a“, then
COLUMN1 < 5 is a legal comparison and the result is FALSE because numeric is less than STRING.
Сравнение числового значения со значением типа STRING:
* Сравнение разрешено, если значение STRING можно явно привести к числовому.
When comparing a BOOLEAN to a BOOLEAN:
TRUE is greater than FALSE.
When comparing a VARBINARY to a VARBINARY:
* The numeric value of each pair of bytes is compared until the end of the byte sequences or until inequality. If two byte sequences are otherwise equal but one is longer, then the longer one is greater.
When comparing for the sake of eliminating duplicates:
* This is usually signalled by the word DISTINCT, so it applies to SELECT DISTINCT, to set operators such as UNION (where DISTINCT is implied), and to aggregate functions such as AVG(DISTINCT).
* Two operators are «not distinct» if they are equal to each other, or are both NULL
* If two values are equal but not identical, for example 1.0 and 1.00, they are non-distinct and there is no way to specify which one will be eliminated
* Values in primary-key or unique columns are distinct due to definition.
When comparing a STRING to a STRING:
* Ordinarily collation is «binary», that is, comparison is done according to the numeric values of the bytes. This can be cancelled by adding a COLLATE clause at the end of either expression. So 'A' < 'a'
and 'a' < 'Ä'
, but 'A' COLLATE "unicode_ci" = 'a'
and 'a' COLLATE "unicode_ci" = 'Ä'
.
* When comparing a column with a string literal, the column’s defined collation is used.
* Ordinarily trailing spaces matter. So 'a' = 'a '
is not TRUE. This can be cancelled by using the TRIM(TRAILING …) function.
When comparing any value to an ARRAY or MAP or ANY:
* The result is an error.
Ограничения:
* Ожидается, что при работе с VARBINARY не будет применяться LIKE.
Инструкция (statement) состоит из ключевых слов и выражений языка SQL, которые предписывают Tarantool выполнять какие-либо действия с базой данных. Инструкции начинаются с одного из ключевых слов: ALTER, ANALYZE, COMMIT, CREATE, DELETE, DROP, EXPLAIN, INSERT, PRAGMA, RELEASE, REPLACE, ROLLBACK, SAVEPOINT, SELECT, SET, START, TRUNCATE, UPDATE, VALUES или WITH. В конце инструкции ставится точка с запятой ;
, хотя это и не является обязательным.
A client sends a statement to the Tarantool server. The Tarantool server parses the statement and executes it. If there is an error, Tarantool returns an error message.
In alphabetical order, the following statements are legal.
ALTER TABLE table-name [RENAME or ADD CONSTRAINT or DROP CONSTRAINT clauses];
ANALYZE [table-name]; – temporarily disabled in current version
COMMIT;
CREATE [UNIQUE] INDEX [IF NOT EXISTS] index-name
ON table-name (column-name [, column-name …]);
CREATE TABLE [IF NOT EXISTS] table-name
(column-or-constraint-definition
[, column-or-constraint-definition …])
[WITH ENGINE = engine-name];
CREATE TRIGGER [IF NOT EXISTS] trigger-name
BEFORE|AFTER INSERT|UPDATE|DELETE ON table-name
FOR EACH ROW
BEGIN dml-statement [, dml-statement …] END;
CREATE VIEW [IF NOT EXISTS] view-name
[(column-name [, column-name …])]
AS select-statement | values-statement;
DROP INDEX [IF EXISTS] index-name ON table-name;
DROP TABLE [IF EXISTS] table-name;
DROP TRIGGER [IF EXISTS] trigger-name;
DROP VIEW [IF EXISTS] view-name;
EXPLAIN explainable-statement;
INSERT INTO table-name
[(column-name [, column-name …])]
values-statement | select-statement;
PRAGMA pragma-name[(value)];
RELEASE SAVEPOINT savepoint-name;
REPLACE INTO table-name VALUES (expression [, expression …]);
ROLLBACK [TO [SAVEPOINT] savepoint-name];
SAVEPOINT savepoint-name;
SELECT [DISTINCT|ALL] expression [, expression …]
FROM [SEQSCAN] table-name | joined-table-names [AS alias]
[WHERE expression]
[GROUP BY expression [, expression …]]
[HAVING expression]
[ORDER BY expression]
LIMIT expression [OFFSET expression]];
SET SESSION session-name = session-value;
START TRANSACTION;
TRUNCATE TABLE table-name;
UPDATE table-name
SET column-name=expression [,column-name=expression…]
[WHERE expression];
VALUES (expression [, expression …];
WITH [RECURSIVE] common-table-expression;
Data type conversion, also called casting, is necessary for any operation involving two operands X and Y,
when X and Y have different data types.
Or, casting is necessary for assignment operations
(when INSERT or UPDATE is putting a value of type X into a column defined as type Y).
Casting can be «explicit» when a user uses the CAST function, or «implicit» when Tarantool does a conversion automatically.
The general rules are fairly simple:
Assignments and operations involving NULL cause NULL or UNKNOWN results.
For arithmetic, convert to the data type which can contain both operands and the result.
For explicit casts, if a meaningful result is possible, the operation is allowed.
For implicit casts, if a meaningful result is possible and the data types on both sides
are either STRINGs or most numeric types (that is, are STRING or INTEGER or UNSIGNED or DOUBLE or DECIMAL but not NUMBER),
the operation is sometimes allowed.
The specific situations in this chart follow the general rules:
~ В BOOLEAN | В число | В STRING | В VARBINARY | В UUID
--------------- ---------- ---------- --------- ------------ -------
Из BOOLEAN | AAA | --- | A-- | --- | ---
Из числа | --- | SSA | A-- | --- | ---
Из STRING | S-- | S-- | AAA | A-- | S--
Из VARBINARY | --- | --- | A-- | AAA | S--
Из UUID | --- | --- | A-- | A-- | AAA
Where each entry in the chart has 3 characters:
Where A = Always allowed, S = Sometimes allowed, - = Never allowed.
The first character of an entry is for explicit casts,
the second character is for implicit casts for assignment,
the third character is for implicit cast for comparison.
So AAA = Always for explicit, Always for Implicit (assignment), Always for Implicit (comparison).
The S «Sometimes allowed» character applies for these special situations:
From STRING To BOOLEAN is allowed if UPPER(string-value) = 'TRUE'
or 'FALSE'
.
From numeric to INTEGER or UNSIGNED is allowed for cast and assignment only if the result is not out of range,
and the numeric has no post-decimal digits.
From STRING to INTEGER or UNSIGNED or DECIMAL is allowed only if the string has a representation of a numeric,
and the result is not out of range,
and the numeric has no post-decimal digits.
From STRING to DOUBLE or NUMBER is allowed only if the string has a representation of a numeric.
From STRING to UUID is allowed only if the value is
(8 hexadecimal digits) hyphen (4 hexadecimal digits) hyphen (4 hexadecimal digits) hyphen (4 hexadecimal digits) hyphen (12 hexadecimal digits),
such as '8e3b281b-78ad-4410-bfe9-54806a586a90'
.
From VARBINARY to UUID is allowed only if the value is
16 bytes long,
as in X'8e3b281b78ad4410bfe954806a586a90'
.
The chart does not show To|From SCALAR because the conversions depend on the type of the value, not the type of the column definition. Explicit cast to SCALAR is always allowed.
The chart does not show To|From ARRAY or MAP or ANY because almost no conversions are possible. Explicit cast to ANY, or casting any value to its original data type, is legal, but that is all. This is a slight change: before Tarantool v. 2.10.0, it was legal to cast such values as VARBINARY. It is still possible to use arguments with these types in QUOTE functions, which is a way to convert them to STRINGs.
Примечание
Since version 2.4.1, the NUMBER type is processed in the same way as the number type in NoSQL Tarantool.
Начиная с версии Tarantool 2.10.1 недопустимы некоторые преобразования, которые раньше были разрешены:
Явное приведение числового типа к BOOLEAN.
Явное приведение BOOLEAN к числовому типу.
Неявное приведение NUMBER к другим числовым типам при выполнении арифметических или встроенных функций.
Неявное приведение числового типа к STRING.
Неявное приведение STRING к числовому типу.
Examples of casts, illustrating the situations in the chart:
Выполнение CAST(TRUE AS STRING)
допустимо. В строке «Из BOOLEAN», столбце «В STRING» приведенной выше таблицы стоит значение A--
, где буква A
относится к явному приведению и означает «Always Allowed» — всегда разрешено. Таким образом, результатом операции будет 'TRUE'
.
Выполнение UPDATE ... SET varbinary_column = 'A'
завершится ошибкой. В строке «Из STRING», столбце «В VARBINARY» приведенной выше таблицы стоит значение A--
, где второй символ -
относится к неявному приведению при присваивании и` означает «не разрешено». Результатом будет сообщение об ошибке.
Выражение 1.7E-1 > 0
допустимо. В строке «Из числа», столбце «В число» приведенной выше таблицы стоит значение SSA
, где третья буква А относится к неявному приведению при сравнении и означает «Always Allowed» — всегда разрешено. Таким образом, результатом операции будет 'TRUE'
.
Выполнение 11 > '2'
завершится ошибкой. В строке «Из числа», столбце «В STRING» приведенной выше таблицы стоит значение A--
, где третий символ -
относится к неявному приведению при сравнении и` означает «не разрешено». Результатом операции будет сообщение об ошибке. Подробное объяснение приводится ниже.
Выполнение CAST('5' AS INTEGER)
допустимо. В строке «Из STRING», столбце «В число» приведенной выше таблицы стоит значение S--
, где первая буква S
относится к явному приведению и означает «Sometimes allowed» — иногда разрешено. При этом приведение CAST('5.5' AS INTEGER)
завершится ошибкой, поскольку это не целое число. Если число содержит цифры после десятичной точки, а целевой тип приведения — INTEGER или UNSIGNED, присвоение не будет выполнено.
Примеры в этом разделе справедливы только для версий Tarantool до 2.10. Начиная с Tarantool 2.10 неявное приведение строк и числовых значений больше не допускается.
Приведение STRING к INTEGER/DOUBLE/NUMBER/UNSIGNED (любому числовому типу) и наоборот, выполняемое в ходе операции присвоения или сравнения, может требовать особых условий.
1 = '1' /* сравнение значения STRING с числовым значением */
UPDATE ... SET string_column = 1 /* запись в STRING числового значения */
Для операций сравнения всегда выполняется приведение STRING к числовому значению.
Поэтому 1e2 = '100'
вернет TRUE
, как и 11 > '2'
.
Если приведение не удалось, числовое значение считается меньше, чем значение типа STRING.
Так что 1e400 < ''
тоже вернет TRUE
.
Исключение: для оператора BETWEEN приведение производится к типу данных первого и последнего операндов.
Поэтому выражение '66' BETWEEN 5 AND '7'
вернет TRUE
.
Начиная с Tarantool 2.5.1 действует измененный алгоритм присваивания. В связи с этим неявные приведения строк к числам недопустимы. Например, INSERT INTO t (integer_column) VALUES ('5');
выдаст ошибку.
Implicit cast does happen if STRINGS are used in arithmetic.
Therefore '5' / '5' = 1
. If the cast fails, then the result is an error.
Therefore '5' / ''
is an error.
Неявное приведение не производится, если числовые значения используются в конкатенации или в LIKE.
Поэтому выражение 5 || '5'
недопустимо.
In the following examples, implicit cast does not happen for values in SCALAR columns:
DROP TABLE scalars;
CREATE TABLE scalars (scalar_column SCALAR PRIMARY KEY);
INSERT INTO scalars VALUES (11), ('2');
SELECT * FROM scalars WHERE scalar_column > 11; /* 0 rows. So 11 > '2'. */
SELECT * FROM scalars WHERE scalar_column < '2'; /* 1 row. So 11 < '2'. */
SELECT max(scalar_column) FROM scalars; /* 1 row: '2'. So 11 < '2'. */
SELECT sum(scalar_column) FROM scalars; /* 1 row: 13. So cast happened. */
These results are not affected by indexing, or by reversing the operands.
Implicit cast does NOT happen for GREATEST()
or LEAST().
Therefore LEAST('5',6)
is 6.
For function arguments:
If the function description says that a parameter has a specific data type,
and implicit assignment casts are allowed, then arguments which are not passed with that
data type will be converted before the function is applied.
For example, the LENGTH() function expects a
STRING or VARBINARY,
and INTEGER can be converted to STRING, therefore LENGTH(15) will return
the length of '15'
, that is, 2.
But implicit cast sometimes does NOT happen for parameters.
Therefore ABS('5')
will cause an error message after
Issue#4159 is fixed.
However, TRIM(5) will still be legal.
Although it is not a requirement of the SQL standard, implicit cast is supposed to help compatibility
with other DBMSs. However, other DBMSs have different rules about what can be converted
(for example they may allow assignment of 'inf'
but disallow comparison with '1e5'
).
And, of course, it is not possible to be compatible with other DBMSs and at the same
time support SCALAR, which other DBMSs do not have.