Още от версия 10.3.1, MariaDB включва както LENGTH()
функция и LENGTHB()
функция.
Този втори има B
в края на името. Така че е нещо като Length A
и Length B
, с изключение на това Length A
няма A
.
Объркан?
Бях, когато за първи път срещнах LENGTHB()
. Вече знаех за LENGTH()
, така че защо е необходима версия „B“?
Нека разберем.
Съвместимост с Oracle
Според MariaDB проблем 12783, преди LENGTHB()
беше въведен (и преди LENGTH()
беше променен) нещата работеха така:
- MariaDB превежда функцията
LENGTH()
към стандартната функция на SQLOCTET_LENGTH()
. - Oracle превежда функцията
LENGTH()
към стандартната функция на SQLCHAR_LENGTH()
.
След това беше взето решение да се промени LENGTH()
на MariaDB функция, така че да се държи различно, в зависимост от режима на SQL, в който работи. По-конкретно:
- Когато работи в режим по подразбиране (т.е.
sql_mode=DEFAULT
), MariaDB ще продължи да превеждаLENGTH()
доOCTET_LENGTH()
. - Въпреки това, когато работите в режим на Oracle (т.е.
sql_mode=ORACLE
), той превеждаLENGTH()
доCHAR_LENGTH()
вместо това.
Представяме LENGTHB()
Което ни отвежда до LENGTHB()
функция.
LENGTHB()
функцията беше добавена като част от същата работа.
LENGTHB()
е синоним на OCTET_LENGTH()
независимо от режима на SQL. С други думи, LENGTHB()
се превежда в OCTET_LENGTH()
когато sql_mode=DEFAULT
и когато sql_mode=ORACLE
.
Това ни позволява да използваме LENGTHB()
в нашия код, без да се притеснявате, че ще бъде засегнат от sql_mode
на потребителя настройки.
Разликата
Разликата между тези две функции е очертана в следващата таблица.
Функция | Режим по подразбиране | Режим Oracle |
---|---|---|
LENGTH() | Връща броя на байтовете. | Връща броя на знаците. |
LENGTHB() | Връща броя на байтовете. | Връща броя на байтовете. |
Имайте предвид, че тази разлика е налице само от MariaDB 10.3.1. Преди това LENGTHB()
не съществува и LENGTH()
просто се превежда в OCTET_LENGTH()
.
Пример
Ето пример, който демонстрира разликата между LENGTH()
и LENGTHB()
.
Нека настроим нашата сесия да използва режима по подразбиране:
SET SESSION sql_mode=DEFAULT;
Сесията ми вероятно вече беше в режим по подразбиране, но няма нищо лошо да я задам изрично.
Сега нека изпълним LENGTH()
и LENGTHB()
със същия аргумент:
SELECT
LENGTH('café'),
LENGTHB('café');
Резултат:
+-----------------+------------------+ | LENGTH('café') | LENGTHB('café') | +-----------------+------------------+ | 5 | 5 | +-----------------+------------------+
Така че, когато са в режим по подразбиране, и двете връщат една и съща стойност.
В този случай и двамата върнаха 5
, защото в този низ има 5 байта (é
символът използва 2 байта, а всички останали използват по 1 байт).
Сега нека преминем към режим на Oracle:
SET SESSION sql_mode=ORACLE;
Сега нека повторим горното изявление:
SELECT
LENGTH('café'),
LENGTHB('café');
Резултат:
+-----------------+------------------+ | LENGTH('café') | LENGTHB('café') | +-----------------+------------------+ | 4 | 5 | +-----------------+------------------+
Този път има разлика между двете функции. Този път LENGTH()
върна 4
. Това е с 1 по-малко от преди.
Това е така, защото LENGTH()
се държи различно в режим на Oracle. Както споменахме, когато sql_mode=ORACLE
, LENGTH()
функцията се превежда в CHAR_LENGTH()
, който връща броя на знаците, а не на байтовете.
В предишния пример LENGTH()
върна броя на байтовете, защото, когато sql_mode=DEFAULT
, превежда се на OCTET_LENGTH()
.