Laravel Migration Change to Make a Column Nullable


194

Utworzyłem migrację z niepodpisanym user_id. Jak mogę edytować user_idnową migrację, aby to zrobić nullable()?

Schema::create('throttle', function(Blueprint $table)
{
    $table->increments('id');
    // this needs to also be nullable, how should the next migration be?
    $table->integer('user_id')->unsigned();
}

Odpowiedzi:


263

Laravel 5 obsługuje teraz zmianę kolumny; oto przykład z oficjalnej dokumentacji:

Schema::table('users', function($table)
{
    $table->string('name', 50)->nullable()->change();
});

Źródło: http://laravel.com/docs/5.0/schema#changing-columns

Laravel 4 nie obsługuje modyfikowania kolumn, więc musisz użyć innej techniki, takiej jak napisanie surowego polecenia SQL. Na przykład:

// getting Laravel App Instance
$app = app();

// getting laravel main version
$laravelVer = explode('.',$app::VERSION);

switch ($laravelVer[0]) {

    // Laravel 4
    case('4'):

        DB::statement('ALTER TABLE `pro_categories_langs` MODIFY `name` VARCHAR(100) NULL;');
        break;

    // Laravel 5, or Laravel 6
    default:                

        Schema::table('pro_categories_langs', function(Blueprint $t) {
            $t->string('name', 100)->nullable()->change();
        });               

}

3
Dzięki za to. Ale jak mogę zrobić coś przeciwnego? Jak zmienić kolumnę, aby nie była zerowalna? Jakieś pomysły?
algorhythm

@algorhythm Czy próbujesz tego „$ t-> string („ name ”, 100) -> change (); '
MURATSPLAT

7
Musisz migrować doktrynę \ dbal
ty

33
@algorhythm ->nullable(false)pozwoli ci ponownie zmienić kolumnę.
Colin

9
-> change () wymaga zainstalowania pakietu Doctrine DBAL i nie rozpoznaje z natury wszystkich tych samych typów kolumn, które są dostępne po wyjęciu z pudełka z laravel .. na przykład double nie jest rozpoznawanym typem kolumny dla DBAL.
Will Vincent,

174

Oto pełna odpowiedź dla przyszłego czytelnika. Pamiętaj, że jest to możliwe tylko w Laravel 5+.

Przede wszystkim potrzebujesz pakietu doktryna / dbal :

composer require doctrine/dbal

Teraz podczas migracji możesz to zrobić, aby kolumna miała wartość null:

public function up()
{
    Schema::table('users', function (Blueprint $table) {
        // change() tells the Schema builder that we are altering a table
        $table->integer('user_id')->unsigned()->nullable()->change();
    });
}

Być może zastanawiasz się, jak przywrócić tę operację. Niestety ta składnia nie jest obsługiwana:

// Sadly does not work :'(
$table->integer('user_id')->unsigned()->change();

To jest poprawna składnia do przywrócenia migracji:

$table->integer('user_id')->unsigned()->nullable(false)->change();

Lub, jeśli wolisz, możesz napisać surowe zapytanie:

public function down()
{
    /* Make user_id un-nullable */
    DB::statement('UPDATE `users` SET `user_id` = 0 WHERE `user_id` IS NULL;');
    DB::statement('ALTER TABLE `users` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
}

Mam nadzieję, że ta odpowiedź okaże się przydatna. :)


4
Jest to najbardziej kompletna odpowiedź dla L5, ale należy wspomnieć, że jeśli „identyfikator_użytkownika” jest kluczem obcym, którym powinien być, nie będzie można go zmienić, dopóki nie uruchomisz instrukcji „DB ::” („SET FOREIGN_KEY_CHECKS” = 0 ');' pierwszy. Po zakończeniu ustaw ponownie na 1.
rzb

1
Dziękuję, nullable(false)uratowałeś mnie przed wyciąganiem włosów, ponieważ nullable()nie jest to dobrze udokumentowane i nie ma żadnej notNull()funkcji.
Zack Morris

nie działa to dla kluczy obcych z postgres. próba SET FOREIGN_KEY_CHECKS = 0powoduje błąd. prawdopodobnie będziesz musiał zmienić ograniczenia tabeli przy użyciu surowego zapytania. patrz tutaj: postgresql.org/docs/current/static/sql-altertable.html
rrrafalsz

To łamie moje testy. Testy zaczynają się uruchamiać, a następnie zawieszają. Przypuszczam, że powoduje to pierwsze wycofanie. Powoduje zawieszanie testów dla MySQL, a także dla SQLite.
Thomas Praxl

155

Zakładam, że próbujesz edytować kolumnę, do której już dodałeś dane, więc usunięcie kolumny i ponowne dodanie jako kolumny zerowalnej nie jest możliwe bez utraty danych. Będziemy alteristniejącą kolumną.

Jednak konstruktor schematów Laravela nie obsługuje modyfikowania kolumn innych niż zmiana nazwy kolumny. Aby to zrobić, musisz uruchomić nieprzetworzone zapytania:

function up()
{
    DB::statement('ALTER TABLE `throttle` MODIFY `user_id` INTEGER UNSIGNED NULL;');
}

Aby mieć pewność, że nadal możesz cofnąć migrację, my również to zrobimy down().

function down()
{
    DB::statement('ALTER TABLE `throttle` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
}

Jedna uwaga jest taka, że ​​ponieważ konwertujesz między wartościami zerowalnymi i zerowymi, musisz upewnić się, że wyczyściłeś dane przed / po migracji. Zrób to w skrypcie migracji na dwa sposoby:

function up()
{
    DB::statement('ALTER TABLE `throttle` MODIFY `user_id` INTEGER UNSIGNED NULL;');
    DB::statement('UPDATE `throttle` SET `user_id` = NULL WHERE `user_id` = 0;');
}

function down()
{
    DB::statement('UPDATE `throttle` SET `user_id` = 0 WHERE `user_id` IS NULL;');
    DB::statement('ALTER TABLE `throttle` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
}

7
Dla laravel 4, zastąpić queryprzezstatement
Razor

2
Dzięki @Razor. Zaktualizowałem odpowiednio moją odpowiedź.
Unnawut

1
W downfunkcji w drugim bloku kodu instrukcja SQL powinna kończyć się NOT NULL. ( downFunkcja w trzecim przykładzie jest poprawna).
Scott Weldon

46

To pełna migracja dla Laravela 5 :

public function up()
{
    Schema::table('users', function (Blueprint $table) {
        $table->unsignedInteger('user_id')->nullable()->change();
    });
}

public function down()
{
    Schema::table('users', function (Blueprint $table) {
        $table->unsignedInteger('user_id')->nullable(false)->change();
    });
}

Chodzi o to, że możesz usunąć nullableprzekazując falsejako argument.



9

Dodanie do odpowiedzi Dmitrija Chebotareva, podobnie jak w przypadku Laravela 5+.

Po wymaganiu pakietu doktryna / dbal :

composer require doctrine/dbal

Następnie możesz wykonać migrację z zerowymi kolumnami, na przykład:

public function up()
{
    Schema::table('users', function (Blueprint $table) {
        // change() tells the Schema builder that we are altering a table
        $table->integer('user_id')->unsigned()->nullable()->change();
    });
}

Aby cofnąć operację, wykonaj:

public function down()
{
    /* turn off foreign key checks for a moment */
    DB::statement('SET FOREIGN_KEY_CHECKS = 0');
    /* set null values to 0 first */
    DB::statement('UPDATE `users` SET `user_id` = 0 WHERE `user_id` IS NULL;');
    /* alter table */
    DB::statement('ALTER TABLE `users` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
    /* finally turn foreign key checks back on */
    DB::statement('SET FOREIGN_KEY_CHECKS = 1');
}

3

Dodanie do odpowiedzi Dmitrija Chebotareva,

Jeśli chcesz zmienić wiele kolumn jednocześnie, możesz to zrobić jak poniżej

DB::statement('
     ALTER TABLE `events` 
            MODIFY `event_date` DATE NOT NULL,
            MODIFY `event_start_time` TIME NOT NULL,
            MODIFY `event_end_time` TIME NOT NULL;
');


2

Dla Laravela 4.2 powyższa odpowiedź Unnawuta jest najlepsza. Ale jeśli używasz prefiksu tabeli, musisz nieco zmienić kod.

function up()
{
    $table_prefix = DB::getTablePrefix();
    DB::statement('ALTER TABLE `' . $table_prefix . 'throttle` MODIFY `user_id` INTEGER UNSIGNED NULL;');
}

Aby mieć pewność, że nadal możesz cofnąć migrację, my również to zrobimy down().

function down()
{
    $table_prefix = DB::getTablePrefix();
    DB::statement('ALTER TABLE `' . $table_prefix . 'throttle` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.