目的
- primary_keyが複数ある。
- idはオートインクリメントにしたい。
- LaravelのMigartionを使いたい。
と、設定されたテーブルを作りたいので…
実装
サンプルコード
<?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 した際に、下記のようにエラーになります。
> 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()
などで主キーを解除しても消えなかったためです。