Вы можете использовать вложенные циклы.
для моего $ e1 (qw (foo bar baz)) {для моего $ e2 (qw (cat dog)) {для моего $ e3 (qw (1 2 3 4)) {my @choice = ($ e1, $ e2, $ e3); ...}}}
Когда вам нужно произвольное количество вложенных циклов, вы можете использовать Algorithm :: Loops 's NestedLoops
].
использовать Алгоритм :: Петли qw (NestedLoops); my @lists = ([qw (foo bar baz)], [qw (cat dog)], [qw (1 2 3 4)],); my $ iter = NestedLoops (\ @ lists); while (my @choice = $ iter- & gt; ()) {...}
767 bytes - это ограничение префикса для таблиц InnoDB в MySQL версии 5.6 (и предыдущих версиях). Это 1000 байтов для таблиц MyISAM. В MySQL версии 5.7 и выше этот предел был увеличен до 3072 байт.
Вы также должны знать, что если вы установите индекс в большом поле char или varchar, кодируемом utf8mb4, вам нужно разделить максимальная длина префикса индекса 767 байтов (или 3072 байта) на 4, что приводит к 191. Это связано с тем, что максимальная длина символа utf8mb4 составляет четыре байта. Для символа utf8 это будет три байта, в результате чего максимальная длина префикса индекса будет равна 254.
Один из вариантов - просто установить нижний предел для полей VARCHAR.
Еще один вариант ( в соответствии с ответом на эту проблему ) следует получить подмножество столбца, а не всю сумму, то есть:
ALTER TABLE `mytable` ADD UNIQUE (column1 (15), столбец 2 (200));
Подчеркните, как вам нужно получить ключ для применения, но мне интересно, стоит ли рассматривать вашу модель данных относительно этого объекта, чтобы увидеть, есть ли улучшения, которые позволят вам реализовать предполагаемые бизнес-правила, не затрагивая ограничение MySQL.
Если вы создаете что-то вроде:
CREATE TABLE, ЕСЛИ НЕ СУЩЕСТВУЕТ your_table (id int (7) UNSIGNED NOT NULL AUTO_INCREMENT, имя varchar (256) COLLATE utf8mb4_bin NOT NULL, PRIMARY KEY (id), UNIQUE KEY name (name)) ENGINE = INNODB DEFAULT CHARSET = utf8mb4 AUTO_INCREMENT = 1 ROW_FORMAT = FIXED;
должно быть что-то вроде
CREATE TABLE, если не EXISTS your_table (id int (7) UNSIGNED NOT NULL AUTO_INCREMENT, имя varchar (256) COLLATE utf8mb4_bin NOT NULL, PRIMARY KEY (id)) ENGINE = INNODB DEFAULT CHARSET = utf8mb4 AUTO_INCREMENT = 1 ROW_FORMAT = FIXED;
, но вам нужно проверить уникальность этого столбца из кода или добавить новый столбец в качестве MD5 или SHA1 столбца varchar
Для меня проблема с «# 1071 - указанный ключ была слишком длинной, максимальная длина ключа - 767 байт» была решена после изменения комбинации primarykey / uniquekey, ограничив размер столбца на 200.
ALTER TABLE `mytable` ADD UNIQUE (` column1` (200), `column2` (200));
Я сделал некоторые поиски по этой теме, наконец, получил некоторые пользовательские изменения
Для Workbench MySQL 6.3.7 Версия доступна графическая межфазная
Для версий ниже 6.3.7 прямые параметры недоступны, поэтому вам нужно перейти с командной строкой
set global innodb_default_row_format = DYNAMIC;
Я вижу это сообщение: ERROR 1193 (HY000): Неизвестная системная переменная 'innodb_default_row_format'
– Adrian Cid Almaguer
24 January 2017 в 15:58
Когда вы достигнете предела. Задайте следующее:
utf8
VARCHAR (255)
utf8mb4
VARCHAR (191)
utf8mb4
(которое является наиболее часто используемым кодированием для новых баз данных, поскольку оно принимает emojis / etc).
– Claudio Holanda
8 September 2016 в 00:48
ENGINE = InnoDB DEFAULT CHARSET = utf8
в конце инструкции CREATE TABLE
, я смог получить первичный файл VARCHAR (255)
ключ. Благодарю.
– xonya
10 June 2018 в 14:07
Решение для Laravel Framework
Согласно Laravel 5.4. * documentation ; Вы должны установить длину строки по умолчанию в методе
boot
для
app / Providers / AppServiceProvider. php
файл следующим образом:
использовать Illuminate \ Support \ Facades \ Schema; public function boot () {Schema :: defaultStringLength (191); }
Объяснение этого исправления, данное Laravel 5.4. * documentation ;
Laravel использует набор символов utf8mb4 по умолчанию , который включает поддержку для хранения «emojis» в базе данных. Если вы используете версию MySQL старше версии 5.7.7 или MariaDB старше версии 10.2.2, вам может потребоваться вручную настроить длину строки по умолчанию, сгенерированную миграциями, чтобы MySQL создавал для них индексы. Вы можете настроить это, вызывая метод Schema :: defaultStringLength в вашем AppServiceProvider
. Кроме того, вы можете включить параметр innodb_large_prefix для вашей базы данных. Обратитесь к документации вашей базы данных, чтобы узнать, как правильно включить эту опцию.
Какую кодировку символов вы используете? Некоторые наборы символов (например, UTF-16 и т. Д.) Используют более одного байта на символ.
20 * 4 + 1
байт, а столбец 500 символов - 500 * 4 + 2
байтов
– Thanatos
29 November 2009 в 04:46
VARCHAR (256)
с индексом UNIQUE
изменение сортировки не повлияло на меня, как это было для @Andresch. Однако уменьшение длины от 256 до 255 действительно позволило решить эту проблему. Я не понимаю, почему, поскольку 767 / max 4 байта на символ даст максимум 191?
– Arjan
5 November 2012 в 16:45
255 * 3 = 765; 256 * 3 = 768
. Кажется, ваш сервер был asssuming 3 байта на символ, @Arjan
– Amber
5 November 2012 в 18:11
Я нашел этот запрос полезным для определения того, какие столбцы имеют индекс, нарушающий максимальную длину:
SELECT c.TABLE_NAME As TableName, c.COLUMN_NAME AS ColumnName, c.DATA_TYPE AS DataType, c .CHARACTER_MAXIMUM_LENGTH AS ColumnLength, s.INDEX_NAME AS IndexName FROM information_schema.COLUMNS AS c INNER JOIN information_schema.statistics AS s ON s.table_name = c.TABLE_NAME И s.COLUMN_NAME = c.COLUMN_NAME WHERE c.TABLE_SCHEMA = DATABASE () И c. CHARACTER_MAXIMUM_LENGTH & gt; 191 И c.DATA_TYPE IN ('char', 'varchar', 'text')
Если вы недавно изменили innodb_log_file_size
, попытайтесь восстановить предыдущее значение, которое сработало.
Указанный ключ слишком длинный; max длина ключа составляет 767 байт
Это сообщение вы получили, потому что 1 байт равен 1 символу, только если вы используете набор символов latin-1
. Если вы используете utf8
, каждый символ будет считаться 3 байтами при определении вашего столбца ключа. Если вы используете utf8mb4
, каждый символ будет считаться 4 байтами при определении вашего столбца ключа. Таким образом, вам нужно умножить предел символов вашего ключевого поля на, 1, 3 или 4 (в моем примере), чтобы определить количество байт, которые ключевое поле пытается разрешить. Если вы используете uft8mb4, вы можете определить только 191 символ для собственного поля InnoDB, primary key. Просто не нарушайте 767 байт.
Я думаю, что varchar (20) требует только 21 байт, а varchar (500) требует только 501 байт. Таким образом, суммарные байты 522, меньше 767. Итак, почему я получил сообщение об ошибке?
blockquote>UTF8 требует 3 байта на символ для хранения строки, поэтому в вашем случае 20 + 500 символов = 20 * 3 + 500 * 3 = 1560 байт, что более чем допустимо 767 байт.
Предел для UTF8 равен 767/3 = 255 символов, для UTF8mb4, который использует 4 байта на символ, это 767 / 4 = 191 символ.
. Если вам нужно использовать более длинный столбец, чем предел, это два решения:
- Используйте «более дешевую» кодировку ( один, который требует меньше байтов на символ). В моем случае мне нужно было добавить уникальный индекс в столбец, содержащий строку SEO-статьи, поскольку я использую только символы
[A-z0-9 \ -]
для SEO, Я использовалlatin1_general_ci
, который использует только один байт на символ, поэтому столбец может иметь длину 767 байт.- Создайте хэш из своего столбца и используйте уникальный индекс только для этого. Другим вариантом для меня было создание другого столбца, в котором будет храниться хэш SEO, этот столбец имел бы
UNIQUE
ключ для убедитесь, что значения SEO уникальны. Я бы также добавил индексKEY
в исходную колонку SEO, чтобы ускорить поиск.
В моем случае у меня была эта проблема, когда я создавал резервную копию базы данных, используя выходные / выходные символы перенаправления linux. Поэтому я изменяю синтаксис, как описано ниже. PS: использование терминала linux или mac.
Резервное копирование (без> перенаправления)
# mysqldump -u root -p databasename -r bkp.sql
Восстановить (без & lt; redirect)
# mysql -u root -p --default-character-set = utf8 databasename mysql & gt; Имена SET «utf8» mysql & gt; SOURCE bkp.sql
Ошибка «Указанный ключ был слишком длинным, максимальная длина ключа - 767 байт» исчезла.
Вот мой оригинальный ответ:
Я просто отбрасываю базу данных и воссоздаю вот так, и ошибка исчезла:
drop database, если существует rhodes; create database rhodes default CHARACTER set utf8 default COLLATE utf8_general_ci;
Однако он не работает для всех случаев.
На самом деле проблема использования индексов в столбцах VARCHAR с набором символов
utf8
(илиutf8mb4
) с столбцами VARCHAR, которые имеют больше, чем определенной длины символов. В случаеutf8mb4
эта определенная длина равна 191.Для получения дополнительной информации о том, как использовать длинные индексы в базе данных MySQL, см. Раздел «Лонг-индекс» в этой статье: http://hanoian.com/content/index.php/24-automate-the-converting-a-mysql-database-character-set-to-utf8mb4
Если вы запустите Laravel (теперь laravel по умолчанию использует 4-байтовый Unicode, который вызывает это), вы можете решить это, изменив следующие строки в config / database.php из
'charset' = & GT; 'utf8mb4', 'collation' = & gt; 'utf8mb4_unicode_ci',
 to
