Edited at

LaravelでPrimaryKeyが複数で片方がIncrementのテーブルを作るmigration

More than 1 year has passed since last update.


目的


  • primary_keyが複数ある。

  • idはオートインクリメントにしたい。

  • LaravelのMigartionを使いたい。

と、設定されたテーブルを作りたいので...


実際の実装

マイグレーションのサンプルコード


2018_06_21_172946_create_examples_table.php

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateOrderSourcesTable extends Migration
{
const TABLE_NAME = 'examples';

/**
* Run the migrations.
*
* @return void
*/

public function up()
{
Schema::create(self::TABLE_NAME, function (Blueprint $table) {
$table->unsignedBigInteger('id');
$table->unsignedBigInteger('parent_id');
$table->unsignedTinyInteger('example_data');

$table->primary(['id', 'parent_id']);
});

Schema::table(self::TABLE_NAME, function (Blueprint $table) {
// 1個目の引数がカラム名、2個目がインクリメント、3個目がunsigned flag
$table->BigInteger('id', true, true)->change();
});
}

/**
* Reverse the migrations.
*
* @return void
*/

public function down()
{
Schema::drop(self::TABLE_NAME);

/**
* SEQUENCEを削除する。
* 自動生成では {テーブル名}_{インクリメントされたカラム}_
*/

\DB::statement('DROP SEQUENCE '.self::TABLE_NAME.'_id_seq');
}
}




解説

未検証ですが、おそらくincement()で主キーのカラムを一個作り、

ALTERでもう一つカラムを追加するやり方でも出来るかもしれません。


重要なポイント


up()


  • 先にincrement()か、primary()で主キーを一個定義してしまうと、
    2個目は「主キーが既にある」として、エラーになってしまいます。

 SQLSTATE[42P16]: Invalid table definition: 7

ERROR: multiple primary keys for table "example" are not allowed
(SQL: alter table "example" add primary key ("secondery_id"))


  • そこで、BigInteger()でidを定義し、
    $table->primary([]);の構文で複数に主キーを指定します。

  • そして必要なカラムを後からインクリメントに変更します。

  • サンプルコードのコメントで記載してあるように、
    Integer(), BigIntegerは第2~3の引数で設定を変えられます。


drop()


  • Sequenceが残っているとrollbackして再びmigrateした際に、下記のようなエラーになります。


cli

> php artisan migrate

> php artisan migrate:rollback
> php artisan migrate
SQLSTATE[42P07]: Duplicate table: 7 ERROR:
relation "order_examples_id_seq" already exists
(SQL: CREATE SEQUENCE order_items_id_seq)



  • このため、dropする際はDROP SEQUENCEを直接実行しています。
    これは、複合キーの場合はSchema::dropしただけでは消えなかったこと、
    dropPrimary(), bigInteger()などで主キーを解除しても消えなかったためです。