0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【DB入門】第8章 関数を使う

0
Last updated at Posted at 2026-10-26

SQL には、値を加工するための 関数 が用意されています。文字をつなげる、文字の一部を取り出す、数を丸める、日付を好きな形式の文字にする、といった処理を、SELECT の中で行えます。この章では、Oracle の関数のうち、現場でよく使うものに絞って学びます。

この章で学ぶこと

  • 関数の書き方と、DUAL 表
  • 文字列の関数:||(連結)・LENGTH・SUBSTR・REPLACE・UPPER・LOWER
  • 数値の関数:ROUND・TRUNC・MOD
  • 日付の関数:SYSDATE・TO_CHAR・TO_DATE・MONTHS_BETWEEN
  • WHERE 句の中で関数を使う

8.1 関数とは

関数 は、値を受け取って、加工した値を返す部品です。関数名(値) の形で書き、( ) の中に渡す値を 引数 といいます。引数が複数あるときは , で区切ります。

書き方
関数名(引数1, 引数2, ...)

たとえば LENGTH(NAME) は、「NAME の値を受け取って、その文字数を返す」関数です。関数は SELECT の列の位置にも、WHERE の条件の中にも書けます。第5章の計算(AGE + 1)と同じく、関数は 結果の表示を加工するだけ で、テーブルの値は変わりません。

8.2 DUAL 表

関数の動きを試すとき、テーブルのデータは必要ありません。しかし SELECT 文には FROM が必須です。そこで Oracle には、1行1列だけの表 DUAL が最初から用意されています。第2章の SELECT USER FROM DUAL でも使いました。

ワークシート(XE_DBAPP)
SELECT 1 + 2 FROM DUAL;
1+2
3

DUAL は1行なので、結果も1行になります。この章では、テーブルの列を使わない例は DUAL で試します。

8.3 文字列の関数

|| :文字列をつなげる

||(縦棒2つ)は、左右の文字列をつなげます。関数ではなく演算子ですが、文字列の加工で最もよく使うので、ここで学びます。氏名の後ろに「さん」を付けてみましょう。

ワークシート(XE_DBAPP)
SELECT NAME, NAME || 'さん' AS GREETING FROM EMPLOYEE ORDER BY EMP_ID;
NAME GREETING
雷禅 海皇 雷禅 海皇さん
院照 心愛 院照 心愛さん
林檎 星飛 林檎 星飛さん
田中 美咲 田中 美咲さん
佐藤 健太 佐藤 健太さん
鈴木 花子 鈴木 花子さん
高橋 翔 高橋 翔さん
伊藤 さくら 伊藤 さくらさん
渡辺 大輔 渡辺 大輔さん
中村 結衣 中村 結衣さん

いくつでもつなげられます。氏名と住所を1つの列にします。

ワークシート(XE_DBAPP)
SELECT NAME || '(' || ADDRESS || ')' AS PROFILE FROM EMPLOYEE ORDER BY EMP_ID;
PROFILE
雷禅 海皇(大阪府)
院照 心愛(京都府)
林檎 星飛(東京都)
田中 美咲(愛知県)
佐藤 健太(東京都)
鈴木 花子(大阪府)
高橋 翔(東京都)
伊藤 さくら(兵庫県)
渡辺 大輔(神奈川県)
中村 結衣(京都府)

数の列もつなげられます。数は自動で文字に変換されます。

ワークシート(XE_DBAPP)
SELECT NAME, AGE || '歳' AS AGE_LABEL FROM EMPLOYEE ORDER BY EMP_ID;
NAME AGE_LABEL
雷禅 海皇 26歳
院照 心愛 27歳
林檎 星飛 24歳
田中 美咲 24歳
佐藤 健太 31歳
鈴木 花子 29歳
高橋 翔 35歳
伊藤 さくら 22歳
渡辺 大輔 42歳
中村 結衣 26歳

【ご注意】+ では文字列をつなげられない

プログラミング言語では + で文字列をつなげるものが多いですが、Oracle の SQL で NAME + 'さん' と書くと、数の足し算として扱われ「ORA-01722: 数値が無効です。」というエラーになります。文字列をつなげるのは || です。

LENGTH・SUBSTR・REPLACE

関数 意味 例 結果
LENGTH(文字列) 文字数を返す LENGTH('雷禅 海皇') 5(空白も1文字)
SUBSTR(文字列, 開始位置, 文字数) 開始位置(1 から数える)から、指定した文字数を取り出す SUBSTR('雷禅 海皇', 1, 2) 雷禅
REPLACE(文字列, 探す文字, 置き換える文字) 探す文字をすべて置き換える REPLACE('雷禅 海皇', ' ', '') 雷禅海皇

