11.4.1. CHAR и VARCHAR Типы
CHAR и VARCHAR типы подобны, но отличаются по способу, которым они сохранены и получаются. Они также отличаются по максимальной длине и по тому, сохраняются ли конечные пробелы.
CHAR и VARCHAR типы объявляются с длиной, которая указывает на максимальное количество символов, которые Вы хотите сохранить. Например, CHAR(30) может содержать до 30 символов.
Длина a CHAR столбец фиксируется к длине, которую Вы объявляете, когда Вы составляете таблицу. Длина может быть любым значением от 0 до 255. Когда CHAR значения сохранены, они дополняются правом пробелами к указанной длине. Когда CHAR значения получаются, конечные пробелы не удаляются если PAD_CHAR_TO_FULL_LENGTH Режим SQL включается.
Значения в VARCHAR столбцы являются строками переменной длины. Длина может быть определена как значение от 0 до 65 535. Эффективная максимальная длина a VARCHAR подвергается максимальному размеру строки (65 535 байтов, который совместно используется среди всех столбцов), и используемый набор символов. См. Раздел E.10.4, «Пределы на Столбце таблицы граф и Размер Строки».
В отличие от CHAR , VARCHAR значения сохранены как 1-байтовый или 2-байтовый префикс длины плюс данные. Префикс длины указывает на число байтов в значении. Столбец использует байт одной длины, если значения требуют не больше, чем 255 байтов, два байта длины, если значения могут потребовать больше чем 255 байтов.
Для VARCHAR столбцы, конечные пробелы сверх длины столбца являются усеченными до вставки, и предупреждение сгенерировано, независимо от режима SQL в использовании. Для CHAR столбцы, усечение избыточных конечных пробелов от вставленных значений выполняется тихо независимо от режима SQL.
VARCHAR значения не дополняются, когда они сохранены. Конечные пробелы сохраняются, когда значения сохранены и получаются в соответствии со стандартным SQL.
Следующая таблица иллюстрирует различия между CHAR и VARCHAR показывая результат хранения различной строки оценивает в CHAR(4) и VARCHAR(4) столбцы (предполагающий, что столбец использует однобайтовый набор символов такой как latin1 ).
| Значение | CHAR(4) | Необходимое хранение | VARCHAR(4) | Необходимое хранение |
|---|---|---|---|---|
| » | ‘ ‘ | 4 байта | » | 1 байт |
| ‘ab’ | ‘ab ‘ | 4 байта | ‘ab’ | 3 байта |
| ‘abcd’ | ‘abcd’ | 4 байта | ‘abcd’ | 5 байтов |
| ‘abcdefgh’ | ‘abcd’ | 4 байта | ‘abcd’ | 5 байтов |
Значения, показанные как сохраненный в последней строке таблицы, применяют только если не использующий строгий режим ; если MySQL работает в строгом режиме, значения, которые превышают длину столбца, не сохранены , и ошибка заканчивается.
Если данное значение сохранено в CHAR(4) и VARCHAR(4) столбцы, значения, полученные от столбцов, являются не всегда тем же самым, потому что конечные пробелы удаляются из CHAR столбцы после извлечения. Следующий пример иллюстрирует это различие:
mysql>CREATE TABLE vc (v VARCHAR(4), c CHAR(4));Query OK, 0 rows affected (0.01 sec)mysql>INSERT INTO vc VALUES ('ab ', 'ab ');Query OK, 1 row affected (0.00 sec)mysql>SELECT CONCAT('(', v, ')'), CONCAT('(', c, ')') FROM vc;+---------------------+---------------------+| CONCAT('(', v, ')') | CONCAT('(', c, ')') |+---------------------+---------------------+| (ab ) | (ab) |+---------------------+---------------------+1 row in set (0.06 sec)
Значения в CHAR и VARCHAR столбцы сортируются и сравниваются согласно сопоставлению набора символов, присвоенному столбцу.
Все сопоставления MySQL имеют тип PADSPACE . Это означает что все CHAR , VARCHAR , и TEXT значения в MySQL сравниваются без отношения с любыми конечными пробелами. «Сравнение» в этом контексте не включает LIKE оператор сопоставления с образцом, для которого конечные пробелы являются существенными. Например:
mysql>CREATE TABLE names (myname CHAR(10));Query OK, 0 rows affected (0.03 sec)mysql>INSERT INTO names VALUES ('Monty');Query OK, 1 row affected (0.00 sec)mysql>SELECT myname = 'Monty', myname = 'Monty ' FROM names;+------------------+--------------------+| myname = 'Monty' | myname = 'Monty ' |+------------------+--------------------+| 1 | 1 |+------------------+--------------------+1 row in set (0.00 sec)mysql>SELECT myname LIKE 'Monty', myname LIKE 'Monty ' FROM names;+---------------------+-----------------------+| myname LIKE 'Monty' | myname LIKE 'Monty ' |+---------------------+-----------------------+| 1 | 0 |+---------------------+-----------------------+1 row in set (0.00 sec)
Это — истина для всех версий MySQL, и не влияется режимом SQL сервера.
Для тех случаев, где запаздывающие символы-заполнители разделяются или сравнения игнорируют их, если у столбца будет индексирование, которое требует уникальных значений, вставляя в значения столбцов, которые отличаются только по числу запаздывающих символов-заполнителей, то приведет к двойной ключевой ошибке. Например, если таблица содержит ‘a’ , попытка сохранить ‘a ‘ вызывает двойную ключевую ошибку.
MySQL максимальный размер varchar — 255. При создании я указал длину 9000. И поместил туда текст такой длины. И он сохранился. Почему не обрезался?

