⚡️Почему тип поля enum на уровне базы — зло



Тип колонки enum используется для хранения данных, которые могут принимать определённые значения из заранее определённого набора.

Он обеспечивает ограничение значений, которые может принимать колонка, и позволяет более строго контролировать данные.

Это может быть полезно для хранения статусов, категорий, типов или любых других значений, которые могут быть заданы только из ограниченного набора вариантов.



А что на практике? Давайте рассмотрим.



Допустим у нас есть таблица со списком платежей, содержащая колонку status со следующими значениями:

CREATE TABLE `payments`(

`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,

`status` ENUM('new', 'progress', 'done', 'fauled') NOT NULL,

KEY(`id`)

) CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;




▪️Через какое-то время была замечена грамматическая ошибка в слове "failed" и принято решение её исправить.



Нюанс изменения enum поля в том, что при его редактировании сбрасываются значения колонки в null для всех строк таблицы, а то и вовсе получим ошибку Data truncated for column 'status' at row 3. То есть, чтобы корректно изменить enum поле, нужно куда-то сохранить данные. План действий будет таков:



1. Создать новую enum колонку с правильным набором данных;



2. Скопировать значение из старой колонки в новую и сразу применить исправление значения;



3. Удалить старую enum колонку;



4. Переименовать новую enum колонку.



При использовании фреймворка Laravel это будет выглядеть следующим образом:

use Illuminate\Database\Migrations\Migration;

use Illuminate\Database\Schema\Blueprint;

use Illuminate\Support\Facades\DB;

use Illuminate\Support\Facades\Schema;



return new class extends Migration

{

public function up(): void

{

// Создаём новую колонку

Schema::table('payments', function (Blueprint $table) {

$table->enum('tmp_status', ['new', 'progress', 'done', 'failed']);

});



// Копируем значения из enum колонки в новую с корректировкой значения

DB::statement('UPDATE payments SET tmp_status = (IF status = \'fauled\' THEN \'failed\' ELSE status END IF)');



// Удаляем старую колонку

Schema::table('payments', function (Blueprint $table) {

$table->dropColumn('status');

});



// Переименовываем колонку

Schema::table('payments', function (Blueprint $table) {

$table->renameColumn('tmp_status', 'status');

});

}

};




На языке SQL эти действия будут выглядеть следующим образом:



📌 Читать далее



@phpshka