Kodrill

SQL: データ操作とデータ型

OSS-DB Silver

SELECT (結合・副問い合わせ・GROUP BY・HAVING・ORDER BY・LIMIT)・INSERT・UPDATE・DELETE・ON CONFLICT・RETURNING/数値・文字列・日付・JSON などのデータ型

問題数
22 問
合格ライン
70%
実行して確認済み
21 問
この分野の要点を読む6 章・約 10 分。実行して確かめたコード例と、試験でよくある引っかけをまとめています

ログインなしで試す

無料の 5 問を、1問ごとに正誤と解説を見ながら解けます。解答は保存されません。

5 問を試す

無料登録して学習を記録する

学習履歴・ダッシュボード・ブックマーク・模試モードが使えます。

★ 残り 17 問はプレミアム会員限定です

無料プランでは先頭 5 問まで解けます。プレミアムなら全問題・苦手問題の復習・広告非表示が使えます。
料金プランを見る

問題と解説を見る (無料)

登録しなくても、次の5問は問題文と解説をそのまま読めます。

SQL: データ操作とデータ型の要点

内容の確認日: 2026-10-29

この分野は出題範囲の S3.1 (SQL コマンド) のうち、SELECT・INSERT・UPDATE・DELETE とデータ型を扱います。S3.1 は 50 問中およそ 13 問と、出題数が最も多い中分類です (テーブル定義などの残りは「SQL: テーブル定義とデータベースオブジェクト」で扱います)。

SQL の問題は「実行したときの出力」を問う形が多く、NULL の扱いや型の変換など、細かい挙動の知識が問われます。この記事のコード例はすべて PostgreSQL 14 で実行した結果です。出力は列を | で区切り、NULL は NULL と表示しています。

SELECT の基本と NULL

PostgreSQL では NULL を「どの値よりも大きい」として並べるので、昇順では最後、降順では最初に来ます。NULLS FIRST・NULLS LAST で変えられます。LIMIT と OFFSET は並べ替えた後に適用されます。

SQL
CREATE TABLE emp (name text, dept text, salary integer);INSERT INTO emp VALUES ('a', 'dev', 400), ('b', 'dev', NULL),                       ('c', 'ops', 300), ('d', 'ops', 500);SELECT name FROM emp ORDER BY salary DESC LIMIT 2;SELECT dept, count(*), count(salary), sum(salary)  FROM emp GROUP BY dept ORDER BY dept;SELECT dept FROM emp GROUP BY dept HAVING sum(salary) > 500;
ターミナル
psql -A -t -P null=NULL -f example.sql
b
d
dev|2|1|400
ops|2|2|800
ops

count(*) は行の数、count(列) と sum などの集約関数は NULL を除いて計算します。集約した結果で絞り込むのは HAVING で、WHERE に集約関数を書くとエラー (42803) になります。DISTINCT は重複を除き、NULL どうしは同じものとして 1 行にまとめます。

結合と副問い合わせ

JOIN (INNER JOIN) は条件に合う組み合わせだけ、LEFT JOIN は左のテーブルの行をすべて残し、相手がない列を NULL にします。RIGHT JOIN・FULL JOIN・CROSS JOIN (直積) もあります。

副問い合わせの IN・EXISTS は似ていますが、NOT IN は副問い合わせの結果に NULL が含まれると、どの行も選ばれなくなります (x <> NULL が NULL になるため)。NULL がありうるときは NOT EXISTS を使います。

SQL
CREATE TABLE a (id integer);CREATE TABLE b (id integer, v text);INSERT INTO a VALUES (1), (2), (3);INSERT INTO b VALUES (2, 'x'), (NULL, 'y');SELECT a.id, b.v FROM a LEFT JOIN b ON a.id = b.id ORDER BY a.id;SELECT count(*) FROM a WHERE id NOT IN (SELECT id FROM b);SELECT count(*) FROM a WHERE NOT EXISTS (SELECT 1 FROM b WHERE b.id = a.id);
ターミナル
psql -A -t -P null=NULL -f example.sql
1|NULL
2|x
3|NULL
0
2

集合演算の UNION は重複を除き、UNION ALL は除きません。INTERSECT (共通部分)・EXCEPT (差) もあります。

INSERT・UPDATE・DELETE

