PostgreSQL小ネタ(Oracleの関数 add_months)

PostgreSQL database

今回はadd_monthsを自作します

前回の記事でOracleにあってPostgreSQLに無い関数「last_day」をファンクションで作成しました。今回は月の加減に利用する「add_months」を作ってみたいと思います。

PostgreSQLで月を加減するには?

PostgreSQLには「interval」という、月だけでなく年・日の加減にも利用できる関数があります。

今日の1年後
select now()::date + interval '1year';
今日の1か月後
select now()::date + interval '1month';
明日
select now()::date + interval '1day';

これはこれで慣れるとどうということ無いのですが、DB移行案件や「使い慣れた関数はそのまま使いたい」という状況もあります。海外旅行に醤油を持参するのと同じです(謎)

add_monthsを作ってみる

それでは早速作ってみましょう!

create or replace function add_months(in date, in int) returns date as $$

	select ($1 + ($2::text || ' month')::interval)::date;

$$ language sql;

非常にシンプルですね。

sandambara=# create or replace function add_months(in date, in int) returns date as $$
sandambara$#
sandambara$#         select ($1 + ($2::text || ' month')::interval)::date;
sandambara$#
sandambara$# $$ language sql;
CREATE FUNCTION

使ってみます。

sandambara=# select add_months('2020-07-14', 1);
 add_months
------------
 2020-08-14
(1 row)

sandambara=# select add_months('2020-07-14', -1);
 add_months
------------
 2020-06-14
(1 row)

月末日付に対して加減を行うときは戻り値も月末日付になります。

sandambara=# select add_months('2020-01-31', 1);
 add_months
------------
 2020-02-29
(1 row)

このファンクションのポイントはintervalの使い方です。日頃SQLでintervalを使っていると「interval $2::text || ‘month’」とか「$1 + (interval ‘$2 month’)」と書きたくなりますが、前者はsyntaxエラーで後者は誤演算となります。

sandambara=# -- これはおこられる
sandambara=# create or replace function add_months(in date, in int) returns date as $$
sandambara$#
sandambara$#         select ($1 + (interval $2::text || 'month'))::date;
sandambara$#
sandambara$# $$ language sql;
ERROR:  syntax error at or near "$2"
LINE 3:  select ($1 + (interval $2::text || 'month'))::date;
                                ^

sandambara=# -- これは常に2か月プラスされる
sandambara=# create or replace function add_months(in date, in int) returns date as $$
sandambara$#
sandambara$#         select ($1 + (interval '$2 month'))::date;
sandambara$#
sandambara$# $$ language sql;
CREATE FUNCTION

sandambara=# select add_months('2020-07-14', 1);
 add_months
------------
 2020-09-14
(1 row)

sandambara=# select add_months('2020-07-14', -1);
 add_months
------------
 2020-09-14
(1 row)

Oracle移行組の方、是非お試しください!

コメント