"BOKU"のITな日常

還暦越えの文系システムエンジニアの”BOKU”は新しいことが大好きです。

はじめてLaravel6.0:マイグレーションのカラム定義を掘り下げる/MariaDB・MySQL

今回は、 Laravel6.0のマイグレーションで利用できるカラム定義について、ちょっとだけ掘り下げて整理してみます。

f:id:arakan_no_boku:20191003220222p:plain

 

 はじめに

 

Laravel6.0のマイグレーションと「 Eloquent ORM」を使えば、MariaDBMySQL)の物理構成を意識しなくても、テーブル作成して、CRUDもできて、サクサクとプログラムを書ける。

そこをさらに生かすために。

マイグレーションで指定できるカラム定義を整理しとこうかと思います。

それでは。

 

まずはキーになる「id」のバリエーションから

 

Laravel6.0はデフォルトで「 Eloquent ORM」を使います。

この「 Eloquent ORM」はテーブルの主キーが「id」というカラムであることを前提にして動作します。

つまり、「id」の値がとりえる範囲によって、そのテーブルのレコードがユニークでありえる範囲が決まってしまうわけです。 

まずは「AUTO INCREMENT」属性つきの「id」になりえるカラムについて確認していきます。

種類はこれだけあります。

  • $table->tinyIncrements('id');
  • $table->smallIncrements('id');
  • $table->increments('id');
  • $table->mediumIncrements('id');
  • $table->bigIncrements('id');

それぞれ、MariaDBMySQL)の型

  • TINYINT : unsignedの場合は「0 ~ 255」
  • SMALLINT: unsignedの場合は 「0 ~ 65,535」
  • MEDIUMINT:unsignedの場合は「 0 ~ 16,777,215」
  • INT: unsignedの場合は「 0 ~  4,294,967,295」
  • BIGINT:  unsignedの場合は「 0 ~ 18,446,744,073,709,551,615」

 のIDカラムを生成します。

INTで約43億レコード、BIGINTだと約1845京!!。

まあ、あふれる前にシステムが動かなくなりますね。(笑)

 

整数の範囲

 

整数のUNSIGNEDの場合が

  • $table->unsignedTinyInteger('unsigned_tiny_int_col');
  • $table->unsignedSmallInteger('unsigned_small_int_col');
  • $table->unsignedMediumInteger('unsigned_medium_int_col');
  • $table->unsignedInteger('unsigned_integer_col');
  • $table->unsignedBigInteger('unsigned_big_int_col');

です。

有効範囲は上記と同じです。

つまり。

MariaDBMySQL)の型

  • TINYINT : unsignedの場合は「0 ~ 255」
  • SMALLINT: unsignedの場合は 「0 ~ 65,535」
  • MEDIUMINT:unsignedの場合は「 0 ~ 16,777,215」
  • INT: unsignedの場合は「 0 ~  4,294,967,295」
  • BIGINT:  unsignedの場合は「 0 ~ 18,446,744,073,709,551,615」

ですね。

対して、「signed」の場合がこちらで

  • $table->tinyInteger('tiny_integer_col');
  • $table->smallInteger('small_integer_col');
  • $table->mediumInteger('midium_integer_col');
  • $table->integer('integer_col');
  • $table->bigInteger('big_integer_col');

有効範囲は以下のとおり。

  • TINYINT : signedの場合は「 -128 ~  127」
  • SMALLINT: signedの場合は 「 -32,768 ~ 32,767」
  • MEDIUMINT:signedの場合は「-8,388,608 ~ 8,388,607」
  • INT: signedの場合は「 -2,147,483,648  ~  2,147,483,647」
  • BIGINT:  signedの場合は「 -9,223,372,036,854,775,808  ~ 9,223,372,036,854,775,807.」

です。

 

浮動小数点数固定小数点数

 

小数点以下の値があるかえる数字としては。

  • $table->decimal('decimal_col', 8, 2);
  • $table->unsignedDecimal('unsigned_decimal_col', 8, 2);
  • $table->float('float_col', 8, 2);
  • $table->double('double_col', 8, 2);

があります。

それぞれMariaDBMySQL)の以下の型に対応してます。

  • DECIMAL:固定小数点 整数部65ケタ・少数部30ケタ位。
  • FLOAT: 浮動小数
  • DOUBLE: 浮動小数点 

itmanabi.com

使い分けは重要です。

お金の計算とか「正確な数字」が必要な場合は「DECIMAL」一択です。

FLOAT・DOUBLE共近似値で「不正確な数字」になるので、お金の計算などには使えません。

 

