リモート開発メインのソフトウェア開発企業のエンジニアブログです

Rails のマイグレーションで PostgreSQL の timestamp(0) 型のカラムを作る

タイトル通りですが、Ruby on Rails のマイグレーションで、PostgreSQL の timestamp(0) with time zone 型のカラムを作成する方法を紹介します。普通にやると timestamp with time zone 型になってしまいます。

やり方

まずはやり方ですが、以下のようなマイグレーションファイルを作成し、普通に実行すれば良いです。

class AddColumn1ToTable1 < ActiveRecord::Migration[6.0]
  def change
    change_table :table1 do |t|
      t.datetime :column1, precision: 0
    end
  end
end

解説・補足

0 って何?

そもそも、 timestamp(0) の「0」って何かというと、(上のマイグレーションファイルを見れば想像つくかと思いますが)精度です。以下、PostgreSQL のドキュメントから引用します。

ここで、オプションである精度の指定 p は秒フィールドの小数点以下の桁数に一致した整数です。精度は time、timestamp、および interval に対して設定できます。

日付/時刻データ型

ちょっと日本語が分かりにくいので補足すると、

  • timestamp(0) は秒までの精度、つまり hh:mm:ss
  • timestamp(3) は秒以下、小数点3桁までの精度、つまり hh:mm:ss.sss という形でミリ秒までの精度

という感じです。

なぜ精度を指定したいか

なぜ精度を指定したいかという理由ですが、主に以下の2つの理由が考えられます。

  • 容量を節約
  • 他のアプリケーションとの互換性

前者ですが、精度が低く設定した方がその分データの容量が少なくなるため、レコード数が多いテーブルの場合などは必要な精度を指定した方が良いでしょう。

後者ですが、今回の件で調査しているときに、Laravel と Rails で同じ DB を共有する際に問題となり得る事を知りました(Rails、Laravel、DBMS の種類・バージョンによって、異なる問題がありました)。それらのうちのいくつかの問題を防ぐための方法として、精度を0に指定するというのが挙げられていました。

Rails 6 では、precision: 6 がデフォルトになった

Rails 6 では、precision: 6 がデフォルトになりました。日本語だと以下のページが参考になります。

なぜRails6.0でprecision: 6が追加されたのか? – Qiita

ちなみに、:precision が設定できるようになったのは、以下を見る限り Rails 4 からのようです。

Allow precision option for postgresql datetimes by tonywok · Pull Request #6821 · rails/rails

MySQL では 5.6.4 から小数点以下がサポートされるようになった

MySQL では、5.6.4 で timestamp 型などで小数点以下の精度がサポートされるようになりました。当初はデフォルトの精度は0ですが、その後しばらく経った後でにデフォルトが6に変更されています。

MySQL :: MySQL 5.6 Release Notes :: Changes in MySQL 5.6.4 (2011-12-20, Milestone 7)

まとめ

RDBMS の timestamp 型は(古い MySQL などを除き)小数点以下の値も保持できます。Rails のマイグレーションで timestamp 型のカラムを作ると、デフォルトでは precision: 6 (精度6桁)が設定されるので、小数点以下の6桁、つまりマイクロ秒まで保存できます。

ただ、秒より小さい値は必要無いユースケースも多いと思いますので、その場合は precision: 0 を明示的に指定することをお勧めします。

← 前の投稿

Laravel のフロントエンドビルドツールが Vite に変わった

次の投稿 →

macOS で Java を使う方法 ver. 2022

コメントを残す