知っておきたい!MariaDB日付・時刻型 代替格納方法のメリット・デメリット
MariaDBにおける日付と時刻のデータ型
MariaDBには、日付、時刻、またはその両方の情報を格納するために設計された特別なデータ型がいくつかあります。これらのデータ型は、情報の種類と精度に応じて適切に選択することが重要です。
以下に主要な日付と時刻のデータ型を説明します。
-
- 用途
日付(年、月、日)のみを格納します。時刻情報は含まれません。 - 形式
'YYYY-MM-DD'
- 範囲
'1000-01-01'
から'9999-12-31'
- 例
'2023-10-27'
- 用途
-
TIME
- 用途
時刻(時、分、秒)のみを格納します。日付情報は含まれません。 - 形式
'HH:MM:SS'
または'HHH:MM:SS'
(より大きな時間間隔のため) - 範囲
'-838:59:59'
から'838:59:59'
(これは時間間隔を表すため、24時間を超える値も可能です) - 例
'14:30:00'
,'-01:00:00'
- 用途
-
DATETIME
- 用途
日付と時刻の両方を格納します。 - 形式
'YYYY-MM-DD HH:MM:SS'
- 範囲
'1000-01-01 00:00:00'
から'9999-12-31 23:59:59'
- 例
'2023-10-27 14:30:00'
- 注意点
DATETIME
はタイムゾーン情報を持っていません。サーバーのタイムゾーン設定に依存します。
- 用途
-
TIMESTAMP
- 用途
日付と時刻の両方を格納しますが、DATETIME
と異なり、タイムゾーンの影響を受けます。一般的に、協定世界時 (UTC) で格納され、取得時にはセッションのタイムゾーンに変換されます。 - 形式
'YYYY-MM-DD HH:MM:SS'
- 範囲
'1970-01-01 00:00:01'
UTC から'2038-01-19 03:14:07'
UTC (Unixエポックからの秒数で表現されるため、この範囲になります。これはUnixエポックの問題として知られています) - 例
'2023-10-27 14:30:00'
- 注意点
*TIMESTAMP
カラムは、行が挿入または更新されたときに自動的に現在の日時を設定するように設定できます。これは、レコードの作成日時や更新日時を記録するのに非常に便利です。DATETIME
よりも省スペースです。
- 用途
-
YEAR
- 用途
年のみを格納します。 - 形式
2桁または4桁の形式で表示されます。- 4桁形式:
'YYYY'
(例:'2023'
) - 2桁形式:
'YY'
(例:'23'
)。ただし、内部的には4桁で解釈されます(70-99
は1970-1999
、00-69
は2000-2069
)。
- 4桁形式:
- 範囲
'1901'
から'2155'
, および'0000'
- 例
'2023'
- 用途
- 年のみが必要な場合
YEAR
- タイムゾーンを考慮し、自動更新機能が必要な場合、またはUnixエポック以降の日付を扱う場合
TIMESTAMP
- タイムゾーンを考慮しない日付と時刻が必要な場合
DATETIME
- 時刻のみが必要な場合
TIME
- 日付のみが必要な場合
DATE
MariaDBで日付や時刻のデータ型を扱う際には、いくつかの一般的な問題に遭遇することがあります。ここでは、よくあるエラーとその解決策について説明します。
不正な日付・時刻形式のエラー (Incorrect datetime value / Data truncated)
-
トラブルシューティング
- 形式の確認
使用しているデータ型の厳密な形式 (YYYY-MM-DD
,HH:MM:SS
,YYYY-MM-DD HH:MM:SS
) に従って値を指定しているか確認してください。 - 有効な日付/時刻
月や日の値がその月や暦において有効なものであるか確認してください(例: 2月は28日または29日まで)。 - 文字列リテラル
日付/時刻の値は、必ずシングルクォーテーションで囲まれた文字列リテラルとして提供する必要があります。 - アプリケーションレベルでのフォーマット
アプリケーション(PHP, Python, Javaなど)からデータを挿入する場合、データベースに渡す前に適切な形式にフォーマットする関数を使用してください(例: PHPのdate()
関数、Pythonのstrftime()
)。 - STR_TO_DATE() 関数
もし入力データが様々な形式で提供される可能性がある場合、MariaDBのSTR_TO_DATE(str, format)
関数を使って、指定したフォーマット文字列に基づいて文字列を日付値に変換することができます。INSERT INTO my_table (my_date_col) VALUES (STR_TO_DATE('27-10-2023', '%d-%m-%Y'));
- 形式の確認
-
エラーメッセージの例
ERROR 1292 (22007): Incorrect datetime value: '2023/10/27' for column 'my_date_col' at row 1
Warning (Code 1265): Data truncated for column 'my_time_col' at row 1
(部分的にしか認識できない場合など)
-
DATE
,TIME
,DATETIME
,TIMESTAMP
カラムに、MariaDBが認識できない形式の値を挿入しようとした場合。- 例:
INSERT INTO my_table (my_date_col) VALUES ('2023/10/27');
(正しい形式はYYYY-MM-DD
) - 存在しない日付(例: 2月30日)を挿入しようとした場合。
TIMESTAMPカラムの自動更新に関する予期せぬ挙動
-
トラブルシューティング
- DEFAULTとON UPDATEの確認
- カラム定義を確認し、
DEFAULT CURRENT_TIMESTAMP
やON UPDATE CURRENT_TIMESTAMP
が設定されているか確認します。 - 特定のカラムを自動更新させたくない場合は、これらの属性を削除するか、
DATETIME
型を検討してください。
-- 例: 自動更新を削除する場合 (ALTER TABLEで変更) ALTER TABLE my_table MODIFY COLUMN created_at TIMESTAMP; -- DEFAULTとON UPDATEがない状態
- カラム定義を確認し、
- NULL許容の確認
TIMESTAMP
カラムがNULL
を許可しない(NOT NULL
)場合、値を指定せずに挿入しようとするとエラーになります。明示的にNULL
を挿入したい場合は、カラム定義でNULL
を許可するようにします。CREATE TABLE example ( id INT PRIMARY KEY, ts_col TIMESTAMP NULL );
- DEFAULTとON UPDATEの確認
-
エラーの状況
TIMESTAMP
カラムは、デフォルトでCURRENT_TIMESTAMP
を設定したり、行の更新時に自動的に更新されるように設定できます。この挙動が予期せぬ結果を引き起こすことがあります。- 例えば、
ON UPDATE CURRENT_TIMESTAMP
が設定されているカラムが、意図しないカラムの更新でも変更されてしまう。 TIMESTAMP
がデフォルトでNULL
を許可しないのにNULL
を挿入しようとした場合。
タイムゾーンの不一致による日付・時刻のずれ (TIMESTAMP特有)
-
トラブルシューティング
- タイムゾーン設定の確認
- MariaDBサーバーのタイムゾーン
SELECT @@global.time_zone, @@session.time_zone;
で確認します。サーバーのmy.cnf
でdefault_time_zone
を設定できます。 - クライアント(セッション)のタイムゾーン
接続文字列やSET time_zone = '...'
コマンドで設定できます。アプリケーションが接続したときに特定のタイムゾーンを設定するようにしてください。 - TIMESTAMPの動作理解
TIMESTAMP
は内部的にUTCで格納され、表示時にはセッションのタイムゾーンに変換されます。異なるタイムゾーンのクライアントからアクセスすると、それぞれ異なる時刻として表示されます。
- MariaDBサーバーのタイムゾーン
- 一貫性の確保
- 理想的には、サーバー、データベース接続、アプリケーションのタイムゾーン設定を統一するか、少なくともその違いを完全に理解して処理するようにします。
DATETIME
型はタイムゾーンの影響を受けないため、タイムゾーンの問題を完全に回避したい場合はDATETIME
の使用も検討します(ただし、タイムゾーンの概念自体が不要な場合に限る)。
- UTCでの統一
アプリケーション側でもデータをUTCで処理し、表示時のみユーザーのローカルタイムゾーンに変換するという方式が、タイムゾーン問題を最もシンプルに解決する一般的なアプローチです。
- タイムゾーン設定の確認
-
エラーの状況
TIMESTAMP
型を使用している場合、データを挿入した時と取得した時で、表示される時刻が異なることがあります。これは、クライアント(アプリケーション)のタイムゾーン、MariaDBサーバーのタイムゾーン、およびTIMESTAMP
カラムの内部的なUTC格納の組み合わせによって発生します。
YEAR型における2桁の年の解釈
-
トラブルシューティング
- 4桁の年を使用
常に4桁の年(例:'2023'
)を挿入することをお勧めします。これにより、曖昧さを完全に排除できます。 - 内部的な解釈の理解
もし2桁の年を挿入する必要がある場合は、MariaDBの内部的な解釈ルールを正確に理解し、それに基づいてデータを用意してください。
- 4桁の年を使用
-
エラーの状況
YEAR(2)
形式で2桁の年を入力した際に、予期せぬ4桁の年に解釈されることがあります。- MariaDBは
00-69
を2000-2069
、70-99
を1970-1999
として解釈します。これが意図と異なる場合があります。
比較やソートの予期せぬ挙動
-
トラブルシューティング
- 適切なデータ型の使用
日付や時刻を扱う場合は、必ずDATE
,TIME
,DATETIME
,TIMESTAMP
のいずれかのデータ型を使用してください。これにより、データベースはそれらを日付/時刻として正しく認識し、比較やソートも意図通りに行われます。 - 型変換関数
やむを得ず文字列として格納されている場合でも、CAST()
やSTR_TO_DATE()
関数を使って比較時に型変換を行うことで、正しい結果を得られる場合があります。-- 例: 文字列を日付としてソート SELECT * FROM my_table ORDER BY STR_TO_DATE(string_date_col, '%Y-%m-%d');
- 適切なデータ型の使用
-
エラーの状況
- 日付・時刻カラムを文字列として格納している場合や、異なる形式の文字列を比較しようとした場合、辞書順ソートになり、日付/時刻として正しくソートされないことがあります。
- 例:
'2023-10-01'
と'2023-9-15'
を文字列として比較すると'2023-9-15'
が先にくる(数値としてではなく)。
MariaDBで日付や時刻のデータを扱う際には、主にSQLクエリを使用して操作を行います。ここでは、各データ型のカラムの作成、データの挿入、取得、そして日付/時刻関数を使った操作の例を示します。
テーブルの作成
まず、各日付・時刻データ型を含むテーブルを作成します。
CREATE TABLE event_logs (
id INT AUTO_INCREMENT PRIMARY KEY,
event_name VARCHAR(255) NOT NULL,
event_date DATE, -- 日付のみ
event_time TIME, -- 時刻のみ
event_datetime DATETIME, -- 日付と時刻 (タイムゾーン非依存)
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 作成日時 (自動設定、タイムゾーン考慮)
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- 更新日時 (自動更新、タイムゾーン考慮)
event_year YEAR -- 年のみ
);
解説
event_year
:YEAR
型。4桁の年を格納します。updated_at
:TIMESTAMP
型。DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
により、行が挿入されたときと更新されたときに自動的に現在の日時が設定されます。created_at
:TIMESTAMP
型。DEFAULT CURRENT_TIMESTAMP
により、行が挿入されたときに自動的に現在の日時が設定されます。event_datetime
:DATETIME
型。'YYYY-MM-DD HH:MM:SS'
形式で日付と時刻を格納します。event_time
:TIME
型。'HH:MM:SS'
形式で時刻を格納します。event_date
:DATE
型。'YYYY-MM-DD'
形式で日付を格納します。
データの挿入
作成したテーブルにデータを挿入します。
-- 明示的に値を指定して挿入
INSERT INTO event_logs (event_name, event_date, event_time, event_datetime, event_year)
VALUES (
'Meeting Start',
'2023-01-15',
'10:00:00',
'2023-01-15 10:00:00',
'2023'
);
-- 現在の日時/時刻を利用して挿入
-- created_at と updated_at は自動的に設定されます
INSERT INTO event_logs (event_name, event_date, event_time, event_datetime, event_year)
VALUES (
'Report Generation',
CURDATE(), -- 現在の日付
CURTIME(), -- 現在の時刻
NOW(), -- 現在の日付と時刻
YEAR(NOW()) -- 現在の年
);
-- 不正な形式の例 (エラーまたは警告になる可能性があります)
-- INSERT INTO event_logs (event_date) VALUES ('Jan 1, 2023'); -- エラー
解説
YEAR(NOW())
:NOW()
から年を抽出します。NOW()
: 現在の日付と時刻を返します。DATETIME
型とTIMESTAMP
型に利用できます。CURTIME()
: 現在の時刻を返します。CURDATE()
: 現在の日付を返します。
データの取得
挿入したデータを取得します。
-- すべてのログを取得
SELECT * FROM event_logs;
-- 特定のイベント日付のログを取得
SELECT * FROM event_logs WHERE event_date = '2023-01-15';
-- 特定の時間範囲のログを取得
SELECT * FROM event_logs WHERE event_time BETWEEN '09:00:00' AND '12:00:00';
-- 特定のタイムスタンプ範囲のログを取得
SELECT * FROM event_logs WHERE created_at BETWEEN '2023-01-01 00:00:00' AND '2023-12-31 23:59:59';
日付・時刻関数を使った操作
MariaDBには、日付や時刻を操作するための多くの組み込み関数があります。
日付/時刻の抽出
-- 各日付/時刻カラムから年、月、日、時、分、秒を抽出
SELECT
event_name,
YEAR(event_datetime) AS year_val,
MONTH(event_datetime) AS month_val,
DAY(event_datetime) AS day_val,
HOUR(event_datetime) AS hour_val,
MINUTE(event_datetime) AS minute_val,
SECOND(event_datetime) AS second_val
FROM
event_logs;
-- 曜日を取得 (1=日曜日, 2=月曜日, ...)
SELECT event_name, DAYOFWEEK(event_date) AS day_of_week FROM event_logs;
-- 週番号を取得
SELECT event_name, WEEK(event_date) AS week_number FROM event_logs;
日付/時刻のフォーマット
DATE_FORMAT()
関数を使って、日付や時刻を指定した形式で出力できます。
-- DATETIMEを'YYYY年MM月DD日 HH時MM分'形式で表示
SELECT
event_name,
DATE_FORMAT(event_datetime, '%Y年%m月%d日 %H時%i分') AS formatted_datetime
FROM
event_logs;
-- DATEを'月/日/年'形式で表示
SELECT
event_name,
DATE_FORMAT(event_date, '%m/%d/%Y') AS formatted_date
FROM
event_logs;
-- TIMEを'HH:MM AM/PM'形式で表示
SELECT
event_name,
DATE_FORMAT(event_time, '%h:%i %p') AS formatted_time
FROM
event_logs;
DATE_FORMATの主なフォーマット指定子
%a
: 曜日の短縮名 (Sun, Mon, ...)%W
: 曜日のフルネーム (Sunday, Monday, ...)%p
: AM/PM%s
,%S
: 00-59の秒%i
: 00-59の分%h
: 01-12の時%H
: 00-23の時%e
: 1-31の日%d
: 01-31の日%c
: 1-12の月%m
: 01-12の月%y
: 2桁の年%Y
: 4桁の年
日付/時刻の加算・減算
DATE_ADD()
(ADDDATE()
) や DATE_SUB()
(SUBDATE()
) を使って、日付や時刻に期間を加算・減算できます。
-- イベント日時から1時間30分後を計算
SELECT
event_name,
event_datetime,
DATE_ADD(event_datetime, INTERVAL '1:30' HOUR_MINUTE) AS datetime_plus_1h30m
FROM
event_logs
WHERE
event_name = 'Meeting Start';
-- イベント日付から7日後を計算
SELECT
event_name,
event_date,
DATE_ADD(event_date, INTERVAL 7 DAY) AS date_plus_7_days
FROM
event_logs
WHERE
event_name = 'Meeting Start';
-- 作成日時から30分前を計算
SELECT
event_name,
created_at,
DATE_SUB(created_at, INTERVAL 30 MINUTE) AS created_at_minus_30m
FROM
event_logs
WHERE
event_name = 'Report Generation';
文字列から日付/時刻への変換
STR_TO_DATE()
関数を使って、様々な形式の文字列を日付/時刻型に変換できます。
-- '2023年05月20日' という文字列をDATE型に変換して挿入
INSERT INTO event_logs (event_name, event_date)
VALUES ('Custom Date', STR_TO_DATE('2023年05月20日', '%Y年%m月%d日'));
-- '12/25/2024 10:30:00 PM' という文字列をDATETIME型に変換
SELECT STR_TO_DATE('12/25/2024 10:30:00 PM', '%m/%d/%Y %h:%i:%s %p') AS converted_datetime;
プログラミング言語からの利用例 (Pythonの例)
MariaDBに接続するプログラミング言語(Python, PHP, Javaなど)からは、通常、各言語のデータベースドライバを使って日付/時刻データを扱います。多くの場合、日付/時刻オブジェクトとして取得・設定できます。
Python (PyMySQL/mysql-connector-pythonなどを使用)
import pymysql
from datetime import date, time, datetime
# データベース接続情報
db_config = {
'host': '127.0.0.1',
'user': 'your_user',
'password': 'your_password',
'database': 'test_db',
'charset': 'utf8mb4',
'cursorclass': pymysql.cursors.DictCursor # 辞書形式で結果を取得
}
try:
connection = pymysql.connect(**db_config)
with connection.cursor() as cursor:
# データの挿入
sql_insert = """
INSERT INTO event_logs (event_name, event_date, event_time, event_datetime, event_year)
VALUES (%s, %s, %s, %s, %s)
"""
data_to_insert = (
'Python Insert Event',
date(2024, 6, 6), # Pythonのdateオブジェクト
time(15, 30, 0), # Pythonのtimeオブジェクト
datetime(2024, 6, 6, 15, 30, 0), # Pythonのdatetimeオブジェクト
2024
)
cursor.execute(sql_insert, data_to_insert)
connection.commit()
print("データを挿入しました。")
# データの取得
sql_select = "SELECT id, event_name, event_date, event_time, event_datetime, created_at, updated_at, event_year FROM event_logs"
cursor.execute(sql_select)
results = cursor.fetchall()
print("\n取得したデータ:")
for row in results:
print(f"ID: {row['id']}, 名前: {row['event_name']}, 日付: {row['event_date']}, 時刻: {row['event_time']}, 日時: {row['event_datetime']}, 作成日時: {row['created_at']}, 更新日時: {row['updated_at']}, 年: {row['event_year']}")
# 取得したデータはPythonのdatetime.date, datetime.time, datetime.datetimeオブジェクトとして扱える
print(f" 型 (event_date): {type(row['event_date'])}, 型 (event_datetime): {type(row['event_datetime'])}")
# 日付/時刻関数を使った取得 (例: フォーマット)
sql_formatted = """
SELECT
event_name,
DATE_FORMAT(event_datetime, '%Y/%m/%d %H:%i:%S') AS formatted_dt
FROM
event_logs
WHERE
event_name = 'Python Insert Event'
"""
cursor.execute(sql_formatted)
formatted_result = cursor.fetchone()
if formatted_result:
print(f"\nフォーマットされた日時: {formatted_result['formatted_dt']}")
finally:
if 'connection' in locals() and connection.open:
connection.close()
- SQL関数(
DATE_FORMAT
など)を使ってフォーマットした結果は、通常は文字列としてPythonに返されます。 - データベースから日付/時刻データを取得する際も、多くの場合、Pythonの対応する
datetime
オブジェクトとして返されます。 - Pythonの
datetime
モジュール(date
,time
,datetime
クラス)のオブジェクトを直接データベースドライバに渡すことができます。ドライバがそれをMariaDBの適切な形式に変換してくれます。
MariaDBで日付と時刻のデータを扱う際には、標準的なデータ型(DATE
, TIME
, DATETIME
, TIMESTAMP
, YEAR
)が最も推奨されますが、特定のユースケースや既存のシステムとの互換性のために、代替の方法が用いられることがあります。
これらの代替方法は、通常、標準的なデータ型を使用するよりもデメリット(パフォーマンス、データの整合性、使いやすさなど)が大きいため、特別な理由がない限り推奨されません。しかし、知識として知っておくことは重要です。
文字列型 (VARCHAR, TEXT) として格納する
日付や時刻を文字列(例: '2023-10-27 14:30:00'
や 'October 27, 2023'
)として格納する方法です。
- 使用を検討するケース
- データが非常に少なく、日付/時刻操作がほとんど必要ない場合。
- 異なる形式の日付/時刻文字列をそのまま保存し、後でアプリケーション側でパースする場合。
- 欠点
- データの整合性
MariaDBは、格納されている文字列が有効な日付や時刻であるかを検証しません。不正なデータ(例:'2023-02-30'
)が格納されるリスクがあります。 - パフォーマンス
日付や時刻の比較、ソート、範囲検索を行う場合、データベースは文字列として処理するため、専用のデータ型に比べて非常に遅くなります。インデックスも効率的に機能しません。 - クエリの複雑さ
日付計算(例: 「3日後」)を行うには、STR_TO_DATE()
で日付型に変換してから計算し、またDATE_FORMAT()
で文字列に戻すなど、複雑なSQL関数を多用する必要があります。 - ストレージ効率
日付型よりも多くのストレージを消費する場合があります(特に短い日付/時刻の場合)。
- データの整合性
- 利点
- 非常に柔軟な形式でデータを格納できます。
- 異なるデータベースシステムへの移行が比較的容易な場合があります(ただし、形式が統一されている前提)。
例
CREATE TABLE event_logs_varchar (
id INT AUTO_INCREMENT PRIMARY KEY,
event_name VARCHAR(255) NOT NULL,
event_datetime_str VARCHAR(50) -- 日付と時刻を文字列として格納
);
INSERT INTO event_logs_varchar (event_name, event_datetime_str)
VALUES ('Event A', '2023-10-27 14:30:00');
INSERT INTO event_logs_varchar (event_name, event_datetime_str)
VALUES ('Event B', 'Oct 27, 2023 2:30 PM'); -- 異なる形式も格納可能だが、後で問題になる
-- 検索例 (パフォーマンスに問題あり、STR_TO_DATE() を使用して比較することが推奨される)
SELECT * FROM event_logs_varchar WHERE event_datetime_str > '2023-01-01 00:00:00';
数値型 (INT, BIGINT) として格納する
日付や時刻をUnixタイムスタンプ(Unixエポック 1970-01-01 00:00:00 UTC
からの秒数)や、YYYYMMDD
形式の整数として格納する方法です。
Unixタイムスタンプ(秒数)として格納する
- 使用を検討するケース
TIMESTAMP
型の範囲を超える非常に古い、または新しい日付を扱いたいが、日付計算は必要ない場合(BIGINT
を使用)。- タイムゾーン管理を厳密に行いたいが、MariaDBの
TIMESTAMP
型の挙動が要件に合わない場合。 - データ量が多く、パフォーマンスが最優先される場合。
- 欠点
- 人間が読み取りにくい。データを直接見ても意味が分かりません。
- アプリケーション側で日付/時刻オブジェクトへの変換(Unixタイムスタンプからの変換)が必要です。
TIMESTAMP
型と同様に、Unixエポックの問題(2038年問題)に直面する可能性があります(INT
型の場合)。
- 利点
- タイムゾーンの問題をある程度管理しやすい(通常はUTCで格納)。
- 数値なので比較やソートが高速。範囲検索も効率的。
- ストレージ効率が良い(
INT
で4バイト、BIGINT
で8バイト)。
例
CREATE TABLE event_logs_int (
id INT AUTO_INCREMENT PRIMARY KEY,
event_name VARCHAR(255) NOT NULL,
event_unix_timestamp INT UNSIGNED -- Unixタイムスタンプ (秒)
);
-- 現在のUnixタイムスタンプを取得し挿入
INSERT INTO event_logs_int (event_name, event_unix_timestamp)
VALUES ('Event C', UNIX_TIMESTAMP(NOW()));
-- 特定の日時のUnixタイムスタンプを計算し挿入
INSERT INTO event_logs_int (event_name, event_unix_timestamp)
VALUES ('Event D', UNIX_TIMESTAMP('2023-10-27 14:30:00'));
-- 取得時に日付/時刻形式に変換
SELECT
id,
event_name,
FROM_UNIXTIME(event_unix_timestamp) AS event_datetime_readable
FROM
event_logs_int;
-- 検索例
SELECT * FROM event_logs_int WHERE event_unix_timestamp > UNIX_TIMESTAMP('2023-01-01 00:00:00');
YYYYMMDD や HHMMSS 形式の整数として格納する
- 使用を検討するケース
- レガシーシステムとの互換性が必要な場合。
- 日付や時刻を純粋な数値として扱いたい非常に特殊なケース。
- 欠点
- 日付計算が非常に複雑になる(数値演算で日数を足し引きするのは困難)。
- 存在しない日付(例: 2月30日)が格納される可能性がある。
- SQL関数(
DATE_FORMAT
,STR_TO_DATE
など)との連携が悪い。
- 利点
- 人間が若干読み取りやすい。
- 数値なのでソートは可能。
CREATE TABLE event_logs_num_date (
id INT AUTO_INCREMENT PRIMARY KEY,
event_name VARCHAR(255) NOT NULL,
event_date_int INT, -- 例: 20231027
event_time_int INT -- 例: 143000
);
INSERT INTO event_logs_num_date (event_name, event_date_int, event_time_int)
VALUES ('Event E', 20231027, 143000);
-- 検索例 (文字列に変換して比較するなど、複雑になりがち)
SELECT * FROM event_logs_num_date WHERE event_date_int > 20230101;
代替方法 | 利点 | 欠点 | 推奨度 |
---|---|---|---|
文字列型 | 柔軟なフォーマット | データ整合性、パフォーマンス、クエリの複雑さ、ストレージ効率 | 低 |
Unixタイムスタンプ | タイムゾーン管理、高速な比較・ソート、ストレージ効率 | 人間が読み取りにくい、2038年問題(INTの場合)、アプリでの変換必須 | 中 |
YYYYMMDD整数 | 若干読みやすい、ソート可能 | 日付計算の困難さ、データ整合性、SQL関数との連携性 | 低 |