now() と CURRENT_TIMESTAMP は、なんとなく同じものかぁ、、と思っていましたが、調べてみると違いがありました。返る値は同じです。違うのは「書き方」と「どこから来たものか」です。
返る値は同じ
SELECT now() = current_timestamp AS same,
pg_typeof(now()), pg_typeof(current_timestamp);
-- same | pg_typeof | pg_typeof
-- t | timestamp with time zone | timestamp with time zone
どちらもトランザクション開始時刻を返します。ほかの時刻関数との違いは「PostgreSQL 時刻を返す関数の一覧」にまとめています。
違い
| now() | CURRENT_TIMESTAMP | |
|---|---|---|
| 出どころ | PostgreSQL 独自の関数 | SQL 標準の書き方 |
| カッコ | 必要 | 付けない |
| 精度の指定 | できない | CURRENT_TIMESTAMP(3) |
| ほかのDBで書けるか | MySQL には NOW() がある。Oracle・Db2 にはない | Oracle・MySQL・Db2 でも書ける |
CURRENT_TIMESTAMP() はエラーになる
SELECT current_timestamp(); -- ERROR: syntax error at or near ")" SELECT current_timestamp(3); -- 2026-10-12 02:52:04.843+09 SELECT now(3); -- ERROR: function now(integer) does not exist
CURRENT_TIMESTAMPは関数ではなく、SQL の決まった書き方(キーワード)です。カッコの中には精度しか書けません。- 反対に
now()は関数なので、カッコが必要です。精度は指定できません。 - MySQL では
CURRENT_TIMESTAMP()と書いてもエラーになりません。そのため、MySQL から移したSQLでつまずきやすいところです。 CURRENT_TIME・CURRENT_DATE・LOCALTIMESTAMP・LOCALTIMEも同じで、カッコを付けずに書きます。
精度を指定すると「切り捨て」ではなく「四捨五入」になる
SELECT now(), current_timestamp(3), current_timestamp(0); -- 02:52:04.842957+09 | 02:52:04.843+09 | 02:52:05+09
CURRENT_TIMESTAMP(0) は、04.84秒が05秒に切り上げられました。最大で0.5秒先の「未来の時刻」になることがあります。秒より下を切り捨てたいときは、date_trunc('second', now()) を使います。
同じ CURRENT_TIMESTAMP でも、DBによって意味が違う
ここがいちばん大事な点です。
| DB | CURRENT_TIMESTAMP が返す時刻 |
|---|---|
| PostgreSQL | トランザクション開始時刻 |
| Oracle・MySQL・Db2 | SQL文の時刻 |
SQL 標準では、「1つのSQL文の中では同じ値」とだけ決まっています。トランザクションの中でも同じ値にするかどうかは、それぞれのDBに任されています。そのため、CURRENT_TIMESTAMP と書けばどのDBでも同じ動きになる、というわけではありません。PostgreSQL でほかのDBと同じ動きにしたいときは、statement_timestamp() を使います。
どちらを使えばよいか
- PostgreSQL だけで使うなら、どちらでもよいです。短いので
now()がよく使われます。 - 複数のDBで同じSQLを使い回したいなら、
CURRENT_TIMESTAMPを使います(ただし、上の意味の違いに注意)。 - ビューの定義に書いたものは、書いたとおりに残ります。
pg_get_viewdefで見ると、now()はnow()のまま、CURRENT_TIMESTAMPはCURRENT_TIMESTAMPのまま表示されます。
※ 手元で動かして確かめたのは PostgreSQL 15 だけです。Oracle・MySQL・Db2 については、各製品のマニュアルをもとに書いています。