'charset' = & gt; 'utf8', 'collation' = & gt; 'utf8_unicode_ci',
utf8
из utf8mb4
.
– Player1
16 July 2018 в 19:42
На основании столбца, приведенного ниже, эти 2 столбца с переменной строкой используют utf8_general_ci
сопоставление ( utf8
подразумевается charset).
В MySQL, utf8
charset использует максимум 3 байта для каждого символа. Таким образом, ему нужно будет выделить 500 * 3 = 1500 байт, что намного больше, чем позволяет 767 байт MySQL. Вот почему вы получаете эту ошибку 1071.
Другими словами, вам нужно вычислить количество символов на основе представления байта набора символов, поскольку не каждая кодировка представляет собой однобайтовое представление (как вы предполагали). I.E. utf8
в MySQL использует не более 3 байтов на символ, 767 / 3≈255 символов, а для utf8mb4
- не более 4-байтового представления, 767 / 4≈ 191 символов.
Известно также, что MySQL
column1 varchar (20) utf8_general_ci column2 varchar (500) utf8_general_ci
вы можете добавить столбец md5 длинных столбцов
запустите этот запрос перед вашим запросом:
SET @@ global.innodb_large_prefix = 1;
это увеличит предел до 3072 байта
.
Я исправил эту проблему с помощью:
varchar (200)
заменен на
varchar (191)
все varchar, которые имеют более 200, заменяют их 191 или устанавливают их текст.
Ответ на вопрос о том, почему вы получили сообщение об ошибке, уже получили ответы от многих пользователей здесь. Мой ответ о том, как исправить и использовать его как есть.
Обратитесь к этой ссылке .
, используя my_database_name;
[ ! d6] База данных изменена
set global innodb_large_prefix = on;
Query OK, 0 строк (0.00 sec)
set global innodb_file_format = Barracuda;
Query OK, 0 строк, затронутых (0.02 сек.)
- Перейдите в свою базу данных на phpMyAdmin или что-то вроде этого для удобства управления. > Выберите базу данных> Просмотреть структуру таблицы> Перейдите на вкладку «Операции». > Измените ROW_FORMAT на DYNAMIC и сохраните изменения.
- Перейдите на вкладку структуры таблицы> Нажмите кнопку «Уникальная».
- Готово. Теперь у него не должно быть ошибок.
Проблема этого исправления заключается в том, что вы экспортируете db на другой сервер (например, с локального хоста на реальный хост), и вы не можете использовать командную строку MySQL на этом сервере , Вы не можете заставить его работать.
Для laravel 5.6
Шаги к следующему
, что все, Наслаждайтесь.
Просто изменив utf8mb4
на utf8
при создании таблиц, решил мою проблему. Например: CREATE TABLE ... DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
to CREATE TABLE ... DEFAULT CHARSET = utf8 COLLATE = utf8_unicode_ci;
.
Мы столкнулись с этой проблемой при попытке добавить индекс UNIQUE в поле VARCHAR (255), используя utf8mb4. Хотя проблема здесь уже хорошо описана, я хотел бы добавить некоторые практические советы о том, как мы это поняли и решили.
При использовании utf8mb4 символы считаются 4 байтами, тогда как под utf8 они могут как 3 байта. Базы данных InnoDB имеют ограничение на то, что индексы могут содержать только 767 байт. Поэтому при использовании utf8 вы можете сохранить 255 символов (767/3 = 255), но используя utf8mb4, вы можете хранить только 191 символ (767/4 = 191).
Вы абсолютно можете добавить регулярные индексы для полей VARCHAR (255)
с использованием utf8mb4, но случается, что размер индекса обрезается с 191 символом автоматически - например unique_key
здесь:
Это прекрасно, потому что регулярные индексы просто используются для быстрого поиска MySQL через ваши данные. Все поле не нужно индексировать.
Итак, почему MySQL автоматически обрезает индекс для регулярных индексов, но бросает явную ошибку при попытке сделать это для уникальных индексов? Ну, для того, чтобы MySQL смог выяснить, существует ли уже существующее или обновляемое значение, ему нужно фактически индексировать все значение, а не только его часть.
В конце дня, если вы хотите иметь уникальный индекс в поле, все содержимое поля должно вписываться в индекс. Для utf8mb4 это означает сокращение длины полей VARCHAR до 191 символа или меньше. Если вам не нужна utf8mb4 для этой таблицы или поля, вы можете вернуть ее обратно в utf8 и сохранить свои длины длины.
MySQL принимает наихудший случай для числа байтов на символ в строке. Для кодировки MySQL 'utf8' это 3 байта на символ, так как эта кодировка не допускает символов за пределами U + FFFF
. Для кодировки MySQL 'utf8mb4' это 4 байта на символ, так как это то, что MySQL называет фактическим UTF-8.
Итак, если вы используете «utf8», ваш первый столбец займет 60 байт index, а второй - 1500.
измените настройку. Вы можете использовать utf8_general_ci, который поддерживает почти все
Если у кого-то возникают проблемы с INNODB / Utf-8, пытаясь поместить индекс UNIQUE
в поле VARCHAR (256)
, переключите его на VARCHAR ( 255)
. Кажется, 255 является ограничением.
3 * 255 = 765 & lt; 767
.
– Stefan Endrullis
23 July 2014 в 09:25
utf8
, который, к сожалению, сломан. Он может кодировать символы только в базовой многоязычной плоскости. Вы получите проблемы с персонажами, которые выходят за рамки этого. Например, те персонажи из Эможи, которые они добавляли, выходят за его пределы, я думаю. Поэтому вместо переключения на VARCHAR (255)
, переключитесь на VARCHAR (191)
и i>, переведите кодировку в utf8mb4
(на самом деле это просто utf8, но MySql хотел удержать. compat).
– Stijn de Witt
5 December 2016 в 11:28
Измените CHARSET в поле индекса жалобы на «latin1», то есть ALTER TABLE tbl CHANGE myfield myfield varchar (600) CHARACTER SET latin1 DEFAULT NULL; latin1 принимает один байт за один символ вместо четырех
Убедитесь, что sql_mode
подобен
sql_mode = NO_ENGINE_SUBSTITUTION, STRICT_TRANS_TABLES
, если это так, измените на
sql_mode = NO_ENGINE_SUBSTITUTION
OR
перезагрузите ваш сервер, изменив файл my.cnf (следующее задание)
innodb_large_prefix = on
utf8mb4
(который остальной мир вызывает utf8), требуется (не более) 4 байта на символ , вы можете индексировать только доVARCHAR ( 191)
. Набор символов Mysql'sutf8
(который весь мир нарушает) требует не более 3 байтов на символ, поэтому, если вы используете это (что вы не должны ), вы может индексироваться доVARCHAR (255)
– Stijn de Witt 5 December 2016 в 11:17