Oracleデータベースでシステム日付(現在の日時)を取得するには、SYSDATE・SYSTIMESTAMP・CURRENT_DATEなどの関数を使います。
この記事では、それぞれの関数の違い、TO_CHARによるフォーマット変換、日付計算、PL/SQLでの活用法、タイムゾーンの注意点まで、実務で必要なパターンを網羅的に解説します。
この記事で学べること
- SYSDATEでシステム日付を取得する基本構文
- SYSTIMESTAMPでミリ秒・タイムゾーン付き日時を取得する方法
- CURRENT_DATE / CURRENT_TIMESTAMPとセッションタイムゾーンの関係
- TO_CHARで日付を任意のフォーマットに変換する方法
- 日付計算(加算・減算・TRUNC・月末取得)の実務パターン
- INSERT / UPDATEでのタイムスタンプ記録
- PL/SQLでの変数への格納と条件分岐
- EXTRACT関数で年・月・日・時を個別に取り出す方法
- INTERVAL型で日時を加算する方法
- よくあるエラーとFIXED_DATEによるテスト対策
SYSDATE関数の基本
SYSDATEは、Oracleで最もよく使われるシステム日付取得関数です。データベースサーバーのOS日時をDATE型で返します。
SQL
SELECT SYSDATE FROM DUAL;
実行結果
SYSDATE
-------------------
2025-03-05 14:30:22
SYSDATEのポイント
- 引数なし(括弧を付けない)
- 戻り値はDATE型(年月日 時分秒)
- データベースサーバーのOS時刻を返す(セッションのタイムゾーンは無関係)
- DUAL表を使って1行で取得するのが定番
SYSTIMESTAMP関数
SYSTIMESTAMPは、SYSDATEよりも高精度なシステム日時を取得する関数です。小数秒とタイムゾーンの情報も含まれます。
SQL
SELECT SYSTIMESTAMP FROM DUAL;
実行結果
SYSTIMESTAMP
--------------------------------------
2025-03-05 14:30:22.847362 +09:00
| 比較項目 |
SYSDATE |
SYSTIMESTAMP |
| 戻り値の型 |
DATE |
TIMESTAMP WITH TIME ZONE |
| 精度 |
秒まで |
小数秒(最大9桁) |
| タイムゾーン |
なし |
あり(+09:00等) |
| 基準時刻 |
DBサーバーのOS時刻 |
DBサーバーのOS時刻 |
ポイント:ログのタイムスタンプや処理時間の計測など、秒未満の精度が必要な場面ではSYSTIMESTAMPを使います。
CURRENT_DATE / CURRENT_TIMESTAMP
CURRENT_DATEとCURRENT_TIMESTAMPは、セッションのタイムゾーンに基づいた日時を返します。
SQL
-- セッションタイムゾーンを確認
SELECT SESSIONTIMEZONE FROM DUAL;
-- セッションのタイムゾーンに基づく日時
SELECT CURRENT_DATE AS curr_date,
CURRENT_TIMESTAMP AS curr_ts
FROM DUAL;
| 関数 |
戻り値の型 |
基準 |
用途 |
| SYSDATE |
DATE |
DBサーバーOS |
一般的な日時取得 |
| SYSTIMESTAMP |
TIMESTAMP WITH TZ |
DBサーバーOS |
高精度タイムスタンプ |
| CURRENT_DATE |
DATE |
セッションTZ |
ユーザーのローカル日時 |
| CURRENT_TIMESTAMP |
TIMESTAMP WITH TZ |
セッションTZ |
高精度ローカル日時 |
注意:DBサーバーが日本(JST)にあり、セッションタイムゾーンがUTCの場合、SYSDATEとCURRENT_DATEは9時間ずれます。タイムゾーンを意識しない環境ではSYSDATEで十分です。
タイムゾーンの違いを実感する
SYSDATEとCURRENT_DATEの違いをセッションタイムゾーンを変更して確認してみましょう。
タイムゾーンの違いを確認
-- セッションをUTCに変更
ALTER SESSION SET TIME_ZONE = 'UTC';
SELECT
SYSDATE AS sys_date, -- DBサーバーの時刻(JST)
CURRENT_DATE AS current_date_ -- セッションの時刻(UTC)
FROM DUAL;
実行結果(DBサーバーがJSTの場合)
SYS_DATE CURRENT_DATE_
------------------- -------------------
2025-03-05 14:30:22 2025-03-05 05:30:22 ← 9時間の差
TO_CHARで日付をフォーマットする
SYSDATEの結果を任意の書式で表示するには、TO_CHAR関数を使います。
よく使うフォーマット一覧
| 書式 |
SQL |
出力例 |
| 年月日 |
TO_CHAR(SYSDATE, 'YYYY/MM/DD') |
2025/03/05 |
| 年月日 時分秒 |
TO_CHAR(SYSDATE, 'YYYY/MM/DD HH24:MI:SS') |
2025/03/05 14:30:22 |
| 年月日(ハイフン) |
TO_CHAR(SYSDATE, 'YYYY-MM-DD') |
2025-03-05 |
| 年月(6桁) |
TO_CHAR(SYSDATE, 'YYYYMM') |
202503 |
| 年月日(8桁) |
TO_CHAR(SYSDATE, 'YYYYMMDD') |
20250305 |
| 時分秒のみ |
TO_CHAR(SYSDATE, 'HH24:MI:SS') |
14:30:22 |
| 曜日 |
TO_CHAR(SYSDATE, 'DY') |
水 |
| 和暦 |
TO_CHAR(SYSDATE, 'EEYY/MM/DD', 'NLS_CALENDAR='Japanese Imperial'') |
令和07/03/05 |
実行例
SELECT
TO_CHAR(SYSDATE, 'YYYY/MM/DD HH24:MI:SS') AS full_datetime,
TO_CHAR(SYSDATE, 'YYYYMMDD') AS date_key,
TO_CHAR(SYSDATE, 'DY') AS day_of_week
FROM DUAL;
関連: 【Oracle】日付フォーマットを変更する方法 / 【Oracle】日付を和暦で取得する方法
EXTRACT関数で年・月・日を取り出す
EXTRACT関数を使うと、日付から年・月・日・時・分・秒を個別に数値で取得できます。
EXTRACT関数の基本
SELECT
EXTRACT(YEAR FROM SYSDATE) AS yr, -- 2025
EXTRACT(MONTH FROM SYSDATE) AS mon, -- 3
EXTRACT(DAY FROM SYSDATE) AS dy -- 5
FROM DUAL;
実行結果
YR MON DY
---- ---- ---
2025 3 5
SYSTIMESTAMPから時・分・秒を取得
時分秒の取得
SELECT
EXTRACT(HOUR FROM SYSTIMESTAMP) AS hr,
EXTRACT(MINUTE FROM SYSTIMESTAMP) AS mi,
EXTRACT(SECOND FROM SYSTIMESTAMP) AS sec
FROM DUAL;
注意:HOUR・MINUTE・SECONDはTIMESTAMP型からのみ取得可能です。EXTRACT(HOUR FROM SYSDATE)はエラーになるため、SYSTIMESTAMPまたはCAST(SYSDATE AS TIMESTAMP)を使います。
EXTRACT vs TO_CHAR の使い分け
| 比較項目 |
EXTRACT |
TO_CHAR |
| 戻り値 |
NUMBER |
VARCHAR2 |
| 用途 |
数値で比較・計算する場合 |
書式付き文字列が欲しい場合 |
| 例 |
EXTRACT(MONTH FROM SYSDATE) = 3 |
TO_CHAR(SYSDATE, 'MM') = '03' |
ポイント:数値として条件分岐や計算に使う場合はEXTRACT、表示用の文字列が欲しい場合はTO_CHARを選びましょう。WHERE句での月指定にはEXTRACTが直感的です。
日付計算の実務パターン
日数の加算・減算
OracleのDATE型は日数の加減算が可能です。
日数の加算・減算
SELECT
SYSDATE AS today,
SYSDATE + 1 AS tomorrow, -- 明日
SYSDATE - 1 AS yesterday, -- 昨日
SYSDATE + 7 AS next_week, -- 1週間後
SYSDATE + 1/24 AS plus_one_hour -- 1時間後
FROM DUAL;
月の加算・減算(ADD_MONTHS)
月の操作
SELECT
ADD_MONTHS(SYSDATE, 1) AS next_month, -- 1ヶ月後
ADD_MONTHS(SYSDATE, -1) AS prev_month, -- 1ヶ月前
ADD_MONTHS(SYSDATE, 12) AS next_year -- 1年後
FROM DUAL;
日付の切り捨て(TRUNC)
TRUNCで日付を切り捨て
SELECT
TRUNC(SYSDATE) AS today_00, -- 今日の0:00:00
TRUNC(SYSDATE, 'MM') AS month_first, -- 月初
TRUNC(SYSDATE, 'Q') AS quarter_first, -- 四半期初
TRUNC(SYSDATE, 'YYYY') AS year_first -- 年初
FROM DUAL;
関連: 【Oracle】今日の0:00を取得する方法
月末の取得(LAST_DAY)
月末と残日数
SELECT
LAST_DAY(SYSDATE) AS month_end,
LAST_DAY(SYSDATE) - SYSDATE AS remaining_days
FROM DUAL;
関連: 【Oracle】月末を取得する方法
2つの日付間の差
日数差と月数差
SELECT
SYSDATE - TO_DATE('2025-01-01', 'YYYY-MM-DD') AS days_diff,
MONTHS_BETWEEN(SYSDATE, TO_DATE('2025-01-01', 'YYYY-MM-DD')) AS months_diff
FROM DUAL;
INTERVAL型で日時を加算する
Oracle 9i以降では、INTERVAL型を使って可読性の高い日時加算ができます。
INTERVAL型での加算
SELECT
SYSDATE + INTERVAL '1' DAY AS plus_1day,
SYSDATE + INTERVAL '2' HOUR AS plus_2hours,
SYSDATE + INTERVAL '30' MINUTE AS plus_30min,
SYSDATE - INTERVAL '90' SECOND AS minus_90sec
FROM DUAL;
数値加算との比較
| 目的 |
数値加算 |
INTERVAL |
| 1日後 |
SYSDATE + 1 |
SYSDATE + INTERVAL '1' DAY |
| 1時間後 |
SYSDATE + 1/24 |
SYSDATE + INTERVAL '1' HOUR |
| 30分後 |
SYSDATE + 30/1440 |
SYSDATE + INTERVAL '30' MINUTE |
| 90秒後 |
SYSDATE + 90/86400 |
SYSDATE + INTERVAL '90' SECOND |
ポイント:数値加算(+ 1/24)は簡潔ですが、INTERVAL型の方が意図が明確でコードレビュー時に読みやすくなります。チーム開発ではINTERVALがおすすめです。
INSERT / UPDATEでの活用
SYSDATEは登録日時や更新日時の記録に頻繁に使われます。
INSERT文でタイムスタンプを記録
登録日時をSYSDATEで記録
INSERT INTO audit_log (user_id, action, created_at)
VALUES (1001, 'LOGIN', SYSDATE);
UPDATE文で更新日時を記録
更新日時の記録
UPDATE employees
SET salary = 500000,
updated_at = SYSDATE
WHERE employee_id = 1001;
デフォルト値としてSYSDATEを設定
テーブル定義でのDEFAULT SYSDATE
CREATE TABLE orders (
order_id NUMBER PRIMARY KEY,
product_id NUMBER,
quantity NUMBER,
order_date DATE DEFAULT SYSDATE -- 省略時は現在日時
);
ポイント:DEFAULT SYSDATEを設定すると、INSERT時にorder_dateを省略しても自動的に現在日時が入ります。
WHERE句での日付条件
今日のデータを取得
今日のデータを抽出
SELECT * FROM orders
WHERE order_date >= TRUNC(SYSDATE)
AND order_date < TRUNC(SYSDATE) + 1;
過去N日間のデータを取得
直近7日間のデータ
SELECT * FROM orders
WHERE order_date >= SYSDATE - 7;
今月のデータを取得
当月のデータ
SELECT * FROM orders
WHERE order_date >= TRUNC(SYSDATE, 'MM')
AND order_date < ADD_MONTHS(TRUNC(SYSDATE, 'MM'), 1);
注意:DATE型には時分秒が含まれるため、WHERE order_date = SYSDATEでは秒単位まで一致するデータしか取得できません。日付のみで比較する場合は必ずTRUNCを使います。
PL/SQLでの活用
PL/SQL – 変数に格納して使用
DECLARE
v_now DATE := SYSDATE;
v_text VARCHAR2(50);
BEGIN
v_text := TO_CHAR(v_now, 'YYYY/MM/DD HH24:MI:SS');
DBMS_OUTPUT.PUT_LINE('現在日時: ' || v_text);
-- 営業時間内かどうかの判定
IF TO_NUMBER(TO_CHAR(v_now, 'HH24')) BETWEEN 9 AND 17 THEN
DBMS_OUTPUT.PUT_LINE('営業時間内です');
ELSE
DBMS_OUTPUT.PUT_LINE('営業時間外です');
END IF;
END;
/
PL/SQL – 処理時間の計測
DECLARE
v_start TIMESTAMP := SYSTIMESTAMP;
v_end TIMESTAMP;
BEGIN
-- 何かの処理
FOR i IN 1..100000 LOOP
NULL;
END LOOP;
v_end := SYSTIMESTAMP;
DBMS_OUTPUT.PUT_LINE('処理時間: ' || (v_end - v_start));
END;
/
よくあるエラーと対処法
| エラー・問題 |
原因 |
対処法 |
SYSDATE()でエラー |
括弧を付けている |
括弧なしのSYSDATEを使用 |
| 日付比較で結果が0件 |
DATE型に時分秒が含まれている |
TRUNCで時刻を切り捨てて比較 |
| SYSDATEとCURRENT_DATEが異なる |
セッションタイムゾーンがDBサーバーと異なる |
ALTER SESSION SET TIME_ZONEで確認・変更 |
| ORA-01843: not a valid month |
NLS_DATE_FORMATと文字列の形式不一致 |
TO_DATEで明示的にフォーマット指定 |
| テスト時にSYSDATEを固定したい |
テスト用に日付を変更したい |
ALTER SYSTEM SET FIXED_DATEを使用 |
テスト用にSYSDATEを固定する
FIXED_DATEでSYSDATEを固定
-- SYSDATEを固定(DBA権限が必要)
ALTER SYSTEM SET FIXED_DATE = '2025-01-01-00:00:00';
-- 確認
SELECT SYSDATE FROM DUAL; -- 2025-01-01 00:00:00
-- 解除
ALTER SYSTEM SET FIXED_DATE = NONE;
注意:FIXED_DATEはインスタンス全体に影響します。本番環境では絶対に使用しないでください。テスト・開発環境専用の機能です。
他のRDBMSとの比較
| RDBMS |
現在日時の取得 |
備考 |
| Oracle |
SYSDATE / SYSTIMESTAMP |
FROM DUALが必要 |
| MySQL |
NOW() / SYSDATE() |
括弧が必要 |
| PostgreSQL |
NOW() / CURRENT_TIMESTAMP |
FROM不要 |
| SQL Server |
GETDATE() / SYSDATETIME() |
括弧が必要 |
| SQLite |
datetime('now') |
関数形式が異なる |
まとめ
| 用途 |
推奨関数 |
理由 |
| 一般的な日時取得 |
SYSDATE |
最もシンプルで高速 |
| ログ・監査記録 |
SYSTIMESTAMP |
小数秒+TZで正確に記録 |
| マルチタイムゾーン環境 |
CURRENT_DATE / CURRENT_TIMESTAMP |
ユーザーのローカル時刻に対応 |
| 日付の比較・検索 |
TRUNC(SYSDATE) |
時刻を除外して日付のみ比較 |
| フォーマット変換 |
TO_CHAR(SYSDATE, …) |
任意の書式で文字列化 |
Oracleでシステム日付を取得するには、まずSYSDATEを覚えれば大半の場面で対応できます。高精度が必要ならSYSTIMESTAMP、タイムゾーンを意識するならCURRENT_DATEと、用途に応じて使い分けましょう。
関連記事