チェックボックスラジオボタンに対応するBoolean

 

TRUE・FALSEとかON・OFFなどの二値しかないものについては、一択です。

$table->boolean('boolean_col');

これもMariaDBにも「BOOLEAN」という型があって、それに対応するわけなのですが、実態としては「TINYINT(1)」です。

 

UUIDに関連するもの

 

UUIDは「Universally Unique Identifier」の略で「ソフトウェア上でオブジェクトを、将来にわたって重複や偶然の一致が起こらないという前提で使うための一意に識別できるID」のことです。

もう少し正確に言えば、「重複する可能性はゼロではないが、ほぼ無視できるくらいに小さい可能性だから重複しないことにして使っても良いと考えられているID」なんですけどね。

ja.wikipedia.org

これに関連するカラムには、ダイレクトに「uuid」となっているものと、「morphs」みたいに「uuid」をキーにした複数のカラムを生成するようなものもあります。

  • $table->uuid('uuid_col');
  • $table->morphs('morphs_col');
  • $table->nullableMorphs('nullable_morphs_col');
  • $table->uuidMorphs('uuid_morphs_col');
  • $table->nullableUuidMorphs('nullable_uuid_morphs_col');

このUUIDは例えばiPhoneみたいな携帯電話の個体識別番号とか、何かのトランザクションの追跡(生産物の流通経路保証とか)みたいに、大量のユニークIDが必要で、かつ連番みたいに番号から全体量が推測されるようなことを防ぎたい・・みたいな用途には最適です。

なので大規模なシステムだと、結構使いどころはあるでしょうね。

 

日付・時刻に対応するカラム定義

 

日付・時刻に対応するのは以下です。

  • $table->date('date_col');
  • $table->dateTime('date_time_col');
  • $table->dateTimeTz('date_time_tz_col');
  • $table->year('year_col');
  • $table->time('time_col');
  • $table->timeTz('time_tz_col');
  • $table->timestamp('timestamp_col');
  • $table->timestampTz('timestamp_tz_col');

目につくのは「Tz」付きと、そうでないのがあることです。

Tzがついているのは「タイムゾーン」付きです。

タイムゾーンは「同じ標準時を利用する地域や区分」のことで、世界中の各地域間で発生しうる時差を、イギリスのグリニッジ天文台の基準時刻との差で表す標準時を利用して、混乱がおきないように調整する仕組みです。

まあ。

自分みたいに、日本で使うアプリケーションしか作らない人間には、あまり関係がなく、実際にタイムゾーン付きのカラム定義も使ったことはないので、あまり偉そうに書けません(笑)。

 

文字列を扱うカラム

 

文字列を扱う型としては以下のようなものがあります。

  • $table->char('char_100_col', 100);
  • $table->string('string_col', 100);
  • $table->text('text_col');
  • $table->mediumText('medium_text_col');
  • $table->longText('long_text_col');

各カラム定義に対応するMariaDBMySQL)の型はこんな感じです。

  • $table->char => CHAR(右側を空白で埋める固定幅文字列)
  • $table->string => VARCHAR(可変長文字列 utf8でMAX21,844文字)
  • $table->text -> TEXT(MAX 65,535文字)
  • $table->mediumText => MEDIUMTEXT(MAX 16,777,215文字) 
  • $table->longText => LONGTEXT(MAX 4,294,967,295文字 又は 4GB)

 まあ、これを見て適切な型を探せばよいと思います。

たぶん。

一番汎用的に使うのはVARCHARなので、迷ったら「$table->string」ですかね。

それで、もっと大容量の文字列が必要になったら「$table->mediumText」くらいを選択肢として考える感じでしょうか。

あと、文字列タイプでも、ちょっと特殊なもの

  • $table->json('json_col');
  • $table->jsonb('json_b_col');
  • $table->set('set_color_col', ['red', 'blue', 'green']);
  • $table->enum('enum_color_col', ['red', 'blue', 'green']);

があります。

それぞれMariaDBMySQL)では以下の型になります。

  • $table->json => LONGTEXT
  • $table->jsonb => LONGTEXT
  • $table->set => SET(最大 64個の値のリストを持てる型)
  • $table->enum => ENUM(論理上最大65,535個の値のリストを持てる型)

SETとENUMはリストを持てるという、ちょっと特殊な型です。

例えば、上記の例だと共に引数で与えた「'red', 'blue', 'green']」の文字列はデフォルトとしてセットされていました。

ここから一つ選ぶことができる・・って感じみたいです。

なるほど・・ですね。

 