氏名の文字数と、先頭2文字(姓)を表示します。

ワークシート(XE_DBAPP)
SELECT NAME, LENGTH(NAME) AS LEN, SUBSTR(NAME, 1, 2) AS FAMILY_NAME FROM EMPLOYEE ORDER BY EMP_ID;
NAME LEN FAMILY_NAME
雷禅 海皇 5 雷禅
院照 心愛 5 院照
林檎 星飛 5 林檎
田中 美咲 5 田中
佐藤 健太 5 佐藤
鈴木 花子 5 鈴木
高橋 翔 4 高橋
伊藤 さくら 6 伊藤
渡辺 大輔 5 渡辺
中村 結衣 5 中村

この教材のサンプルデータは、姓が2文字なので SUBSTR(NAME, 1, 2) で姓を取り出せています。実際の業務では姓の文字数は決まっていないので、姓と名は最初から別の列に分けて持つのが一般的です。

氏名の姓と名の間の空白を取り除きます。

ワークシート(XE_DBAPP)
SELECT NAME, REPLACE(NAME, ' ', '') AS NO_SPACE FROM EMPLOYEE ORDER BY EMP_ID;
NAME NO_SPACE
雷禅 海皇 雷禅海皇
院照 心愛 院照心愛
林檎 星飛 林檎星飛
田中 美咲 田中美咲
佐藤 健太 佐藤健太
鈴木 花子 鈴木花子
高橋 翔 高橋翔
伊藤 さくら 伊藤さくら
渡辺 大輔 渡辺大輔
中村 結衣 中村結衣