INSERT ... SELECT で問い合わせの結果を挿入でき、RETURNING で挿入・更新・削除した行の値を返せます。ON CONFLICT (列) DO NOTHING は一意制約の違反を無視し、DO UPDATE SET ... は既存の行を更新します (EXCLUDED は挿入しようとした行)。UPDATE ... FROM で、ほかのテーブルを結合した条件で更新できます。

SQL
CREATE TABLE stock (sku text PRIMARY KEY, qty integer);INSERT INTO stock VALUES ('A', 5) RETURNING qty;INSERT INTO stock VALUES ('A', 3)  ON CONFLICT (sku) DO UPDATE SET qty = stock.qty + EXCLUDED.qty;UPDATE stock SET qty = qty * 2 RETURNING sku, qty;
ターミナル
psql -A -t -P null=NULL -f example.sql
5
A|16

UPDATE・DELETE に WHERE を書かないと、すべての行が対象になります。

数値・文字列・論理値の型

・整数: smallint・integer・bigint。整数どうしの割り算は小数点以下を切り捨てる ・numeric(全体の桁数, 小数点以下の桁数) (decimal も同じ): 誤差のない 10 進数。桁を超える小数は四捨五入、整数部分が入らなければエラー ・real・double precision: 浮動小数点数 (誤差がある) ・varchar(n): n 文字を超えるとエラー (明示的な型変換なら切り詰め)。char(n): 空白で埋めるが、末尾の空白は意味を持たない。text: 長さの上限なし ・boolean: true・yes・on・1 などを受け付け、psql では t・f と表示される

SQL
SELECT 7 / 2, 7 / 2.0, 123.456::numeric(5,2), 2.5::numeric::integer;SELECT char_length('ab'::char(5)), 'abcd'::varchar(3), 'yes'::boolean;
ターミナル
psql -A -t -P null=NULL -f example.sql
3|3.5000000000000000|123.46|3
2|abc|t

日付と時刻・JSON・自動採番

date に整数を足すと日数だけ進み、date どうしの引き算は日数の整数です。timestamp どうしの引き算は interval で、interval '1 month' を足すと月末を超える日はその月の末日になります。

SQL
SELECT date '2026-01-31' + 1, date '2026-03-01' - date '2026-02-01';SELECT timestamp '2026-01-31 10:00' + interval '1 month',       timestamp '2026-01-02 03:00' - timestamp '2026-01-01 01:30';
ターミナル
psql -A -t -P null=NULL -f example.sql
2026-02-01|28
2026-02-28 10:00:00|1 day 01:30:00

json は入力した文字列をそのまま保存し、jsonb は解析してバイナリで保存します (重複したキーは最後の値だけ残り、キーは並べ替えられる)。-> は jsonb のまま、->> は text で取り出し、#>> はパスで取り出します。JSON パス (jsonb_path_query など) では、$.items[*] ? (@.p > 150) のように条件で絞り込めます。

SQL
SELECT '{"b":1,"a":2,"a":3}'::jsonb;SELECT '{"user": {"name": "alice"}}'::jsonb -> 'user' ->> 'name';
ターミナル
psql -A -t -P null=NULL -f example.sql
{"a": 3, "b": 1}
alice

自動で番号を振る列は serial (integer の列・シーケンス・既定値の組) か、SQL 標準の GENERATED ... AS IDENTITY で作ります。GENERATED ALWAYS の列に値を指定するとエラー (428C9) になり、GENERATED BY DEFAULT なら指定した値が使われます。serial の列に値を直接指定してもシーケンスは進まないので、後で番号が重複することがあります。

試験でよくある引っかけ

  • 降順では NULL が先頭

    ORDER BY 列 DESC では NULL が最初に来ます。NULLS LAST で後ろにできます。

  • count(*) と count(列)

    count(列) は NULL を数えません。sum・avg も NULL を無視します。

  • NOT IN と NULL

    副問い合わせに NULL があると、NOT IN は 1 行も選びません。NOT EXISTS を使います。

  • 整数の割り算

    7 / 2 は 3 です。小数の結果がほしいときは、どちらかを numeric にします。

  • varchar(n) を超える値

    列への挿入はエラー、::varchar(n) の型変換は切り詰めです。

  • ON CONFLICT DO NOTHING の RETURNING

    挿入されなかった行については、何も返しません。

  • json と jsonb

    jsonb は重複したキーを最後の値だけにし、キーの順番も変わります。

問題で確認する

この分野の問題を、解説つきで読めます (登録不要)。

出典・参考

コード例は、PostgreSQL 14 で実際に実行して結果を確認しています。