Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
Страницы 1
У меня есть две миграции по умолчанию (
2014_10_12_000000_create_users_table
и
2014_10_12_100000_create_password_resets_table
) и ещё одна собственная:
class CreatePagesTable extends Migration {
public function up() {
Schema::create('pages', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->unique();
$table->string('title');
$table->text('metadesc');
$table->text('keywords');
});
}
public function down() {
Schema::dropIfExists('pages');
}
}
Когда я попытался сделать миграцию в первый раз, в консоли было:
> php artisan migrate
Migration table created successfully.
[Illuminate\Database\QueryException]
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max ke
y length is 767 bytes (SQL: alter table `users` add unique `users_email_unique`(`email`))
[PDOException]
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max ke
y length is 767 bytes
Таблицы pages при этом в БД не появилось. Эксперимента ради я решил попробовать ещё раз сделать миграцию, и тогда получил
[Illuminate\Database\QueryException]
SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'users' already exists (SQL
: create table `users` (`id` int unsigned not null auto_increment primary key, `name` varc
har(191) not null, `email` varchar(191) not null, `password` varchar(191) not null, `remem
ber_token` varchar(100) null, `created_at` timestamp null, `updated_at` timestamp null) de
fault character set utf8mb4 collate utf8mb4_unicode_ci)
[PDOException]
SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'users' already exists
Однако, когда я попробовал сделать откат, то получил
> php artisan migrate:rollback
Nothing to rollback.
> php artisan migrate:reset
Nothing to rollback.
Я пробовал это решение, безрезультатно:
public function boot()
{
Schema::defaultStringLength(191);
}
Я хочу понять причину происходящего.
Данные моих инструментов:
Laravel Framework 5.4.22
Apache PHP-7
MySQL - 5.5
Не в сети
Вот, мне помогло в свое время установка сравнения как `utf_general_ci`, если тебе нужна именно `utf8mb4` в ссылке решение.
Не в сети
Благодарю Вас за ответ!
В результате экспериментов я-таки все миграции сделал, но причину предыдущих неудач не установил, потому пока не могу сказать, помогло ли Ваше решение. Если появится новая информация, я снова отпишусь в данной теме.
Не в сети
utf_general_ci — такой кодировки в MySQL не существует. Есть utf8_general_ci, utf16_general_ci, utf32_general_ci и обычно используется первая. Однако если MySQL нормальной версии, а не раритет — лучше во всех случаях вместо них использовать utf8mb4_..., так как только она полностью поддерживает Юникод (в частности, emoji будут работать только там).
Кроме того, кодировка влияет на размер строки и ключа. В MySQL и то, и другое ограничено 767 байтами (о чём и указано в ошибке).
Поле переменной длины (VARCHAR/VARBINARY) в данном случае по смыслу равно полю фиксированной длины (CHAR/BINARY). Это значит, что его размер задаёт максимальный размер поля, то есть MySQL предполагает, что значения действительно будут достигать этой длины. Это имеет несколько последствий, два самых важных из которых:
В случае Gleb2708, видимо, имеет место быть первая проблема (хотя я не вижу кода CREATE TABLE users, который выдал ошибку в первый раз). utf8_general_ci это урезанная («облегченная») версия Юникода, где символ может занимать 1-3 байта. Соответственно, если у нас поле с максимальной длиной 255 символа (не байт!), то:
255 * 3 = 765 + 2 = 767
Здесь 3 — максимальная длина каждого символа (по верхней планке), 2 — длина значения-строки в байтах (т.к. поле с переменной длиной, длина значения для каждой строки данных хранится в виде двух байт). Итого получаем, что 255 при utf8_general_ci есть максимальная длина, при которой такое строковое поле может использоваться в виде ключа.
Если ключ составной (состоит из нескольких полей), то аналогичным образом складываются длины всех полей в нём — они не должны быть больше 767 байт.
utf8mb4_general_ci — это реализация UCS-4 (UTF-32), где каждый символ занимает 1-4 байта. Соответственно, длина такого поля ещё меньше:
191 * 4 = 764 + 2 = 766
Длина поля также влияет на длину строки данных в таблице, но там расчёт другой. Общая идея та же — указанная длина должна быть максимально близкой к длине настоящих данных, это лучше во многих отношениях.
Тем не менее, максимальная длина поля не обязательно напрямую зависит от того, используется оно в ключе или нет. При создании ключа можно указать длину, которая будет индексироваться и она может быть меньше полной длины поля (в этом случае индекс будет работать, но менее эффективно для строк, которые длиннее длины поля, указанной для ключа). Расчёт для максимальной длины индекса тот же, что и выше.
Таким образом, если ты создаёшь поле email varchar(N) collate utf8mb4_unicode_ci и потом создаёшь ключ на нём без указания длины, то MySQL берёт длину поля (N) и при N >191 ты получишь ошибку (причём не при создании таблицы, а при добавлении туда ключа). Для полей TEXT/BLOB при создании ключа обязательно нужно указывать длину, так как максимальная длина таких полей заведомо очень большая (за исключением TINYTEXT/TINYBLOB она начинается от 65 Кб).
Вариантов это решить два, даже три:
Не в сети
Ну, простите, очепятался.
Не в сети
Страницы 1