Руководство пользователя SQL
В этом руководстве описано, как начать работу с SQL в Tarantool, а также необходимые концепции.
Заголовок | Описание |
|---|---|
Ввод SQL-операторов в консоли | |
Например, какие символы допустимы | |
токены, литералы, идентификаторы, операнды, операторы, выражения, инструкции | |
Приведение типов, явное или неявное |
Пояснения по установке и запуску сервера Tarantool приведены в других главах руководства по Tarantool.
Чтобы начать работу с функциями SQL, используя Tarantool в качестве клиента, выполните следующие запросы:
box.cfg{}box.execute([[VALUES ('hello');]])
В нижней части экрана должно отобразиться следующее:
tarantool> box.execute([[VALUES ('hello');]])---- metadata:- name: COLUMN_1type: stringrows:- ['hello']...
Это SQL-запрос, выполненный в Tarantool.
Теперь можно выполнять любые SQL-запросы через подключение. Например:
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;]])
Результат SQL-запроса будет выведен на экран.
Далее в этой главе конструкция box.execute([[...]]) не
приводится. В примерах будет показан только синтаксис, например
SELECT 'hello';
и следует понимать, что вводить нужно как
box.execute([[SELECT 'hello';]])
SQL-запросы также можно заключать
в одинарные или двойные кавычки вместо [[ ... ]].
Ключевые слова, например CREATE, INSERT или VALUES, могут вводиться как в верхнем, так и в нижнем регистре.
Литералы, например 55 или 'Hello SQL world!', следует вводить без
одинарных кавычек, если они числовые, и в одинарных кавычках, если они
строковые.
Имена объектов, например table1 или column1, обычно следует вводить без двойных кавычек, при этом они подчиняются ряду ограничений. Имена можно заключать в двойные кавычки — в этом случае ограничений меньше.
Почти все ключевые слова являются зарезервированными, что означает невозможность их использования в качестве имен объектов, если они не заключены в двойные кавычки.
Комментарии могут быть заключены между /* и */ (блочные) или между
-- и концом строки (строчные).
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,
при этом круглые скобки необязательны.
В руководстве по SQL для начинающих
рассматривались следующие темы:
Что такое: реляционные базы данных,
таблицы, представления, строки и колонки?
Что такое: транзакции,
журналы предварительной записи, фиксация и откат?
Что такое: аспекты
безопасности?
Как: добавлять, удалять или обновлять строки в
таблицах?
Как: работать внутри транзакций с фиксацией и/или откатом?
Как: выбирать, объединять, фильтровать, группировать и сортировать
строки?
В Tarantool есть «схема». Схема — это контейнер для всех объектов базы данных. В других СУБД схема может называться «базой данных».
Tarantool позволяет создавать внутри схемы четыре типа «объектов базы данных»: таблицы, триггеры, индексы и ограничения. Внутри таблиц есть «колонки».
Почти все SQL-операторы Tarantool начинаются с зарезервированного
«глагола», например INSERT, и могут заканчиваться точкой с запятой.
Пример: INSERT INTO t VALUES (1);
SQL-база данных Tarantool и NoSQL-база данных Tarantool — это одно и то же. Однако некоторые операции возможны только в SQL, а другие — только в NoSQL. Смешивание SQL-операторов с NoSQL-запросами допускается.
Токен — это минимальная единица синтаксиса SQL, которую понимает Tarantool. Далее перечислены типы токенов:
Ключевые слова — официальные слова языка, например 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;
Существует восемь видов литералов: BOOLEAN, INTEGER, DOUBLE, DECIMAL, STRING, VARBINARY, MAP, ARRAY.
Литералы BOOLEAN:
TRUE | FALSE | UNKNOWN
Литерал имеет
тип данных = BOOLEAN, если это ключевое слово
TRUE или FALSE. UNKNOWN — синоним для NULL. Литерал может иметь тип =
BOOLEAN, если это ключевое слово NULL и нет контекста, указывающего на
другой тип данных.
Литералы INTEGER:
[знак плюс | знак минус] цифра [цифра ...]
или, для шестнадцатеричного целочисленного литерала:
[знак плюс |
знак минус] 0X | 0x шестнадцатеричная-цифра [шестнадцатеричная-цифра
...]
Примеры: 5, -5, +5, 55555, 0X55, 0x55
Шестнадцатеричное
0X55 равно десятичному 85. Литерал имеет
тип данных = INTEGER, если он содержит только
цифры и находится в диапазоне от -9223372036854775808 до
+18446744073709551615; целые числа за пределами этого диапазона
недопустимы.
Литералы DOUBLE:
[E|e [знак плюс |
знак минус] цифра ...]
Примеры: 1E5, 1.1E5.
Литерал имеет
тип данных = DOUBLE, если он содержит «E».
Литералы DOUBLE также называются литералами с плавающей точкой или
литералами приближённых чисел. Для представления «Inf» (бесконечности)
следует указать вещественное число за пределами диапазона чисел двойной
точности, например 1E309. Для представления «nan» (не число) следует
использовать выражение, результатом которого не является вещественное
число, например 0/0, с помощью Tarantool/NoSQL. В Tarantool/SQL это
будет отображаться как NULL. В более ранней версии литералы, содержащие
точки, считались литералами типа NUMBER. В
будущей версии «nan» может не отображаться как NULL. До Tarantool
2.10.0 числа с точкой,
такие как .0, считались литералами DOUBLE, а теперь они считаются
литералами DECIMAL.
Литералы DECIMAL:
[знак плюс | знак минус] [цифра [цифра
...]] точка [цифра [цифра ...]]
Примеры: .0, 1.0,
12345678901234567890.123456789012345678
Литерал имеет
тип данных = DECIMAL, если он содержит точку и
не содержит «E». Литералы DECIMAL могут содержать до 38 цифр; если цифр
больше, цифры после точки могут быть округлены. В более ранних версиях
Tarantool литералы, содержащие точки, считались литералами
NUMBER или DECIMAL.
Литералы STRING:
[одинарная кавычка] [символ ...] [одинарная
кавычка]
Примеры: 'ABC', 'AB''C'
Литерал имеет
тип данных = STRING, если он представляет собой
последовательность из нуля или более символов, заключённую в одинарные
кавычки. Последовательность '' (две одинарные кавычки подряд) внутри
кавычек трактуется как ' (одинарная кавычка), то есть 'A''B'
интерпретируется как A'B.
Литералы VARBINARY:
X|x [одинарная кавычка] [пара
шестнадцатеричных цифр ...] [одинарная кавычка]
Пример: X'414243' — будет отображаться как 'ABC'.
Литерал имеет
тип данных = VARBINARY («двоичные данные
переменной длины»), если он состоит из буквы X, за которой следуют
кавычки с парами шестнадцатеричных цифр, представляющими значения
байтов.
Литералы MAP:
[левая фигурная скобка] ключ [двоеточие] значение
[правая фигурная скобка]
Примеры: {'a':1}, {1:'a'}
Литерал
MAP — это пара фигурных скобок, внутри которых находится литерал
STRING, INTEGER или UUID (называемый «ключом» карты), за которым следует
двоеточие, за которым следует литерал любого типа (называемый
«значением» карты). Это минимальная форма
выражения MAP.
Литералы ARRAY:
[левая квадратная скобка] [литерал] [правая
квадратная скобка]
Примеры: [1], ['a']
Литерал ARRAY — это
значение литерала, заключённое в квадратные скобки. Это минимальная
форма выражения ARRAY.
Далее приведены четыре способа включения не-ASCII символов, таких как
греческая буква α (альфа), в строковые литералы:
Сначала убедитесь,
что ваша оболочка настроена на приём символов в кодировке UTF-8. Простой
способ проверки:
SELECT hex(cast('α' as VARBINARY)); Если результат
— CEB1 (шестнадцатеричное значение UTF-8-представления символа α), всё
настроено правильно.
-
(1) Просто заключите символ в
'...',
'α' -
(2) Узнайте шестнадцатеричный код UTF-8-представления символа α, и заключите его в
X'...', затем приведите к STRING, так как литералыX'...'имеют тип данных VARBINARY, а не STRING:
CAST(X'CEB1' AS STRING) -
(3) Узнайте кодовую точку Юникода для символа α и передайте её в функцию CHAR.
CHAR(945) /* помните, что это α с типом данных STRING, а не VARBINARY */ -
(4) Заключите операторы в двойные кавычки и используйте Lua-экранирование, например
box.execute("SELECT '\206\177';")Для объединения символов, созданных любым из этих способов, можно использовать оператор конкатенации||.
Ограничения:
(Issue#2344)
*
LENGTH('A''B') = 3 — это правильно, но в консоли Tarantool результат
выполнения SELECT A''B; отображается как A''B, что вводит в
заблуждение.
- К сожалению,
X'41'— это последовательность байтов, которая выглядит так же, как'A', но не является тем же самым. Выражениеbox.execute("select 'A' < X'41';")в данный момент недопустимо. Это происходит потому, чтоTYPEOF(X'41')возвращает'varbinary'. Также недопустимоUPDATE ... SET string_column = X'41'— следует использоватьUPDATE ... SET string_column = CAST(X'41' AS STRING);.
Все объекты базы данных — таблицы, триггеры, индексы, колонки,
ограничения, функции, правила сортировки — имеют идентификаторы.
Идентификатор должен начинаться с буквы или символа подчёркивания
('_') и должен содержать только буквы, цифры, знаки доллара ('$')
или символы подчёркивания. Максимальное количество байтов в
идентификаторе — от 64982 до 65000. Из соображений совместимости
Tarantool рекомендует, чтобы идентификатор содержал не более 30
символов.
Буквы в идентификаторах не обязательно должны принадлежать латинскому алфавиту — например, японский слог ひ и кириллическая буква д допустимы. Однако следует учитывать, что латинская буква занимает один байт, а кириллическая — два, поэтому кириллические идентификаторы занимают немного больше места.
Некоторые слова зарезервированы и не должны использоваться в качестве идентификаторов. Простое правило: если слово имеет значение в синтаксисе SQL Tarantool, не используйте его в качестве идентификатора. Текущий список зарезервированных слов:
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
Идентификаторы могут заключаться в двойные кавычки. Такие идентификаторы
называются идентификаторами в кавычках или «ограниченными
идентификаторами» (идентификаторы без кавычек могут называться
«регулярными идентификаторами»). Сами двойные кавычки не являются частью
идентификатора. Ограниченный идентификатор может быть зарезервированным
словом и может содержать любой печатный символ. Tarantool преобразует
буквы в регулярных идентификаторах в верхний регистр перед обращением к
базе данных, поэтому для таких инструкций, как
CREATE TABLE a (a INTEGER PRIMARY KEY); или SELECT a FROM a; именем
таблицы будет A, а именем колонки — A. Однако Tarantool не преобразует
ограниченные идентификаторы в верхний регистр, поэтому для таких
инструкций, как CREATE TABLE "a" ("a" INTEGER PRIMARY KEY); или
SELECT "a" FROM "a"; именем таблицы будет a, а именем колонки — a.
Последовательность "" внутри двойных кавычек обрабатывается как ",
то есть "A""B" интерпретируется как "A"B".
Примеры: things, t45, journal_entries_for_2017, ддд, "into"
Внутри некоторых инструкций к идентификаторам можно добавлять
квалификаторы для исключения двусмысленности. Квалификатор — это
идентификатор объекта более высокого уровня, за которым следует точка.
Например, к колонке column1 в таблице table1 можно обратиться как
table1.column1. Идентификатор, в том числе с добавленным
квалификатором, — своего рода имя объекта. Например, в
SELECT table1.column1, table2.column1 FROM table1, table2;
соответствующие квалификаторы дают понять, что первый используемый
колонка — это column1 из table1, а второй — column1 из
table2.
В целях совместимости правила иногда смягчаются — например, некоторые небуквенные символы, такие как $ и «, допустимы в регулярных идентификаторах. Однако лучше исходить из того, что правила не смягчаются никогда.
Ниже приведены примеры допустимых и недопустимых идентификаторов.
_A1 -- legal, begins with underscore and contains underscore | letter | digit1_A -- illegal, begins with digitA$« -- legal, but not recommended, try to stick with digits and letters and underscores+ -- illegal, operator tokengrant -- 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 identifiersA123456789012345678901234567890 -- legal, identifiers can be longддд -- legal, and will be converted to upper case in identifiers
Следующий пример показывает, что преобразование к верхнему регистру применяется к регулярным идентификаторам, но не к ограниченным.
CREATE TABLE "q" ("q" INTEGER PRIMARY KEY);SELECT * FROM q;-- Result = "error: 'no such table: Q'.
Операнд — это объект, над которым выполняется операция. Литералы и идентификаторы колонок являются операндами. NULL и DEFAULT также являются операндами.
NULL и DEFAULT — ключевые слова, представляющие значения, тип данных которых неизвестен до момента присваивания или сравнения, поэтому они известны под техническим термином «контекстно-типизированные спецификации значений» (contextually typed value specifications). (Исключение: для нестандартной инструкции "SELECT NULL FROM table-name;" NULL имеет тип данных BOOLEAN.)
Каждый операнд имеет тип данных.
Для литералов, как показано ранее, тип данных обычно определяется форматом.
Для идентификаторов тип данных обычно определяется определением.
Обычное определение может измениться из-за контекста или из-за явного приведения типов.
У некоторых имён типов данных SQL есть псевдонимы. Псевдоним может
использоваться при определении данных. Например, VARCHAR(5) и TEXT —
псевдонимы STRING, и они могут встречаться в
CREATE TABLE {table_name} ({column_name} VARCHAR(5) PRIMARY KEY);, но Tarantool при запросе сообщит, что тип данных
{column_name} — STRING.
Для каждого типа данных SQL существует соответствующий тип NoSQL, например SQL STRING хранится в NoSQL-спейсе как type .
Во избежание путаницы в этом руководстве все ссылки на имена типов данных SQL указаны в верхнем регистре, а все похожие слова, относящиеся к типам NoSQL или другим видам объектов, — в нижнем регистре, например:
- STRING — это имя типа данных, а string — общий термин;
- NUMBER — это имя типа данных, а numeric — общий термин.
Хотя принято называть значение VARBINARY «бинарной строкой», в этом руководстве этот термин не используется; вместо него используется «последовательность байтов».
Ниже приведены все типы данных SQL, соответствующие им типы NoSQL, их псевдонимы, а также примеры минимальных и максимальных литералов.
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 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 (нет)
INTERVAL interval (none)
SCALAR (varies) (none) FALSE максимальное значение UUID
MAP map (none) {} {big-key:big-value}
ARRAY array (none) [] [many values]
ANY any (none) FALSE [many values]
Значения BOOLEAN — это FALSE, TRUE и UNKNOWN (эквивалентно NULL). FALSE меньше 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 могут содержать до 38 цифр по обе стороны от десятичной
точки, а любые арифметические операции со значениями DECIMAL дают точные
результаты (арифметические операции со значениями DOUBLE могут давать
приближенные, а не точные результаты). До Tarantool
2.10.0 для DECIMAL не
существовало формата литералов, поэтому для указания, что числовое
значение имеет тип DECIMAL, было необходимо использовать
CAST, например CAST(1.1 AS DECIMAL) или
CAST('99999999999999999999999999999999999999' AS DECIMAL). См. также
описание типа 'decimal' в NoSQL. Поддержка DECIMAL в SQL
была добавлена в версии Tarantool 2.10.1.
Значения STRING — это любая последовательность из нуля или более
символов в кодировке UTF-8, либо NULL. Возможные значения символов
соответствуют стандарту Unicode. Последовательности байтов, не
являющиеся допустимыми символами UTF-8, разрешены, но не рекомендуются.
Строковые литералы заключаются в одинарные кавычки, например
'literal'. При использовании псевдонима VARCHAR для определения
колонки необходимо указать максимальную длину, например column_1
VARCHAR(40). Однако максимальная длина игнорируется. После типа данных
может следовать [COLLATE collation-name].
Значения VARBINARY — это любая последовательность из нуля или более
октетов (байтов), либо NULL. Литералы VARBINARY записываются в виде X,
за которым следуют пары шестнадцатеричных цифр, заключенные в одинарные
кавычки, например X'0044'. Эквивалентом VARBINARY в NoSQL является
'varbinary', а не символьная строка — для хранения в MessagePack
используется MP_BIN (бинарный формат MsgPack).
Значения 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(), либо с
помощью функции CAST(). Поддержка
UUID в SQL была добавлена в версии Tarantool 2.9.1.
DATETIME. Добавлен в 2.10.0. Поле таблицы типа datetime можно создать с
помощью этого типа, который семантически эквивалентен стандартному типу
TIMESTAMP WITH TIME ZONE.
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: Dtype: datetimerows:- ['2022-01-01T00:00:00Z']...
Неявное приведение строкового выражения к выражению типа datetime недоступно (в отличие от подхода, используемого большинством поставщиков SQL). В таких случаях необходимо использовать явное приведение строкового значения к значению datetime (см. пример выше).
Можно вычитать datetime из datetime, interval из datetime или складывать datetime и interval в любом порядке (примеры таких арифметических операций приведены в описании типа INTERVAL).
Встроенные функции, связанные с типом DATETIME: DATE_PART() и NOW()
INTERVAL. Добавлен в 2.10.0. Аналогично типу
DATETIME, можно определить колонку типа
INTERVAL.
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: Dtype: datetime- name: Itype: intervalrows:- ['2022-02-02T01:01:00Z', '+1 years, 1 months']...
В отличие от DATETIME, INTERVAL не может быть частью индекса.
Неявное приведение строки или любого другого типа к интервалу недоступно. Однако допускается явное приведение от map (см. примеры ниже).
Интервалы можно использовать в арифметических операциях, таких как +
или -, только с выражением datetime или другим интервалом:
tarantool> select * from t---- metadata:- name: Dtype: datetime- name: Itype: intervalrows:- ['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: Dtype: datetime- name: COLUMN_1type: datetime- name: COLUMN_2type: datetimerows:- ['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_1type: intervalrows:- ['+2 years, 3 months']...
Для преобразования map в выражение INTERVAL предусмотрен следующий список известных атрибутов:
yearmonthweekdayhourminutesecondnsec
tarantool> select cast({'year': 1, 'month': 1, 'week': 1, 'day': 1, 'hour': 1, 'min': 1, 'sec': 1} as interval)---- metadata:- name: COLUMN_1type: intervalrows:- ['+1 years, 1 months, 1 weeks, 1 days, 1 hours, 1 minutes, 1 seconds']...tarantool> \set language luatarantool> 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_1type: intervalrows:- ['+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 — это комбинации ключ:значение, которые можно получить с
помощью выражений MAP. MAP нельзя использовать в
арифметических операциях или сравнениях (кроме IS [NOT] NULL), а из
функций с ними допустимо использовать только CAST,
QUOTE, TYPEOF и функции,
связанные с проверкой на NULL.
Значения ARRAY — это списки, которые можно получить с помощью
выражений ARRAY. ARRAY нельзя использовать в
арифметических операциях или сравнениях (кроме IS [NOT] NULL), а из
функций с ними допустимо использовать только CAST,
QUOTE, TYPEOF и функции,
связанные с проверкой на NULL.
ANY можно использовать в определениях колонок, при этом отдельные значения колонки имеют тип ANY. Различие между SCALAR и ANY заключается в следующем:
- Колонки SCALAR не могут содержать значения MAP или ARRAY, а колонки ANY — могут.
- Значения SCALAR сравнимы, а значения ANY — нет.
Любое значение любого типа данных может быть NULL. Обычно NULL приводится к типу данных операнда, с которым сравнивается, или к типу данных колонки, в котором оно находится. Если тип данных NULL невозможно определить из контекста, считается, что он имеет тип BOOLEAN.
Большинство типов данных SQL соответствуют
типам Tarantool/NoSQL с тем же именем.
В версиях Tarantool до 2.10.0 существовали также типы данных
Tarantool/NoSQL, не имевшие соответствующих типов в SQL. В этих версиях,
если Tarantool/SQL считывал значение Tarantool/NoSQL типа, не имеющего
SQL-аналога, Tarantool/SQL мог трактовать его как NULL, INTEGER или
VARBINARY. Например, SELECT "flags" FROM "_vspace"; возвращал бы
колонка типа 'map'. Такие колонки в SQL можно обрабатывать только
вызывая Lua-функции.
Оператор указывает, какая операция может быть выполнена над операндами.
Почти все операторы легко распознать, так как они состоят из одно- или двухсимвольных небуквенных лексем, за исключением шести ключевых слов-операторов (AND IN IS LIKE NOT OR).
Почти все операторы — «диадические», то есть они применяются к паре операндов. Единственные операторы, применяемые к одному операнду, — это NOT, ~ и (иногда) -.
Результатом операции является новый операнд. Если оператор — оператор сравнения, то результат имеет тип данных BOOLEAN (TRUE, FALSE или UNKNOWN). В остальных случаях результат имеет тот же тип данных, что и исходные операнды, за исключением того, что может происходить повышение до более широкого типа во избежание переполнения. Арифметические операции с операндами NULL дают в результате NULL.
В списке операторов ниже пометка "(арифметическая операция)" указывает на то, что все операнды должны быть числовыми значениями (кроме NUMBER) и в результате тоже должно получиться число. Пометка "(сравнение)" указывает, что операнды должны иметь схожие типы данных и результат будет типа BOOLEAN. Пометка "(логическая операция)" указывает, что операнды должны быть типа BOOLEAN и результат также будет типа BOOLEAN. Если операция невозможна, выбрасывается исключение. Кроме того, существуют особые ситуации: их описание приводится после списка операторов. На месте указанных в примерах конкретных значений (литералов) могут с тем же успехом стоять идентификаторы колонок.
Начиная с версии Tarantool 2.10.1 арифметические операнды не могут быть типа NUMBER.
-
+сложение (арифметическая операция)Складывает два числа согласно стандартным арифметическим правилам. Пример:
1 + 5, результат = 6. -
-вычитание (арифметическая операция)Вычитает второе число из первого согласно стандартным арифметическим правилам.
Пример:
1 - 5, результат = -4. -
*умножение (арифметическая операция)Умножает два числа согласно стандартным арифметическим правилам.
Пример:
2 * 5, результат = 10. -
/деление (арифметическая операция)Делит первое число на второе согласно стандартным арифметическим правилам. Деление на ноль недопустимо. Результат деления целых чисел всегда округляется в сторону нуля; используйте CAST к DOUBLE или DECIMAL, чтобы получить нецелочисленный результат.
Пример:
5 / 2, результат = 2. -
%остаток от деления (арифметическая операция)Делит первое число на второе согласно стандартным арифметическим правилам. Результатом является остаток. Начиная с версии Tarantool 2.10.1 операнды должны быть типа INTEGER или UNSIGNED.
Примеры:
17 % 5, результат = 2;-123 % 4, результат = -3. -
<<сдвиг влево (арифметическая операция)Сдвигает первое число влево N раз, где N — второе число. Для положительных чисел каждый сдвиг на 1 бит влево эквивалентен умножению на 2.
Пример:
5 << 1, результат = 10. -
>>сдвиг вправо (арифметическая операция)Сдвигает первое число вправо N раз, где N — второе число. Для положительных чисел каждый сдвиг на 1 бит вправо эквивалентен делению на 2.
Пример:
5 >> 1, результат = 2. -
&побитовое И (арифметическая операция)Комбинирует два числа, при этом в результате бит равен 1 тогда и только тогда, когда оба исходных числа имеют бит 1.
Пример:
5 & 4, результат = 4. -
|побитовое ИЛИ (арифметическая операция)Комбинирует два числа, при этом в результате бит равен 1, если хотя бы одно из исходных чисел имеет бит 1.
Пример:
5 | 2, результат = 7. -
~инверсия (арифметическая операция), иногда называемая побитовым отрицаниемМеняет биты 0 на 1, а биты 1 на 0.
Пример:
~5, результат = -6. -
<меньше (сравнение)Возвращает TRUE, если первый операнд меньше второго по арифметическим правилам или правилам сортировки.
Пример для чисел:
5 < 2, результат = FALSEПример для строк:
'C' < ' ', результат = FALSE -
<=меньше или равно (сравнение)Возвращает TRUE, если первый операнд меньше или равен второму по арифметическим правилам или правилам сортировки.
Пример для чисел:
5 <= 5, результат = TRUEПример для строк:
'C' <= 'B', результат = FALSE -
>больше (сравнение)Возвращает TRUE, если первый операнд больше второго по арифметическим правилам или правилам сортировки.
Пример для чисел:
5 > -5, результат = TRUEПример для строк:
'C' > '!', результат = TRUE -
>=больше или равно (сравнение)Возвращает TRUE, если первый операнд больше или равен второму по арифметическим правилам или правилам сортировки.
Пример для чисел:
0 >= 0, результат = TRUE Пример для строк:'Z' >= 'Γ', результат = FALSE -
=равно (присваивание или сравнение)После слова SET "=" означает, что первый операнд получает значение второго операнда. В остальных контекстах "=" возвращает TRUE, если операнды равны.
Пример присваивания:
... SET column1 = 'a';Пример для чисел:
0 = 0, результат = TRUEПример для строк:
'1' = '2 ', результат = FALSE -
==равно (присваивание) или равно (сравнение)Нестандартный эквивалент "= равно (присваивание или сравнение)".
-
<>не равно (сравнение)Возвращает TRUE, если первый операнд не равен второму по арифметическим правилам или правилам сортировки.
Пример для строк:
'A' <> 'A '— TRUE. -
!=не равно (сравнение)Нестандартный эквивалент ["](/не равно (сравнение)" ).
-
[,](оператор индексированного доступа)Пример с массивом:
['a', 'b', 'c'] [2](возвращает'b')Пример с map:
{'a' : 123, 7: 'asd'}['a'](возвращает123)См. также: выражение индекса ARRAY и выражение индекса MAP.
-
IS NULLиIS NOT NULL(сравнение)Для IS NULL: возвращает TRUE, если первый операнд равен NULL, иначе FALSE. Пример: column1 IS NULL, результат = TRUE, если column1 содержит NULL.
Для IS NOT NULL: возвращает FALSE, если первый операнд равен NULL, иначе TRUE. Пример:
column1 IS NOT NULL, результат = FALSE, если column1 содержит NULL. -
LIKE(сравнение)Выполняет сравнение двух строковых операндов. Если второй операнд содержит
'_', то'_'совпадает с любым одиночным символом в первом операнде. Если второй операнд содержит'%', то'%'совпадает с нулем или более символами в первом операнде. Если необходимо найти'_'или'%'внутри строки без их специальной обработки, можно добавить необязательную конструкцию ESCAPE single-character-operand, например'abc_' LIKE 'abcX_' ESCAPE 'X'возвращает TRUE, так какX'означает, что следующий символ не является специальным. На сопоставление также влияет сортировка строки. -
BETWEEN(сравнение){x} BETWEEN {y} AND {z}— сокращенная запись для{x} >= {y} AND {x} <= {z}. -
NOTотрицание (логическая операция)Возвращает TRUE, если операнд равен FALSE; возвращает FALSE, если операнд равен TRUE, иначе возвращает UNKNOWN.
Пример:
NOT (1 > 1), результат = TRUE. -
IN— равно одному из операндов в списке (сравнение)Возвращает TRUE, если первый операнд равен любому из операндов в списке в скобках.
Пример:
1 IN (2,3,4,1,7), результат = TRUE. -
ANDлогическое И (логическая операция)Возвращает TRUE, если оба операнда равны TRUE. Возвращает UNKNOWN, если оба операнда равны UNKNOWN. Возвращает UNKNOWN, если один операнд равен TRUE, а другой — UNKNOWN. Возвращает FALSE, если один операнд равен FALSE, а другой — (UNKNOWN, TRUE или FALSE).
-
ORлогическое ИЛИ (логическая операция)Возвращает TRUE, если хотя бы один операнд равен TRUE. Возвращает FALSE, если оба операнда равны FALSE. Возвращает UNKNOWN, если один операнд равен UNKNOWN, а другой — (UNKNOWN или FALSE).
-
||конкатенация (строковая операция)Возвращает значение первого операнда, объединённое со значением второго операнда.
Пример:
'A' || 'B', результат ='AB'.
Приоритет диадических операторов:
||* / %+ -<< >> & |< <= > >== == != <> IS IS NOT IN LIKEANDOR
Чтобы задать нужный приоритет, используйте круглые скобки ().
Если один из операндов имеет тип данных DOUBLE, Tarantool использует арифметику с плавающей запятой. Это означает, что точные результаты не гарантируются и округление может происходить без предупреждения. Например, 4.7777777777777778 = 4.7777777777777777 — TRUE.
Значения с плавающей запятой inf и -inf возможны. Например,
SELECT 1e318, -1e318; вернёт "inf, -inf". Арифметические операции с
бесконечными значениями могут приводить к результату NULL, например
SELECT 1e318 - 1e318; возвращает NULL, а SELECT 1e318 * 0; — NULL.
SQL-операции никогда не возвращают значение с плавающей запятой -nan, хотя оно может присутствовать в данных, созданных средствами NoSQL Tarantool. В SQL -nan трактуется как NULL.
В предыдущих версиях Tarantool строка преобразовывалась в числовое
значение, если она использовалась с арифметическим оператором и
преобразование было возможно. Например, результатом выражения
'7' + '7' было 14. Для операций сравнения строка '7'
преобразовывалась в значение 7. Это называется неявным приведением.
Оно было применимо для значений типа STRING и всех числовых типов
данных. Начиная с версии Tarantool 2.10 неявное приведение в числа
больше не поддерживается.
Ограничения (подробнее в Issue#2346 на
GitHub):
*
Некоторые ключевые слова, например MATCH и REGEXP, зарезервированы, но в
текущих или будущих версиях Tarantool их пока не планируется
использовать.
99999999999999999 << 210возвращает0.
Выражение — это фрагмент синтаксиса, возвращающий значение. Выражения могут содержать литералы, имена колонок, операторы и круглые скобки.
Таким образом, примерами выражений являются: 1, 1 + 1 << 1,
(1 = 2) OR 4 > 3, 'x' || 'y' || 'z'.
Также существуют два выражения с ключевыми словами:
value IS [NOT] NULL: проверка, равно ли значениеNULL(или не равно).CASE ... WHEN ... THEN ... ELSE ... END: задание набора условий.
Использование: [ value ... ]
Примеры: [1,2,3,4], [1,[2,3],4], ['a', "column_1", uuid()]
Выражение имеет тип данных ARRAY, если оно представляет собой
последовательность из нуля или более значений, заключенных в квадратные
скобки ([ и ]). Значения в последовательности часто называются
«элементами». Тип данных элемента может быть любым, включая ARRAY — то
есть массивы ARRAY могут быть вложенными. Разные элементы могут иметь
разные типы. Эквивалентный тип в Lua —
'array'.
Использование: { key : value }
Примеры литералов: {'a':1}, { "column_1" : X'1234' }
Примеры не-литералов: {"a":"a"}, {UUID(): (SELECT 1) + 1},
{1:'a123', 'two':uuid()}
Выражение имеет тип данных MAP, если оно заключено в фигурные скобки {
и } и содержит ключ для идентификации, затем двоеточие :, а затем
значение, которое идентифицируется ключом. Тип данных ключа должен быть
INTEGER, STRING или UUID. Тип данных значения может быть любым, включая
MAP — то есть MAP могут быть вложенными. Эквивалентный тип в Lua —
'map', но синтаксис немного отличается: например, значение SQL
{'a': 1} в Lua представляется как {a = 1}.
Использование: array-value [square bracket] index [square bracket]
Пример: ['a', 'b', 'c'] [2] (возвращает 'b')
Как и в других языках, к элементу массива можно обратиться с помощью целого числа в квадратных скобках. Возвращаемое значение имеет тип ANY.
Приведенный ниже запрос SELECT извлекает все значения оценок,
хранящиеся во второй позиции поля массива scores:
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]... */
Использование: map-value [square bracket] index [square bracket]
Пример: {'a' : 123, 7: 'asd'}['a'] (возвращает 123). Возвращаемое
значение имеет тип ANY.
Приведенный ниже запрос SELECT извлекает все значения, хранящиеся в
атрибуте name поля info типа map:
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']... */
См. также: подзапрос.
Определить, равны ли два значения или первое больше/меньше второго,
помогают специальные правила. Они применяются при поиске, сортировке
результатов в порядке возрастания значений в колонке, а также
определении уникальности содержимого колонки. Результатом сравнения
могут быть три значения типа BOOLEAN: TRUE, FALSE или UNKNOWN. В
любом сравнении, где ни один из операндов не является NULL, операнды
считаются различными, если результат сравнения равен FALSE. Любой
набор операндов, где все операнды отличаются друг от друга, считается
уникальным.
Сравнение двух числовых значений:
- infinity = infinity вернет
TRUE; - -обычные числовые значения сравниваются по обычным арифметическим правилам.
При сравнении любого значения с NULL:
(в примерах этого раздела
предполагается, что колонка column1 в таблице T содержит {NULL, NULL, 1,
2})
- результат операции сравнения значения с NULL равен UNKNOWN (не TRUE и не FALSE). Это влияет на условие «WHERE condition», так как условие должно быть TRUE, но не влияет на «CHECK (condition)», так как условие должно быть либо TRUE, либо UNKNOWN. Поэтому SELECT * FROM T WHERE column1 > 0 OR column1 < 0 OR column1 = 0; вернет только {1,2}, а таблица может быть создана с помощью CREATE TABLE T (... column1 INTEGER, CHECK (column1 >= 0));
- для любых операций, содержащих ключевое слово DISTINCT, значения NULL не считаются различными. Поэтому SELECT DISTINCT column1 FROM T; вернет {NULL,1,2}.
- при группировке значения NULL объединяются. Поэтому SELECT column1, COUNT(*) FROM T GROUP BY column1; включит строку {NULL, 2}.
- при упорядочении значения NULL группируются вместе и считаются меньшими, чем значения, не равные NULL. Поэтому SELECT column1 FROM T ORDER BY column1; вернет {NULL, NULL, 1,2}.
- при проверке ограничения UNIQUE или уникального индекса любое количество значений NULL допустимо. Поэтому CREATE UNIQUE INDEX i ON T (column1); будет выполнена успешно.
При сравнении любого значения (кроме ARRAY, MAP или ANY) со значением типа SCALAR:
- Сравнение всегда допустимо, а результат зависит от базового типа значения. Например, если COLUMN1 определен как SCALAR, а значение в колонке равно 'a', то COLUMN1 < 5 — допустимое сравнение, и его результат равен FALSE, так как числовое значение меньше значения типа STRING.
Сравнение числового значения со значением типа STRING:
- Сравнение разрешено, если значение STRING можно явно привести к числовому.
При сравнении значения типа BOOLEAN со значением типа BOOLEAN:
TRUE
больше, чем FALSE.
При сравнении значения типа VARBINARY со значением типа VARBINARY:
- Сравнивается числовое значение каждой пары байтов до конца последовательности байтов или до обнаружения неравенства. Если две последовательности байтов равны, но одна из них длиннее, то более длинная последовательность считается большей.
При сравнении в целях устранения дубликатов:
- Обычно это обозначается ключевым словом DISTINCT, поэтому применяется к SELECT DISTINCT, к операторам над множествами, таким как UNION (где DISTINCT подразумевается), и к агрегатным функциям, таким как AVG(DISTINCT).
- Два операнда считаются «не различными», если они равны друг другу или оба равны NULL.
- Если два значения равны, но не идентичны, например 1.0 и 1.00, они считаются не различными, и невозможно определить, какое из них будет исключено.
- Значения в колонках первичного ключа или уникальных колонках различны по определению.
При сравнении значения типа STRING со значением типа STRING:
- По
умолчанию используется «бинарное» правило сортировки (collation), то
есть сравнение выполняется по числовым значениям байтов. Это можно
изменить, добавив предложение COLLATE в конце
любого из выражений. Так,
'A' < 'a'и'a' < 'Ä', но'A' COLLATE "unicode_ci" = 'a'и'a' COLLATE "unicode_ci" = 'Ä'. - При сравнении колонки со строковым литералом используется правило сортировки, определенное для колонки.
- По умолчанию завершающие
пробелы учитываются. Так,
'a' = 'a 'не равно TRUE. Это можно изменить с помощью функции TRIM(TRAILING ...). При сравнении любого значения со значением типа ARRAY, MAP или ANY: - Результатом будет ошибка.
Ограничения:
- Ожидается, что при работе с 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. В конце инструкции ставится точка с запятой ;, хотя это и не
является обязательным.
Клиент отправляет инструкцию на сервер Tarantool. Сервер Tarantool анализирует инструкцию и выполняет её. При возникновении ошибки Tarantool возвращает сообщение об ошибке.
Ниже перечислены допустимые операторы в алфавитном порядке.
NBSP
ALTER TABLE table-name [RENAME or ADD CONSTRAINT or DROP CONSTRAINT clauses];
NBSP ANALYZE [table-name]; – временно отключено в текущей версии
NBSP COMMIT;
NBSP
CREATE [UNIQUE] INDEX [IF NOT EXISTS] index-name
NBSP NBSP NBSP NBSP
ON table-name (column-name [, column-name ...]);
NBSP CREATE TABLE [IF NOT EXISTS] table-name
NBSP NBSP NBSP NBSP (column-or-constraint-definition
NBSP NBSP NBSP NBSP
[, column-or-constraint-definition ...])
NBSP
NBSP NBSP NBSP [WITH ENGINE = engine-name];
NBSP CREATE TRIGGER [IF NOT EXISTS] trigger-name
NBSP NBSP NBSP NBSP
BEFORE|AFTER INSERT|UPDATE|DELETE ON table-name
NBSP NBSP NBSP NBSP FOR EACH ROW
NBSP NBSP
NBSP NBSP
BEGIN dml-statement [, dml-statement ...] END;
NBSP CREATE VIEW [IF NOT EXISTS] view-name
NBSP NBSP NBSP NBSP
[(column-name [, column-name ...])]
NBSP NBSP
NBSP NBSP AS select-statement | values-statement;
NBSP
DROP INDEX [IF EXISTS] index-name ON table-name;
NBSP DROP TABLE [IF EXISTS] table-name;
NBSP
DROP TRIGGER [IF EXISTS] trigger-name;
NBSP
DROP VIEW [IF EXISTS] view-name;
NBSP
EXPLAIN explainable-statement;
NBSP
INSERT INTO table-name
NBSP NBSP NBSP NBSP
[(column-name [, column-name ...])]
NBSP NBSP NBSP
NBSP values-statement | select-statement;
NBSP
PRAGMA pragma-name[(value)];
NBSP
RELEASE SAVEPOINT savepoint-name;
NBSP
REPLACE INTO table-name VALUES (expression [, expression ...]);
NBSP ROLLBACK [TO [SAVEPOINT] savepoint-name];
NBSP SAVEPOINT savepoint-name;
NBSP
SELECT [DISTINCT|ALL] expression [, expression ...]
NBSP NBSP NBSP NBSP
FROM [SEQSCAN] table-name | joined-table-names [AS alias]
NBSP NBSP NBSP NBSP [WHERE expression]
NBSP NBSP
NBSP NBSP [GROUP BY expression [, expression ...]]
NBSP NBSP NBSP NBSP [HAVING expression]
NBSP NBSP
NBSP NBSP [ORDER BY expression]
NBSP NBSP NBSP NBSP
[LIMIT expression [OFFSET expression]];](sql_limit)
NBSP
SET SESSION session-name = session-value;
NBSP
START TRANSACTION;
NBSP
TRUNCATE TABLE table-name;
NBSP
UPDATE table-name
NBSP NBSP NBSP NBSP
SET column-name=expression [,column-name=expression...]
NBSP NBSP NBSP NBSP [WHERE expression];
NBSP
VALUES (expression [, expression ...];
NBSP
WITH [RECURSIVE] common-table-expression;
Преобразование типов данных, также называемое приведением типов,
необходимо для любой операции с двумя операндами X и Y, если X и Y имеют
разные типы данных.
Также приведение типов необходимо для операций
присваивания (когда INSERT или UPDATE помещает значение типа X в
колонка, определенный как тип Y).
Приведение может быть «явным»,
когда пользователь использует функцию CAST, или
«неявным», когда Tarantool выполняет преобразование автоматически.
Общие правила достаточно просты:
Присваивания и операции с NULL
приводят к результатам NULL или UNKNOWN.
Для арифметических операций
выполняется преобразование к типу данных, который может содержать оба
операнда и результат.
Для явного приведения операция разрешена, если
возможен осмысленный результат.
Для неявного приведения операция
иногда разрешена, если возможен осмысленный результат и типы данных с
обеих сторон являются либо строками (STRING), либо большинством числовых
типов (то есть STRING, INTEGER, UNSIGNED, DOUBLE или DECIMAL, но не
NUMBER).
Конкретные ситуации в этой таблице соответствуют общим правилам:
~ В BOOLEAN | В число | В STRING | В VARBINARY | В UUID--------------- ---------- ---------- --------- ------------ -------Из BOOLEAN | AAA | --- | A-- | --- | ---Из числа | --- | SSA | A-- | --- | ---Из STRING | S-- | S-- | AAA | A-- | S--Из VARBINARY | --- | --- | A-- | AAA | S--Из UUID | --- | --- | A-- | A-- | AAA
Каждая ячейка в таблице содержит 3 символа:
Где A = всегда разрешено
(Always allowed), S = иногда разрешено (Sometimes allowed), - = никогда
не разрешено (Never allowed).
Первый символ ячейки относится к явному
приведению,
второй — к неявному приведению при присваивании,
третий — к неявному приведению при сравнении.
Таким образом, AAA =
всегда для явного, всегда для неявного (присваивание), всегда для
неявного (сравнение).
Символ S («иногда разрешено») применяется в следующих особых случаях:
Из STRING в BOOLEAN разрешено, если UPPER(string-value) = 'TRUE' или
'FALSE'.
Из числового типа в INTEGER или UNSIGNED разрешено для
приведения и присваивания, только если результат не выходит за пределы
диапазона и число не имеет цифр после десятичной точки.
Из STRING в
INTEGER, UNSIGNED или DECIMAL разрешено, только если строка содержит
представление числа, результат не выходит за пределы диапазона и число
не имеет цифр после десятичной точки.
Из STRING в DOUBLE или NUMBER
разрешено, только если строка содержит представление числа.
Из STRING
в UUID разрешено, только если значение имеет вид (8 шестнадцатеричных
цифр) дефис (4 шестнадцатеричные цифры) дефис (4 шестнадцатеричные
цифры) дефис (4 шестнадцатеричные цифры) дефис (12 шестнадцатеричных
цифр), например '8e3b281b-78ad-4410-bfe9-54806a586a90'.
Из
VARBINARY в UUID разрешено, только если значение имеет длину 16 байт,
как в X'8e3b281b78ad4410bfe954806a586a90'.
В таблице не показаны преобразования To|From SCALAR, так как они
зависят от типа значения, а не от типа, указанного в определении
колонки. Явное приведение к SCALAR всегда разрешено.
В таблице не показаны преобразования To|From ARRAY, MAP или ANY, так
как практически ни одно преобразование невозможно. Явное приведение к
ANY или приведение любого значения к его исходному типу данных
допустимо, но только это. Это небольшое изменение: до Tarantool
2.10.0 было допустимо
приводить такие значения к VARBINARY. По-прежнему можно использовать
аргументы этих типов в функциях QUOTE, что
позволяет преобразовать их в STRING.
Примеры приведения типов, иллюстрирующие ситуации из таблицы:
Выполнение 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 </release/2.5.1) действует измененный алгоритм присваивания. В связи с этим неявные приведения строк к числам недопустимы. Например, INSERT INTO t (integer_column) VALUES ('5');` выдаст ошибку.
Неявное приведение выполняется, если строки (STRING) используются в
арифметических операциях.
Поэтому '5' / '5' = 1. Если приведение не
удалось, результатом будет ошибка.
Поэтому '5' / '' вызовет ошибку.
Неявное приведение не производится, если числовые значения используются
в конкатенации или в LIKE.
Поэтому выражение 5 || '5' недопустимо.
В следующих примерах неявное приведение не выполняется для значений в
колонках SCALAR:
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 строк. Значит, 11 > '2'. */
SELECT * FROM scalars WHERE scalar_column < '2'; /* 1 строка. Значит, 11 < '2'. */
SELECT max(scalar_column) FROM scalars; /* 1 строка: '2'. Значит, 11 < '2'. */
SELECT sum(scalar_column) FROM scalars; /* 1 строка: 13. Значит, приведение выполнено. */
На эти результаты не влияет индексирование или изменение порядка
операндов.
Неявное приведение НЕ выполняется для
GREATEST() и LEAST().
Поэтому LEAST('5',6) вернет 6.
Для аргументов функций:
Если в описании функции указано, что параметр
имеет определенный тип данных и неявное приведение при присваивании
разрешено, то аргументы, переданные с другим типом данных, будут
преобразованы до применения функции.
Например, функция
LENGTH() ожидает STRING или VARBINARY, а INTEGER
можно преобразовать в STRING, поэтому LENGTH(15) вернет длину строки
'15', то есть 2.
Однако для параметров неявное приведение иногда НЕ
выполняется. Поэтому ABS('5') вызовет сообщение об ошибке после
исправления
Issue#4159. Тем не
менее TRIM(5) останется допустимым.
Хотя это не является требованием стандарта SQL, неявное приведение
призвано обеспечить совместимость с другими СУБД. Однако в других СУБД
действуют разные правила относительно того, что можно преобразовывать
(например, может разрешаться присваивание 'inf', но запрещаться
сравнение с '1e5'). И, конечно, невозможно обеспечить совместимость с
другими СУБД и одновременно поддерживать SCALAR, которого в других СУБД
нет.