''(' を2つ続けたもの)は、空の文字列を表します。Oracle では、空の文字列は NULL と同じ扱いになりますが、REPLACE の3つ目の引数に書くと「探した文字を消す」という動きになります。

UPPER・LOWER

UPPER は英字を大文字に、LOWER は小文字にします。日本語には影響しません。この教材のデータには英字が無いので、DUAL で試します。

ワークシート(XE_DBAPP)
SELECT UPPER('oracle') AS UP, LOWER('ORACLE') AS LOW FROM DUAL;
UP LOW
ORACLE oracle

英字を含む列を検索するとき、WHERE UPPER(EMAIL) = UPPER('Taro@Example.com') のように両側を大文字にそろえると、大文字と小文字の違いを無視して比べられます。

8.4 数値の関数

関数 意味 例 結果
ROUND(数, 桁) 小数点以下 桁 で四捨五入する。桁を省略すると整数にする ROUND(123.456, 1)
ROUND(123.456)
123.5
123
TRUNC(数, 桁) 小数点以下 桁 で切り捨てる。桁を省略すると整数にする TRUNC(123.456, 1) 123.4
MOD(数1, 数2) 数1 を 数2 で割った余りを返す MOD(10, 3) 1
ワークシート(XE_DBAPP)
SELECT ROUND(123.456, 1) AS R1, ROUND(123.456) AS R0, TRUNC(123.456, 1) AS T1, MOD(10, 3) AS M FROM DUAL;
R1 R0 T1 M
123.5 123 123.4 1

ROUND は、第9章で平均(AVG)を計算するときに、小数の桁をそろえるために使います。

8.5 日付の関数

SYSDATE:現在の日時

SYSDATE は、データベースの現在の日時を返します。( ) は付けません。

ワークシート(XE_DBAPP)
SELECT SYSDATE FROM DUAL;
SYSDATE
2026-10-20 21:07:03

結果は、実行した日時になります(上の表は例です)。DATE 型が時刻も持っていることが、ここで確かめられます。日付には数を足し引きでき、1 が1日 を表します。

ワークシート(XE_DBAPP)
SELECT SYSDATE + 7 AS NEXT_WEEK FROM DUAL;
NEXT_WEEK
2026-10-27 21:07:03

TO_CHAR:日付を文字にする

TO_CHAR(日付, '書式') は、日付を指定した書式の文字列にします。書式には、「開発環境の準備」の日付書式の設定で使ったものと同じ記号を使います。

記号 意味 例(2000年6月22日)
YYYY 4桁の年 2000
MM 2桁の月 06
DD 2桁の日 22
HH24・MI・SS 24時間表記の時・分・秒 00・00・00
"文字" " で囲んだ文字をそのまま入れる 'YYYY"年"MM"月"DD"日"' → 2000年06月22日
ワークシート(XE_DBAPP)
SELECT NAME, TO_CHAR(BIRTH_DATE, 'YYYY/MM/DD') AS BIRTH FROM EMPLOYEE ORDER BY EMP_ID;
NAME BIRTH
雷禅 海皇 2000/06/22
院照 心愛 1999/07/11
林檎 星飛 2001/12/24
田中 美咲 2002/03/05
佐藤 健太 1995/04/12
鈴木 花子 1997/01/30
高橋 翔 1991/08/15
伊藤 さくら 2004/05/20
渡辺 大輔 1984/02/10
中村 結衣 2000/09/03
ワークシート(XE_DBAPP)
SELECT NAME, TO_CHAR(BIRTH_DATE, 'YYYY"年"MM"月"DD"日"') AS BIRTH FROM EMPLOYEE ORDER BY EMP_ID;
NAME BIRTH
雷禅 海皇 2000年06月22日
院照 心愛 1999年07月11日
林檎 星飛 2001年12月24日
田中 美咲 2002年03月05日
佐藤 健太 1995年04月12日
鈴木 花子 1997年01月30日
高橋 翔 1991年08月15日
伊藤 さくら 2004年05月20日
渡辺 大輔 1984年02月10日
中村 結衣 2000年09月03日

書式の一部だけを使えば、年だけ、月だけを取り出せます。TO_CHAR(BIRTH_DATE, 'YYYY') は '2000' のような4文字の文字列を返します。

【知識メモ】TO_CHAR の結果は文字列

TO_CHAR の結果は日付ではなく 文字列 です。表示を整えるのには便利ですが、日付として比べたり計算したりするときは、元の日付の列(BIRTH_DATE)を使います。Spring入門では、日付の表示の整形はアプリの画面側で行うので、SQL で TO_CHAR を使う場面は多くありません。

TO_DATE:文字を日付にする

TO_DATE('文字列', '書式') は、TO_CHAR の逆で、文字列を日付にします。'2000/06/22' のように / で区切った文字列を日付として使いたいときに使います。

ワークシート(XE_DBAPP)
SELECT NAME, BIRTH_DATE FROM EMPLOYEE WHERE BIRTH_DATE = TO_DATE('2000/06/22', 'YYYY/MM/DD');
NAME BIRTH_DATE
雷禅 海皇 2000-06-22 00:00:00

この教材では、日付の値は DATE '2000-06-22' の書き方で統一しています。TO_DATE は、入力された文字列の形が決まっているとき(画面から 2000/06/22 の形で受け取るなど)に使います。書式を省略した TO_DATE('2000-06-22') や、文字列をそのまま日付の列と比べる書き方(BIRTH_DATE = '2000/06/22')は、環境の設定によって動いたり動かなかったりするので、書式を必ず書く か DATE '…' を使ってください。

MONTHS_BETWEEN:日付の差

MONTHS_BETWEEN(日付1, 日付2) は、2つの日付の間の月数を返します。12 で割れば年数になります。生年月日から今日時点の年齢を計算し、AGE の列と比べてみましょう。

ワークシート(XE_DBAPP)
SELECT NAME, BIRTH_DATE,
       TRUNC(MONTHS_BETWEEN(SYSDATE, BIRTH_DATE) / 12) AS CALC_AGE,
       AGE
  FROM EMPLOYEE
 ORDER BY EMP_ID;
NAME BIRTH_DATE CALC_AGE AGE
雷禅 海皇 2000-06-22 00:00:00 26 26
院照 心愛 1999-07-11 00:00:00 27 27
林檎 星飛 2001-12-24 00:00:00 24 24
田中 美咲 2002-03-05 00:00:00 24 24
佐藤 健太 1995-04-12 00:00:00 31 31
鈴木 花子 1997-01-30 00:00:00 29 29
高橋 翔 1991-08-15 00:00:00 35 35
伊藤 さくら 2004-05-20 00:00:00 22 22
渡辺 大輔 1984-02-10 00:00:00 42 42
中村 結衣 2000-09-03 00:00:00 26 26

上の表は 2026年10月 に実行した結果です。この教材の AGE の値はこの時点の年齢なので、CALC_AGE と一致しています。誕生日を過ぎた人がいると、CALC_AGE の方が1つ大きくなります。TRUNC で小数を切り捨てているのは、「26.3年」を「26歳」にするためです。関数の中に関数を書く(入れ子にする)こともできます。

8.6 WHERE 句で関数を使う

関数は WHERE の条件の中にも書けます。氏名が6文字以上の社員を取り出します。

ワークシート(XE_DBAPP)
SELECT NAME, LENGTH(NAME) AS LEN FROM EMPLOYEE WHERE LENGTH(NAME) >= 6;
NAME LEN
伊藤 さくら 6

6月生まれの社員を取り出します。TO_CHAR で月だけを文字列にして比べます。

ワークシート(XE_DBAPP)
SELECT NAME, TO_CHAR(BIRTH_DATE, 'MM') AS BIRTH_MONTH FROM EMPLOYEE WHERE TO_CHAR(BIRTH_DATE, 'MM') = '06';
NAME BIRTH_MONTH
雷禅 海皇 06

TO_CHAR の結果は文字列なので、比べる値も '06' と文字列で書きます。= 6 と数で書くと、Oracle が '06' を数に変換して比べるので動きますが、結果が分かりにくくなるので、型をそろえて書きます。

【ご注意】WHERE 句の別名は使えない

SELECT LENGTH(NAME) AS LEN … WHERE LEN >= 6 のように、SELECT で付けた別名を WHERE で使うことはできません(「ORA-00904: "LEN": 無効な識別子です。」)。WHERE は SELECT より先に処理されるためです(第6章)。WHERE には、関数や式をもう一度書きます。

8.7 うまくいかないときは

症状 考えられる原因と対処
「ORA-01722: 数値が無効です。」 文字列を + でつなげようとしているか、数に変換できない文字列を数と比べています。文字列の連結は || です。
「ORA-00904: "〇〇": 無効な識別子です。」 関数名の打ち間違い(LENGHT など)か、WHERE 句で別名を使っています。
「ORA-00909: 引数の個数が無効です。」
「ORA-00938: 関数の引数が不足しています。」
関数に渡す引数の数が違います。SUBSTR は2つか3つ、REPLACE は2つか3つ、MOD は2つです。
「ORA-01858: 数値を指定する箇所に数値以外の文字が指定されています」 日付として解釈できない文字列を、日付の列と比べているか TO_DATE に渡しています。DATE '2000-06-22' の書き方にするか、TO_DATE に文字列と合った書式を書いてください。
日付が 00-06-22 のように2桁の年で表示される 「開発環境の準備」の日付書式の設定が反映されていません。設定を確認し、SQL Developer をいったん終了して、もう一度起動してから接続してください。

ほかのエラーは、付録B「よくあるエラーと対処法」 も参考にしてください。

8.8 まとめと確認問題

まとめ

  • 関数は 関数名(引数, …) の形で書き、値を加工して返す。テーブルの値は変わらない。テーブルを使わずに試すときは DUAL 表を使う
  • 文字列は || でつなげる。LENGTH(文字数)・SUBSTR(一部を取り出す)・REPLACE(置き換え)・UPPER・LOWER
  • 数値は ROUND(四捨五入)・TRUNC(切り捨て)・MOD(余り)
  • SYSDATE は現在の日時。日付に数を足すと日数が進む。TO_CHAR(日付, '書式') で文字列に、TO_DATE('文字列', '書式') で日付にする。MONTHS_BETWEEN で月数の差
  • 関数は WHERE 句でも使える。SELECT の別名は WHERE では使えない

この章で使った関数は、付録C「SQL 早見表」の「関数」 にまとめています。

確認問題

問1 氏名と住所を「雷禅 海皇さんは大阪府に住んでいます」の形で表示する SELECT 文を書いてください。

解答を見る

SELECT NAME || 'さんは' || ADDRESS || 'に住んでいます' AS MSG FROM EMPLOYEE;

問2 SUBSTR('伊藤 さくら', 4, 3) の結果は何ですか。

解答を見る

さくら です。4文字目(「さ」)から3文字を取り出します。空白も1文字と数えます。

問3 ROUND(28.65, 1) と TRUNC(28.65, 1) の結果をそれぞれ答えてください。

解答を見る

ROUND(28.65, 1) は 28.7(四捨五入)、TRUNC(28.65, 1) は 28.6(切り捨て)です。

問4 生年月日を「1999年7月」のように年と月だけで表示したいとき、TO_CHAR の書式はどう書きますか(月は2桁でよい)。

解答を見る

TO_CHAR(BIRTH_DATE, 'YYYY"年"MM"月"') です。結果は 1999年07月 になります。

問5 SELECT NAME, LENGTH(NAME) AS LEN FROM EMPLOYEE WHERE LEN = 4; がエラーになる理由と、直し方を答えてください。

解答を見る

SELECT で付けた別名 LEN は、SELECT より先に処理される WHERE では使えないためです。WHERE LENGTH(NAME) = 4 と関数を書き直します。結果は 高橋 翔 の1行です。


前へ

第7章 データを変更・削除する

次へ

第9章 集計する

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?