バイナリを扱うカラム

 

 バイナリデータを扱うカラム定義としてはこれです。

  • $table->binary('binary_col');

これは、MariaDBMySQL)では以下の型に対応づけられます。

  • $table->binary => BLOB(バイナリ 最大長65,535バイト)

MariaDBMySQL)にはBLOBでもっと大きなバイナリデータを扱える型はあります。

  • MEDIUMBLOB(最大長16,777,215バイト)
  • LONGBLOB(最大長4,294,967,295 bytes or 4GB )

ですが、マイグレーションのカラム定義には、特にこれに対応するものは見当たりませんでしたけど・・。

自分が見落としたのか?、本当にないのか?・・はわかりません。

 

 Laravel(Eloquent ORM)特有のルールにそったカラム定義

 

単純に型に変換するのではなく、Laravel特有の機能で利用するためのカラムを生成するものがあります。

  • $table->softDeletes();
  • $table->rememberToken();
  • $table->timestamps();
  • $table->macAddress('mac_address_col');
  • $table->ipAddress('ip_address_col');

なんかがそうです。

 

$table->softDeletes();

 

実際には「deleted_at」というTIMESTAMP型のカラムになります。

このカラムを定義しておけば、ソフトデリートが使えるようになります。

ソフトデリートは、delete()コマンドを発行した時に、物理的に削除しないで、deleted_atに値をセットすることで「削除されたもの」とみなして使える機能です。

このページの「ソフトデリート」の箇所に詳しく書いてあります。

readouble.com

これは業務アプリケーションでは、わりとよく使う手法です。

物理的に削除してしまうと、操作ミスとかのリカバリが難しくなるので、ソフトデリートにしておいてリスクを減らすという考え方です。

だから、最初から仕組が用意してあるのはいいですね。

 

$table->rememberToken();

 

認証の機能をカスタマイズする場合に使います。

こちらに書いてあります。

readouble.com

引用すると。

users、もしくは同等の働きをするテーブルには、100文字のremember_token文字列カラムも含めてください。

このカラムはログイン時に、アプリケーションで"remember me"を選んだユーザーのトークンを保存しておくカラムとして使用されます。

ということです。

 

$table->timestamps();

 

これを実行すると「created_at」と「updated_at」という2つのTIMESTAMP型のカラムを生成します。

これがあると、save()を実行した時に自動的にあデータの作成・更新のタイムスタンプを記録してくれます。

 

その他

 

特有の・・ってほどではないですが。

「$table->macAddress('mac_address_col');」は、単純に、長さ17のVARCHARカラムとして、DBに定義されます。

同様に「$table->ipAddress('ip_address_col');」は、単純に長さ45のVARCHARカラムとしてDBに定義されます。

 

グラフィック系には便利そうなGeometry関連カラム 

 

なかなか特殊なカラムです。

MariaDBMySQLの「Geometry Types」に属する以下のものです。

  • $table->point('point_col');
  • $table->polygon('polygon_col');
  • $table->multiPoint('multi_point_col');
  • $table->lineString('line_string_col');
  • $table->multiLineString('multi_line_string_col');
  • $table->multiPolygon('multi_polygon_col');
  • $table->geometry('geometry_col');
  • $table->geometryCollection('geometry_collection_col');

これらは、MariaDBMySQL)の「Geometry Types」の以下の型に対応します。

  • $table->point => POINT
  • $table->lineString => LINESTRING
  • $table->polygon => POLYGON
  • $table->multiPoint => MULTIPOINT
  • $table->multiLineString => MULTILINESTRING
  • $table->multiPolygon => MULTIPOLYGON
  • $table->geometry => GEOMETRY
  • $table->geometryCollection => GEOMETRYCOLLECTION

Geometryは「幾何学」とか「形状」の意味を持つ言葉です。

グラフィック系のプログラミングでは画像を描画するために、その構成要素である、点(ポイント)・線(ライン)・多角形の面(ポリゴン)の座標を管理する必要があるのですが、それらの「形状」の構成要素の保存に使う・・とか。

機械学習なんかでは、データをベクトル(行列かな)で保持する必要がありますが、それらをそのまま保持するとか・・。

まあ、自分もまだ使ったことがないので、推測ですが(笑) 

 

まとめ

 

駆け足ですが、ざっとまとめてみました。

整理しながら、自分でも勘違いしていたこととかに気づけたりして、有益でした。

やっぱり、マイグレーションした時に、DBにどう反映するのかを知っていると安心して使えるかな・・と思うわけです。

今回はこんなところで。

ではでは。