Вся актуальная информация по размерам в документации по каждому типу данных
https://dev.mysql.com/doc/refman/8.0/en/data-types.html
Английский все-же надо подтягивать, без него в мире разработки будет ну очень сложно. Переводите для начала хоть гуглом.
‘varbinary’ => 65535, //аналогично varchar

Добавлю, есть и сводная страница по всем типам.
https://dev.mysql.com/doc/refman/8.0/en/storage-re.
Также учитывайте, что текст свыше 255 символов занимает L+2 байта.
И внимание на многобайтовые кодировки.
Число в скобках у varchar — число символов. Предел же в 64 килоБАЙТа. Что далеко не всегда одно и то же. Для utf8mb4 вы гипотетически сможете записать от 16к до 65к символов — в зависимости от того, что именно пишете.
Ну и конкретно для varchar важнейшая деталь — 64кб — это не его предельный размер. Это hardcoded лимит на размер одной строки таблицы, включающий в себя все колонки этой таблицы. Невозможно иметь два varchar по 40кб
Ответы на вопрос 0
Ваш ответ на вопрос
Войдите, чтобы написать ответ

- MySQL
Как сделать сортировку по двум полям?
- 1 подписчик
- 13 часов назад
- 36 просмотров

- PHP
- +3 ещё
Как сделать быструю сортировку и фильтрацию товаров в bitrix с учетом скидок которые указаны в правилах корзины?
- 1 подписчик
- вчера
- 56 просмотров
Форум пользователей MySQL
Зачем нужно указывать длину ячейки varchar меньше 255-и символов, если на расход памяти это вроде как не влияет?
#2 12.01.2013 22:48:57
deadka Администратор Зарегистрирован: 14.11.2007 Сообщений: 2417
Re: Зачем указывать длину varchar меньше 255?
. Что значит «не влияет на расход памяти»? И что за привязка такая к числу 255? В-общем, поясните свою мысль.
Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли.
#3 12.01.2013 23:25:58
Имя занято Участник Зарегистрирован: 26.10.2011 Сообщений: 17
Re: Зачем указывать длину varchar меньше 255?
deadka, а что тут пояснять-то?)
Разница между ячейками CHAR(10) и VARCHAR(10) в том, что CHAR(10) всегда занимает 10 байт, даже если в ней записана только одна буква. А ячейка VARCHAR(10) будет занимать от 1-го до 11-и байт в зависимости от содержимого.
http://dev.mysql.com/doc/refman/5.6/en/char.html
Так зачем писать VARCHAR(10), если всегда можно писать VARCHAR(255) и не париться?
255 потому что:
1) до версии MySQL 5.0.3 это была максимальная длина
2) если указать больше 255-и, то к длине каждой записи будет прибавляться 2 байта вместо одного
http://dev.mysql.com/doc/refman/5.6/en/ … ments.html
3) если нужно хранить в ячейке большой текст, то для этого есть тип TEXT
Отредактированно Имя занято (12.01.2013 23:27:08)
CHAR или VARCHAR? А может быть BLOB?
На диске запись всегда упаковывается. То есть, концевые пробелы не имеют никакого значения с точки зрения дискового пространства.
Количество концевых пробелов учитывается только для varchar. Значение char «добивается» пробелами до объявленной длины только тогда, когда с ним производятся операции присвоения или передача данных на сторону клиента.
Поэтому с точки зрения эффективности хранения различия между char и varchar практически нет. И для работы нужно выбирать то, что удобнее. Как правило это varchar.
Клиентские компоненты могут (или не могут) осуществлять обрезание концевых пробелов для столбцов CHAR. В зависимости от склонностей разработчика такого набора обрезание пробелов может быть по умолчанию, а может и потребовать установки в True какого-либо свойства или на уровне DataSet, или на уровне конкретного поля (TStringField). Поэтому, если вас замучили концевые пробелы в строках, посмотрите на свойства компонент.
Нужно отметить, что ни BDE ни dbExpress не могут выполнять обрезание концевых пробелов у строк.
Поля типа BLOB
Поля этого типа позволяют хранить безразмерную произвольную двоичную информацию (поэтому поля типа BLOB не имеют свойства «набор символов»). Запись на диск производится сегментами. Дисковый сегмент блоба это вовсе не то, что имеется в виду при объявлении столбца BLOB (SEGMENT SIZE xx). Сервер сам разбирается, как хранить конкретное значение blob на диске. Указание размера сегмента при объявлении столбца BLOB не даст никакого выигрыша или проигрыша в производительности. Оно нужно только для приложений, написанных на C (Embedded SQL) при помощи GPRE. Например, в IBX размер буфера для чтения-записи blob определен жестко в 16К, и именно такими «сегментами» оперирует IBX. Поэтому определять размер сегмента при объявлении blob не имеет смысла.
Существуют предопределенные подтипы (SUB_TYPE) BLOB: 0 – двоичные данные, 1 – текстовые данные. На самом деле разницы между ними нет, и подтип имеет значение только для вашего приложения (или при написании фильтров BLOB). Пользовательские подтипы можно определить, указав SUB_TYPE с отрицательным знаком – -1, -2, -10, -200 и т. д., и опять же это имеет значение только для приложения, работающего с данными или для фильтра.
Сегменты BLOB всегда записываются на свободное пространство, и занимают только действительный объем данных BLOB.
Если размер BLOB превышает размер страницы, то создается массив указателей на страницы BLOB. При очень больших размерах BLOB могут появиться указатели на страницы указателей BLOB.
При изменении записи, если содержимое blob не менялось, его blobID остается тем же самым. Собственно, в новой версии записи пишутся только те поля, которые были изменены. Следовательно, при модификации записи, если не затронуто поле BLOB, данные blob не «дублируются». Если же блоб меняется, то как и версия записи, он находится на диске в двух экземплярах – старом и новом. Учитывайте это для блобов, хранящих большой объем данных.
Примечание. Индексировать по полям BLOB невозможно.
CHAR или BLOB?
- Если длина поля < 255 символов, то
- лучше использовать VARCHAR – по хранению varchar на 2 байта больше char, зато в приложениях не надо писать отрезание концевых пробелов у строк.
- в старых версиях IB при использовании VARCHAR могут возникнуть проблемы с производительностью при использовании протокола TCP/IP.
- не имеет смысла использовать BLOB – выборка BLOB осуществляется по его идентификатору, поэтому происходит чуть дольше и требует немного больше затрат на программирование.
- Можно использовать как CHAR или VARCHAR, так и BLOB. Индексирование по полями такой длины невозможно, к тому же есть шанс что однажды записываемые данные превысят 10000 символов, и может быть BLOB подойдет больше. Ориентируйтесь только на удобство работы с такими данными в приложении.
- лучше использовать BLOB. Подтип может быть любой, информацию в таком поле можно хранить произвольную и не беспокоиться о размере данных. Стоимость доступа к данным такого размера полностью компенсирует разницу в способах хранения и извлечения полей типа CHAR и BLOB.
Конвертация данных
В Firebird и Yaffil, в 3-м диалекте появилась возможность при insert (update?) содержимое блоба задавать обычной строкой. В остальных серверах при подобных действиях будет выдано стандартное сообщение о невозможности конвертации данных.
Вместе с тем уже давно существуют UDF перевода блоба в строку и обратно (FreeUDFLib и другие).
Возможные проблемы
Индексирование
- Строковые независимо от типа поля имеют ограничение на длину индекса – 84 байта при указании COLLATE и 252 байта – без COLLATE.
- BLOB-поля не могут быть проиндексированы.
Поиск
- Для поиска по полям типа CHAR, VARCHAR и BLOB можно использовать операторы STARTING WITH (начинается с), LIKE (начинается, содержит, или заканчивается на) и CONTAINING (содержит). В BLOB этими операторами можно искать произвольную информацию (необязательно текстовую), однако необходимо учитывать что поиск в BLOB может осуществляться только перебором записей.
- Если поиск производится по окончанию, например, LIKE ‘%ов’, то такой запрос по полю CHAR выдаст 0 записей, если длина значения поля хотя бы на один символ меньше объявленной длины поля. Это происходит потому, что CHAR при сравнении добивается до длины поля пробелами, и получается, что ‘Иванов ‘ не подходит под условие поиска ‘%ов’. Для решения этой проблемы нужно пользоваться VARCHAR
- Поиск или упорядочивание (ORDER BY) с использованием функции UPPER возможен только для полей типа CHAR или VARCHAR, т. к. только они имеют свойство CHARACTER SET (BLOB содержит только произвольную двоичную информацию, т. е. необязательно текстовую). Кроме того, для UPPER поля CHAR и VARCHAR должны иметь соответствующий COLLATE либо в объявлении типа поля, либо в выражении поиска или сортировки.
Примечание. Вы можете написать собственную функцию, аналогичную UPPER, и избежать указанной проблемы.
Выборка данных
- При конкатенации строковых полей в запросе нужно учитывать, что CHAR-поля будут «расширены» до указанной длины пробелами, а VARCHAR – нет. Например, если в запросе производится «сборка» фамилии, имени и отчества
select last_name||first_name||middle_name from clients
то результат будет приблизительно такой: «Иванов Иван Иванович». А если это будут VARCHAR-поля, то такой же запрос выдаст результат в виде «ИвановИванИванович».
Для решения этой проблемы можно для CHAR использовать UDF (типа RTrim), а для VARCHAR – вставлять дополнительные пробелы (||» «||).
- Для многоязыковых баз данных BLOB не могут быть перекодированы из одной кодировки в другую. Например, если сервер поддерживает кодировки WIN1251 и KOI8R, и база создана в WIN1251, возможно подключиться (через компоненты прямого доступа) указывая lc_ctype=KIO8R в параметрах коннекта. При этом информация будет перекодироваться из win1251 в koi8r и наоборот для всех строковых типов данных, кроме BLOB. Для конвертации данных blob хотя бы при выборке придется написать собственную UDF.
Вставка и модификация данных
- Поля BLOB невозможно передавать как параметр запроса или хранимой процедуры в BDE 2.5x и 3.x (такая возможность появилась только в BDE 4.0 и у компонент Delphi 3.0). Это приводит к необходимости использования TQuery и передачи данных в BLOB-поля через TBlobStream. Сам сервер не имеет проблем с получением или передачей blob в виде параметров запроса или параметров процедур.
Создание переносимой базы данных
- Стандарт ANSI SQL в частности определяет типы полей, но безусловно реализация этих типов, способ хранения и обработки определяет изготовитель конкретного SQL-сервера. Для обеспечения хоть какой-то возможной переносимости следует пользоваться совместимыми типами, игнорируя преимущества использовани типов данных (например CHAR в InterBase). Вам необходимо обратиться к документации или справочным файлам BDE (BDE32.HLP), для того чтобы определить совместимость различных типов между выбранными вами SQL-серверами.
Copyright iBase.ru © 2002-2023