目的別 SQL クイックリファレンス
データ検索 (SELECT)
テーブルから情報を取得するための基本的な操作です。
基本的な検索
- 全ての列を取得:
SELECT * FROM テーブル名; - 特定の列を取得:
SELECT 列1, 列2 FROM テーブル名; - 重複を除外して取得 (DISTINCT):
SELECT DISTINCT 列1 FROM テーブル名; - 別名 (エイリアス) を使用:
SELECT 列1 AS 別名1, 列2 AS 別名2 FROM テーブル名; SELECT t.列1, t.列2 FROM テーブル名 AS t; -- テーブルにも別名 
条件指定 (WHERE)
特定の条件に一致する行のみを取得します。
- 基本的な比較演算子: `=`, `<>` (または `!=`), `<`, `>`, `<=`, `>=` 
SELECT 列1, 列2 FROM テーブル名 WHERE 列1 = '値'; SELECT 列1, 列2 FROM テーブル名 WHERE 列2 > 100; - 論理演算子 (AND, OR, NOT):
SELECT * FROM テーブル名 WHERE 列1 = '値1' AND 列2 < 50; SELECT * FROM テーブル名 WHERE 列1 = '値1' OR 列1 = '値2'; SELECT * FROM テーブル名 WHERE NOT 列1 = '特定の値'; - 範囲指定 (BETWEEN):
SELECT * FROM テーブル名 WHERE 列1 BETWEEN 10 AND 20; -- 10と20を含む - リスト指定 (IN):
SELECT * FROM テーブル名 WHERE 列1 IN ('値A', '値B', '値C'); - パターンマッチング (LIKE): `%` (任意の文字列), `_` (任意の1文字) 
SELECT * FROM テーブル名 WHERE 列1 LIKE 'A%'; -- Aで始まる SELECT * FROM テーブル名 WHERE 列1 LIKE '%パターン%'; -- パターンを含む SELECT * FROM テーブル名 WHERE 列1 LIKE 'A_C'; -- Aで始まり、Cで終わる3文字注意: エスケープ文字はデータベースによって異なる場合があります (例: `\`)
 - NULL 値の判定 (IS NULL, IS NOT NULL):
SELECT * FROM テーブル名 WHERE 列1 IS NULL; SELECT * FROM テーブル名 WHERE 列1 IS NOT NULL; 
結果の並び替え (ORDER BY)
取得した結果を指定した列で並び替えます。
- 昇順 (ASC – デフォルト):
SELECT * FROM テーブル名 ORDER BY 列1 ASC; SELECT * FROM テーブル名 ORDER BY 列1; -- ASCは省略可能 - 降順 (DESC):
SELECT * FROM テーブル名 ORDER BY 列1 DESC; - 複数列での並び替え:
SELECT * FROM テーブル名 ORDER BY 列1 ASC, 列2 DESC; - 列番号での指定 (非推奨だが可能):
SELECT 列1, 列2 FROM テーブル名 ORDER BY 1 DESC; -- 1番目の列(列1)で降順ソート 
結果の制限 (LIMIT / TOP / ROWNUM)
取得する行数を制限します。構文はデータベース製品によって異なります。
| データベース | 構文例 (先頭からN件) | 構文例 (M行目からN件) | 
|---|---|---|
| MySQL, PostgreSQL, SQLite |  |  | 
| SQL Server |  |  | 
| Oracle |  |  | 
集計関数とグループ化 (Aggregate Functions, GROUP BY, HAVING)
データをグループ化し、各グループに対して集計を行います。
- 主な集計関数:
- `COUNT()`: 行数を数える ( `COUNT(*)`: 全行数, `COUNT(列名)`: NULL以外の行数, `COUNT(DISTINCT 列名)`: 重複を除いた行数)
 - `SUM(列名)`: 合計値
 - `AVG(列名)`: 平均値
 - `MAX(列名)`: 最大値
 - `MIN(列名)`: 最小値
 
SELECT COUNT(*) AS 総行数, AVG(価格) AS 平均価格 FROM 商品; - グループ化 (GROUP BY): 特定の列の値が同じ行をグループ化し、集計関数を適用します。`SELECT`句には`GROUP BY`で指定した列か集計関数しか記述できません。 
SELECT カテゴリID, COUNT(*) AS 商品数 FROM 商品 GROUP BY カテゴリID; - グループ化後の条件指定 (HAVING): `GROUP BY`でグループ化された結果に対して条件を指定します。`WHERE`句はグループ化前の行に対する条件指定です。 
SELECT カテゴリID, AVG(価格) AS 平均価格 FROM 商品 GROUP BY カテゴリID HAVING AVG(価格) > 5000; -- 平均価格が5000より大きいカテゴリのみ 
テーブル結合 (JOIN)
複数のテーブルを関連する列を基に結合します。
| JOINの種類 | 説明 | 構文例 | 
|---|---|---|
| INNER JOIN (または JOIN) | 両方のテーブルに結合キーが存在する行のみを結合します。 |  | 
| LEFT JOIN (または LEFT OUTER JOIN) | 左側のテーブル(t1)の全ての行と、右側のテーブル(t2)で結合キーが一致する行を結合します。一致しない場合は右側の列はNULLになります。 |  | 
| RIGHT JOIN (または RIGHT OUTER JOIN) | 右側のテーブル(t2)の全ての行と、左側のテーブル(t1)で結合キーが一致する行を結合します。一致しない場合は左側の列はNULLになります。 |  | 
| FULL OUTER JOIN | 左右両方のテーブルの全ての行を結合します。どちらかのテーブルにしか存在しない場合は、存在しない側の列はNULLになります。(MySQLは標準ではサポートしていません) |  | 
| CROSS JOIN | 両方のテーブルの行の全ての組み合わせ(デカルト積)を生成します。結合条件は指定しません。 |  | 
| SELF JOIN | 同じテーブル同士を結合します。テーブルに別名をつける必要があります。 |  | 
副問い合わせ (Subquery)
クエリの中に別のクエリを埋め込む方法です。
- SELECT句内の副問い合わせ (スカラ副問い合わせ): 単一の値を返す必要があります。 
SELECT 商品名, 価格, (SELECT AVG(価格) FROM 商品) AS 全体平均価格 FROM 商品; - FROM句内の副問い合わせ (インラインビュー): 結果セットを一時的なテーブルとして扱います。 
SELECT t.カテゴリID, t.平均価格 FROM ( SELECT カテゴリID, AVG(価格) AS 平均価格 FROM 商品 GROUP BY カテゴリID ) AS t WHERE t.平均価格 > 5000; - WHERE句内の副問い合わせ:
- 単一値を返す副問い合わせ: 比較演算子 (`=`, `>`, etc.) と共に使用します。 
SELECT 商品名, 価格 FROM 商品 WHERE 価格 > (SELECT AVG(価格) FROM 商品); - リストを返す副問い合わせ: `IN`, `NOT IN` と共に使用します。 
SELECT * FROM 注文 WHERE 顧客ID IN (SELECT 顧客ID FROM 顧客 WHERE 地域 = '東京'); - 存在確認: `EXISTS`, `NOT EXISTS` と共に使用します。副問い合わせが1行でも返せば真。 
SELECT * FROM 顧客 c WHERE EXISTS (SELECT 1 FROM 注文 o WHERE o.顧客ID = c.顧客ID); -- 注文履歴のある顧客 - 比較演算子 (`ANY`, `SOME`, `ALL`) と共に使用します。 
-- いずれかの東京の顧客の注文額より大きい注文 SELECT * FROM 注文 WHERE 金額 > ANY (SELECT 注文額 FROM 注文履歴 WHERE 顧客地域 = '東京'); -- 全ての東京の顧客の注文額より大きい注文 SELECT * FROM 注文 WHERE 金額 > ALL (SELECT 注文額 FROM 注文履歴 WHERE 顧客地域 = '東京'); 
 - 単一値を返す副問い合わせ: 比較演算子 (`=`, `>`, etc.) と共に使用します。 
 - 相関副問い合わせ (Correlated Subquery): 外側のクエリの列を内側の副問い合わせが参照するものです。外側のクエリの行ごとに実行されるため、パフォーマンスに影響が出ることがあります。 
-- 各カテゴリで最も価格が高い商品 SELECT 商品名, カテゴリID, 価格 FROM 商品 p1 WHERE 価格 = (SELECT MAX(価格) FROM 商品 p2 WHERE p1.カテゴリID = p2.カテゴリID); 
ウィンドウ関数 (Window Functions)
行のセット(ウィンドウ)に対して計算を行いますが、`GROUP BY`のように行を集約しません。各行に対して計算結果を返します。分析関数とも呼ばれます。
`関数名() OVER ( [PARTITION BY 列…] [ORDER BY 列…] [ROWS BETWEEN … AND …] )` の形式で使用します。
- ランキング関数:
- `ROW_NUMBER()`: ウィンドウ内で一意の連番を付与 (同順位でも異なる番号)
 - `RANK()`: 順位を付与 (同順位は同じ番号、次の順位は飛ぶ)
 - `DENSE_RANK()`: 順位を付与 (同順位は同じ番号、次の順位は飛ばない)
 - `NTILE(n)`: ウィンドウをn個のグループに分割し、グループ番号を付与
 
SELECT 商品名, 価格, カテゴリID, ROW_NUMBER() OVER (PARTITION BY カテゴリID ORDER BY 価格 DESC) AS カテゴリ内価格順位_ROWNUM, RANK() OVER (PARTITION BY カテゴリID ORDER BY 価格 DESC) AS カテゴリ内価格順位_RANK, DENSE_RANK() OVER (PARTITION BY カテゴリID ORDER BY 価格 DESC) AS カテゴリ内価格順位_DENSERANK FROM 商品; - 集計関数 (ウィンドウ関数として使用): `SUM()`, `AVG()`, `COUNT()`, `MAX()`, `MIN()` など 
SELECT 注文日, 注文額, SUM(注文額) OVER (ORDER BY 注文日) AS 累計注文額, -- 全体の累計 AVG(注文額) OVER (PARTITION BY MONTH(注文日)) AS 月別平均注文額 -- 月ごとの平均 FROM 注文履歴; - 値関数:
- `LAG(列 [, オフセット [, デフォルト値]])`: ウィンドウ内の前の行の値を取得
 - `LEAD(列 [, オフセット [, デフォルト値]])`: ウィンドウ内の後の行の値を取得
 - `FIRST_VALUE(列)`: ウィンドウ内の最初の行の値を取得
 - `LAST_VALUE(列)`: ウィンドウ内の最後の行の値を取得
 
SELECT 注文日, 注文額, LAG(注文額, 1, 0) OVER (ORDER BY 注文日) AS 前日の注文額, LEAD(注文額, 1, 0) OVER (ORDER BY 注文日) AS 翌日の注文額 FROM 注文履歴; - フレーム句 (ROWS/RANGE BETWEEN): ウィンドウ関数が計算対象とする範囲をより細かく指定します。 
- `ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW`: 先頭行から現在の行まで (累計計算のデフォルト)
 - `ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING`: 前の行、現在の行、次の行
 - `ROWS BETWEEN 3 PRECEDING AND CURRENT ROW`: 3つ前の行から現在の行まで (移動平均など)
 
SELECT 日付, 売上, AVG(売上) OVER (ORDER BY 日付 ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS 3日間移動平均 FROM 日次売上; 
共通テーブル式 (Common Table Expression – CTE)
`WITH`句を使って、クエリ内で一時的な名前付き結果セットを定義します。複雑なクエリを読みやすくしたり、再帰的なクエリを記述するのに役立ちます。
- 基本的な使い方:
WITH CategorySales AS ( SELECT p.カテゴリID, SUM(oi.数量 * oi.単価) AS カテゴリ別売上 FROM 商品 p JOIN 注文明細 oi ON p.商品ID = oi.商品ID GROUP BY p.カテゴリID ), HighSalesCategories AS ( SELECT カテゴリID FROM CategorySales WHERE カテゴリ別売上 > 100000 ) SELECT c.カテゴリ名, cs.カテゴリ別売上 FROM カテゴリ c JOIN CategorySales cs ON c.カテゴリID = cs.カテゴリID WHERE c.カテゴリID IN (SELECT カテゴリID FROM HighSalesCategories); - 再帰CTE (Recursive CTE): 階層構造データ(組織図、親子関係など)を扱う際に有用です。`WITH RECURSIVE` (PostgreSQL, MySQL 8.0+) または `WITH` (SQL Server, Oracle) を使用します。 
-- 例: 従業員とその上司の階層を取得 (SQL Server/Oracle) WITH EmployeeHierarchy (従業員ID, 名前, 上司ID, Level) AS ( -- アンカーメンバー (起点となる行) SELECT 従業員ID, 名前, 上司ID, 0 FROM 従業員 WHERE 上司ID IS NULL -- 最上位の従業員 UNION ALL -- 再帰メンバー (アンカーメンバーに結合) SELECT e.従業員ID, e.名前, e.上司ID, eh.Level + 1 FROM 従業員 e INNER JOIN EmployeeHierarchy eh ON e.上司ID = eh.従業員ID ) SELECT * FROM EmployeeHierarchy ORDER BY Level, 従業員ID; 
データ操作 (DML – Data Manipulation Language)
テーブル内のデータを追加、更新、削除します。
データ挿入 (INSERT)
- 1行挿入 (列指定):
INSERT INTO テーブル名 (列1, 列2, 列3) VALUES (値1, 値2, 値3); - 1行挿入 (全列指定 – 非推奨): 列の順序に依存するため、列指定が推奨されます。 
INSERT INTO テーブル名 VALUES (全列分の値...); - 複数行挿入 (標準SQL / PostgreSQL / MySQLなど):
INSERT INTO テーブル名 (列1, 列2) VALUES (値1A, 値2A), (値1B, 値2B), (値1C, 値2C); - 複数行挿入 (Oracle / SQL Server – UNION ALL を使用):
-- Oracle INSERT ALL INTO テーブル名 (列1, 列2) VALUES (値1A, 値2A) INTO テーブル名 (列1, 列2) VALUES (値1B, 値2B) SELECT * FROM dual; -- SQL Server (昔の方法) INSERT INTO テーブル名 (列1, 列2) SELECT 値1A, 値2A UNION ALL SELECT 値1B, 値2B;注意: SQL Server 2008以降、MySQL/PostgreSQL と同様の VALUES 句による複数行挿入も可能です。
 - 別のテーブルから挿入 (INSERT INTO … SELECT):
INSERT INTO テーブルA (列1, 列2) SELECT 列X, 列Y FROM テーブルB WHERE 条件; - 存在しない場合のみ挿入 (UPSERT / MERGE): データベースによって構文が異なります。 
- MySQL: `INSERT … ON DUPLICATE KEY UPDATE` 
INSERT INTO テーブル名 (ID, 列1, 列2) VALUES (1, '値A', '値B') ON DUPLICATE KEY UPDATE 列1 = '新しい値A', 列2 = '新しい値B'; - PostgreSQL: `INSERT … ON CONFLICT DO UPDATE / DO NOTHING` 
-- 更新する場合 INSERT INTO テーブル名 (ID, 列1, 列2) VALUES (1, '値A', '値B') ON CONFLICT (ID) DO UPDATE SET 列1 = EXCLUDED.列1, 列2 = EXCLUDED.列2; -- 何もしない場合 INSERT INTO テーブル名 (ID, 列1, 列2) VALUES (1, '値A', '値B') ON CONFLICT (ID) DO NOTHING; - SQL Server / Oracle: `MERGE` 
MERGE INTO ターゲットテーブル T USING ソーステーブル S ON (T.結合キー = S.結合キー) WHEN MATCHED THEN UPDATE SET T.列1 = S.列1, T.列2 = S.列2 WHEN NOT MATCHED THEN INSERT (結合キー, 列1, 列2) VALUES (S.結合キー, S.列1, S.列2); - SQLite: `INSERT OR REPLACE INTO` または `INSERT OR IGNORE INTO` 
INSERT OR REPLACE INTO テーブル名 (ID, 列1, 列2) VALUES (1, '値A', '値B'); -- 存在すれば置き換え INSERT OR IGNORE INTO テーブル名 (ID, 列1, 列2) VALUES (1, '値A', '値B'); -- 存在すれば無視 
 - MySQL: `INSERT … ON DUPLICATE KEY UPDATE` 
 
データ更新 (UPDATE)
- 特定の行を更新: `WHERE`句で対象行を指定します。指定しないと全行が更新されます。 
UPDATE テーブル名 SET 列1 = 新しい値1, 列2 = 新しい値2 WHERE 条件; - 他のテーブルの値を使って更新 (データベースによる違いあり):
- 標準SQL / PostgreSQL / SQL Server: `FROM`句や`JOIN`を使用 
-- SQL Server UPDATE t1 SET t1.列A = t2.列X FROM テーブル1 t1 INNER JOIN テーブル2 t2 ON t1.結合キー = t2.結合キー WHERE t1.条件; -- PostgreSQL UPDATE テーブル1 t1 SET 列A = t2.列X FROM テーブル2 t2 WHERE t1.結合キー = t2.結合キー AND t1.条件; - MySQL: `JOIN`を`UPDATE`句の後ろに記述 
UPDATE テーブル1 t1 INNER JOIN テーブル2 t2 ON t1.結合キー = t2.結合キー SET t1.列A = t2.列X WHERE t1.条件; - Oracle: 副問い合わせや`MERGE`を使用 
-- 副問い合わせ UPDATE テーブル1 t1 SET 列A = (SELECT t2.列X FROM テーブル2 t2 WHERE t1.結合キー = t2.結合キー) WHERE EXISTS (SELECT 1 FROM テーブル2 t2 WHERE t1.結合キー = t2.結合キー) AND t1.条件; -- MERGE (INSERTなし) MERGE INTO テーブル1 T USING テーブル2 S ON (T.結合キー = S.結合キー) WHEN MATCHED AND T.条件 THEN UPDATE SET T.列A = S.列X; 
 - 標準SQL / PostgreSQL / SQL Server: `FROM`句や`JOIN`を使用 
 
データ削除 (DELETE)
- 特定の行を削除: `WHERE`句で対象行を指定します。指定しないと全行が削除されます。 
DELETE FROM テーブル名 WHERE 条件; - 全行削除 (DELETE vs TRUNCATE):
- `DELETE FROM テーブル名;`: トランザクションログに記録され、ロールバック可能。WHERE句がないだけで、行ごとに削除処理が走る。低速な場合がある。
 - `TRUNCATE TABLE テーブル名;`: トランザクションログ記録が最小限(または記録されない)。ロールバック不可な場合が多い。高速だが注意が必要。テーブル構造は残る。Auto Incrementもリセットされることが多い。
 
-- 全行削除 (ロールバック可能) DELETE FROM テーブル名; -- 全行高速削除 (ロールバック不可の場合が多い、注意!) TRUNCATE TABLE テーブル名; - 他のテーブルの条件に基づいて削除 (データベースによる違いあり):
- 標準SQL / PostgreSQL / SQL Server: `USING`句や副問い合わせ、`JOIN`を使用 
-- SQL Server (JOIN) DELETE t1 FROM テーブル1 t1 INNER JOIN テーブル2 t2 ON t1.結合キー = t2.結合キー WHERE t2.条件; -- PostgreSQL (USING) DELETE FROM テーブル1 t1 USING テーブル2 t2 WHERE t1.結合キー = t2.結合キー AND t2.条件; -- 副問い合わせ (多くのDBで動作) DELETE FROM テーブル1 WHERE 結合キー IN (SELECT 結合キー FROM テーブル2 WHERE 条件); - MySQL: `JOIN`を使用 
DELETE t1 FROM テーブル1 t1 INNER JOIN テーブル2 t2 ON t1.結合キー = t2.結合キー WHERE t2.条件; - Oracle: 副問い合わせを使用 
DELETE FROM テーブル1 WHERE 結合キー IN (SELECT 結合キー FROM テーブル2 WHERE 条件); 
 - 標準SQL / PostgreSQL / SQL Server: `USING`句や副問い合わせ、`JOIN`を使用 
 
データ定義 (DDL – Data Definition Language)
データベースオブジェクト(テーブル、インデックスなど)を作成、変更、削除します。
テーブル操作 (TABLE)
- テーブル作成 (CREATE TABLE): 列名、データ型、制約を指定します。 
CREATE TABLE 従業員 ( 従業員ID INT PRIMARY KEY, -- 主キー制約 名前 VARCHAR(100) NOT NULL, -- NOT NULL制約 部署ID INT, 給与 DECIMAL(10, 2) CHECK (給与 >= 0), -- CHECK制約 メールアドレス VARCHAR(255) UNIQUE, -- UNIQUE制約 入社日 DATE DEFAULT CURRENT_DATE, -- デフォルト値 FOREIGN KEY (部署ID) REFERENCES 部署(部署ID) -- 外部キー制約 ); -- AUTO_INCREMENT / IDENTITY / SERIAL (データベース依存) -- MySQL CREATE TABLE 商品 ( 商品ID INT AUTO_INCREMENT PRIMARY KEY, 商品名 VARCHAR(50) ); -- SQL Server CREATE TABLE 商品 ( 商品ID INT IDENTITY(1,1) PRIMARY KEY, 商品名 VARCHAR(50) ); -- PostgreSQL CREATE TABLE 商品 ( 商品ID SERIAL PRIMARY KEY, 商品名 VARCHAR(50) ); -- Oracle (12c以降) CREATE TABLE 商品 ( 商品ID INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, 商品名 VARCHAR2(50) );主なデータ型:
分類 主な型 (例) 説明 数値 `INT`, `INTEGER`, `SMALLINT`, `BIGINT`, `DECIMAL(p,s)`, `NUMERIC(p,s)`, `FLOAT`, `REAL`, `DOUBLE PRECISION` 整数、固定小数点数、浮動小数点数 文字列 `CHAR(n)`, `VARCHAR(n)`, `TEXT`, `NCHAR(n)`, `NVARCHAR(n)` (Unicode) 固定長文字列、可変長文字列、長いテキスト 日付/時刻 `DATE`, `TIME`, `TIMESTAMP`, `DATETIME` (DBによる) 日付、時刻、日付と時刻 真偽値 `BOOLEAN`, `BOOL`, `BIT` (DBによる) 真 (True) または偽 (False) バイナリ `BINARY(n)`, `VARBINARY(n)`, `BLOB` バイナリデータ (画像など) 注意: データ型の名称や機能はデータベース製品によって異なります。
 - テーブル変更 (ALTER TABLE): 列の追加、削除、変更、制約の追加、削除などを行います。 
-- 列の追加 ALTER TABLE 従業員 ADD COLUMN 電話番号 VARCHAR(20); -- 列の削除 ALTER TABLE 従業員 DROP COLUMN 入社日; -- 列のデータ型変更 (DBにより構文差異あり) -- PostgreSQL / SQL Server ALTER TABLE 従業員 ALTER COLUMN 名前 TYPE VARCHAR(150); -- MySQL ALTER TABLE 従業員 MODIFY COLUMN 名前 VARCHAR(150); -- Oracle ALTER TABLE 従業員 MODIFY (名前 VARCHAR2(150)); -- 列名の変更 (DBにより構文差異あり) -- PostgreSQL / Oracle ALTER TABLE 従業員 RENAME COLUMN 電話番号 TO 連絡先; -- MySQL ALTER TABLE 従業員 CHANGE COLUMN 電話番号 連絡先 VARCHAR(20); -- SQL Server EXEC sp_rename '従業員.電話番号', '連絡先', 'COLUMN'; -- 制約の追加 ALTER TABLE 従業員 ADD CONSTRAINT chk_給与 CHECK (給与 > 0); ALTER TABLE 従業員 ADD FOREIGN KEY (部署ID) REFERENCES 部署(部署ID); -- 制約の削除 (制約名が必要な場合が多い) ALTER TABLE 従業員 DROP CONSTRAINT chk_給与; ALTER TABLE 従業員 DROP CONSTRAINT 従業員_部署ID_fkey; -- 制約名はDBや定義により異なる - テーブル削除 (DROP TABLE): テーブルとそのデータ、インデックス、制約などを完全に削除します。 
DROP TABLE 従業員; -- 存在する場合のみ削除 (多くのDBでサポート) DROP TABLE IF EXISTS 従業員; 
インデックス操作 (INDEX)
検索パフォーマンスを向上させるために使用します。
- インデックス作成 (CREATE INDEX):
-- 通常のインデックス CREATE INDEX idx_従業員_名前 ON 従業員 (名前); -- 複合インデックス CREATE INDEX idx_従業員_部署_給与 ON 従業員 (部署ID, 給与 DESC); -- ユニークインデックス (一意制約と似ているが、NULLの扱いに差異がある場合あり) CREATE UNIQUE INDEX uidx_従業員_メール ON 従業員 (メールアドレス); - インデックス削除 (DROP INDEX):
-- MySQL / Oracle / SQL Server DROP INDEX idx_従業員_名前 ON 従業員; -- PostgreSQL DROP INDEX idx_従業員_名前;注意: `DROP INDEX` の構文はデータベースによって異なります。
 
ビュー操作 (VIEW)
一つ以上のテーブルから導出される仮想的なテーブルです。クエリを単純化したり、セキュリティを向上させるために使用します。
- ビュー作成 (CREATE VIEW):
CREATE VIEW 東京顧客 AS SELECT 顧客ID, 名前, メールアドレス FROM 顧客 WHERE 地域 = '東京'; -- ビューを利用したクエリ SELECT * FROM 東京顧客 WHERE 名前 LIKE '田中%'; - ビュー変更 (ALTER VIEW or CREATE OR REPLACE VIEW):
-- SQL Server / PostgreSQLなど ALTER VIEW 東京顧客 AS SELECT 顧客ID, 名前, メールアドレス, 電話番号 -- 列を追加 FROM 顧客 WHERE 地域 = '東京'; -- Oracle / MySQL / PostgreSQLなど CREATE OR REPLACE VIEW 東京顧客 AS SELECT 顧客ID, 名前, メールアドレス, 電話番号 FROM 顧客 WHERE 地域 = '東京'; - ビュー削除 (DROP VIEW):
DROP VIEW 東京顧客; -- 存在する場合のみ削除 DROP VIEW IF EXISTS 東京顧客; 
データベース/スキーマ操作 (DATABASE / SCHEMA)
データベースやスキーマ(データベース内の名前空間)を管理します。
- データベース作成 (CREATE DATABASE): (DBA権限が必要なことが多い) 
CREATE DATABASE 新しいデータベース名; - スキーマ作成 (CREATE SCHEMA): (PostgreSQL, SQL Serverなどで使用) 
CREATE SCHEMA 販売管理スキーマ; -- スキーマを指定してテーブル作成 CREATE TABLE 販売管理スキーマ.商品 ( ... ); - データベース/スキーマ削除 (DROP DATABASE / DROP SCHEMA): (非常に危険な操作!中のオブジェクトも全て削除される) 
DROP DATABASE データベース名; DROP SCHEMA スキーマ名; -- CASCADEオプションが必要な場合あり (中のオブジェクトも削除) DROP SCHEMA IF EXISTS スキーマ名 CASCADE; 
データ制御 (DCL – Data Control Language)
ユーザーのアクセス権限を管理します。
権限付与 (GRANT)
ユーザーまたはロールに対して、データベースオブジェクトへの操作権限を与えます。
- 特定の操作権限を付与:
-- user1 に '商品' テーブルへの SELECT 権限を付与 GRANT SELECT ON 商品 TO user1; -- user2 に '顧客' テーブルへの SELECT, INSERT, UPDATE 権限を付与 GRANT SELECT, INSERT, UPDATE ON 顧客 TO user2; -- public (全ユーザー) に '公開情報' ビューへの SELECT 権限を付与 GRANT SELECT ON 公開情報 TO PUBLIC; -- sales_role ロールに '注文' テーブルへの全権限を付与 GRANT ALL PRIVILEGES ON 注文 TO sales_role; - 権限付与オプション (GRANT OPTION): 他のユーザーに権限を付与する権限も与えます。 
GRANT SELECT ON 顧客 TO manager_user WITH GRANT OPTION; - ロールへの権限付与:
-- ロールの作成 (DBによる) CREATE ROLE sales_staff; -- ロールに権限を付与 GRANT SELECT, INSERT ON 注文 TO sales_staff; -- ユーザーにロールを付与 GRANT sales_staff TO user3; 
権限剥奪 (REVOKE)
ユーザーまたはロールから権限を取り消します。
- 特定の操作権限を剥奪:
-- user1 から '商品' テーブルへの SELECT 権限を剥奪 REVOKE SELECT ON 商品 FROM user1; -- user2 から '顧客' テーブルへの UPDATE 権限を剥奪 REVOKE UPDATE ON 顧客 FROM user2; -- sales_role から '注文' テーブルへの DELETE 権限を剥奪 REVOKE DELETE ON 注文 FROM sales_role; - 権限付与オプション (GRANT OPTION) の剥奪: (DBにより `GRANT OPTION FOR` または `CASCADE` などの指定が異なる) 
-- 例: SQL Server / PostgreSQL REVOKE GRANT OPTION FOR SELECT ON 顧客 FROM manager_user; -- 例: Oracle (CASCADEで付与した権限も連鎖的に剥奪) REVOKE SELECT ON 顧客 FROM manager_user CASCADE; 
トランザクション制御 (TCL – Transaction Control Language)
一連の DML 操作を一つの処理単位(トランザクション)として管理します。
トランザクションは、原子性(Atomicity)、一貫性(Consistency)、独立性(Isolation)、永続性(Durability)という ACID 特性を保証するための仕組みです。
トランザクションの開始
多くのデータベースでは、最初の DML 文 (INSERT, UPDATE, DELETE) が実行された時点で暗黙的にトランザクションが開始されます (自動コミットが無効な場合)。明示的に開始することも可能です。
-- 標準SQL / PostgreSQL / SQL Server など
BEGIN TRANSACTION;
-- または
BEGIN WORK;
-- MySQL
START TRANSACTION; 注意: 自動コミット(Auto Commit)設定が有効な場合、各 DML 文が即座にコミットされるため、明示的なトランザクション制御が必要です。
変更の確定 (COMMIT)
トランザクション内の全ての変更を確定し、データベースに永続的に反映させます。
COMMIT;
-- または
COMMIT WORK; 変更の取り消し (ROLLBACK)
トランザクション内の全ての変更を取り消し、トランザクション開始前の状態に戻します。
ROLLBACK;
-- または
ROLLBACK WORK; セーブポイント (SAVEPOINT)
トランザクション内に中間ポイントを設定し、そこまでロールバックできるようにします。
- セーブポイントの設定:
SAVEPOINT ポイント名; - セーブポイントまでロールバック:
ROLLBACK TO SAVEPOINT ポイント名; - セーブポイントの解放 (任意、COMMIT/ROLLBACKで自動解放されることが多い):
-- Oracle RELEASE SAVEPOINT ポイント名; -- PostgreSQL (標準 SQL 準拠、ただし通常不要) RELEASE SAVEPOINT ポイント名;注意: `RELEASE SAVEPOINT` はサポートされていない、または不要なデータベースもあります。
 
使用例:
BEGIN TRANSACTION;
INSERT INTO テーブルA VALUES (1);
SAVEPOINT sp1;
UPDATE テーブルB SET 列1 = 'X' WHERE ID = 10;
SAVEPOINT sp2;
INSERT INTO テーブルC VALUES (100);
-- 何か問題が発生したので、テーブルCへのINSERTを取り消したい
ROLLBACK TO SAVEPOINT sp2; -- テーブルCへのINSERTが取り消される
-- さらに問題があったので、テーブルBのUPDATEも取り消したい
ROLLBACK TO SAVEPOINT sp1; -- テーブルBのUPDATEも取り消される
-- 最終的に問題なければコミット (この例では最初のINSERTのみが残る)
-- COMMIT;
-- 全てを取り消す場合
-- ROLLBACK; その他の便利な機能・関数
SQL をより強力にする様々な機能
条件分岐 (CASE 式)
条件に応じて返す値を切り替えます。
- 単純 CASE 式: 列の値が特定の値と一致するかで分岐 
SELECT 商品名, 価格帯 = CASE サイズ WHEN 'S' THEN '小' WHEN 'M' THEN '中' WHEN 'L' THEN '大' ELSE 'その他' END FROM 商品; - 検索 CASE 式: より複雑な条件で分岐 
SELECT 商品名, 価格カテゴリ = CASE WHEN 価格 < 1000 THEN '低価格' WHEN 価格 >= 1000 AND 価格 < 5000 THEN '中価格' WHEN 価格 >= 5000 THEN '高価格' ELSE '価格不明' -- NULL の場合など END FROM 商品; - UPDATE 文での利用:
UPDATE 従業員 SET 給与 = CASE 役職 WHEN '部長' THEN 給与 * 1.1 WHEN '課長' THEN 給与 * 1.05 ELSE 給与 END WHERE 評価 = 'A'; 
NULL 値の処理関数
- COALESCE(値1, 値2, …): 引数の中で最初に NULL でない値を返します。全て NULL なら NULL を返します。 
-- 電話番号が NULL なら '未登録' を表示 SELECT 名前, COALESCE(電話番号, '未登録') AS 表示用電話番号 FROM 顧客; - NULLIF(値1, 値2): 値1 と 値2 が等しい場合は NULL を返し、等しくない場合は 値1 を返します。ゼロ除算を防ぐのに使われることがあります。 
-- 数量が 0 の場合に NULL にして平均計算から除外する (例) SELECT AVG(価格 / NULLIF(数量, 0)) FROM 売上明細; - ISNULL(値, 置換値) (SQL Server): 値が NULL なら置換値を返します。 
SELECT 名前, ISNULL(メールアドレス, 'N/A') FROM 従業員; - IFNULL(値, 置換値) (MySQL): 値が NULL なら置換値を返します。`COALESCE`と似ていますが、引数は2つです。 
SELECT 商品名, IFNULL(割引率, 0) FROM 商品; - NVL(値, 置換値) (Oracle): 値が NULL なら置換値を返します。`COALESCE`と似ていますが、引数は2つです。 
SELECT 従業員名, NVL(ボーナス, 0) FROM 給与; 
文字列操作関数
データベース製品によって関数名や挙動が異なる場合が多いです。
| 機能 | 関数例 (標準/代表的) | 説明 | 
|---|---|---|
| 連結 | `||` (標準/PostgreSQL/Oracle), `CONCAT()` (標準/MySQL/PostgreSQL/SQL Server 2012+), `+` (SQL Server) | 文字列を結合する (`SELECT ‘A’ || ‘B’;` or `SELECT CONCAT(‘A’, ‘B’);`) | 
| 長さ | `LENGTH()`, `LEN()` (SQL Server), `CHAR_LENGTH()` | 文字列の長さを返す (`SELECT LENGTH(‘abc’);`) | 
| 部分文字列 | `SUBSTRING(str FROM start FOR len)`, `SUBSTR(str, start, len)` | 文字列の一部を抽出する (`SELECT SUBSTRING(‘abcdef’ FROM 2 FOR 3); — ‘bcd’`) | 
| 置換 | `REPLACE(str, from_str, to_str)` | 文字列中の特定の部分を置換する (`SELECT REPLACE(‘abc abc’, ‘b’, ‘X’); — ‘aXc aXc’`) | 
| 大文字/小文字変換 | `UPPER()`, `LOWER()` | 文字列を大文字または小文字に変換する (`SELECT UPPER(‘abc’), LOWER(‘XYZ’);`) | 
| トリム | `TRIM()`, `LTRIM()`, `RTRIM()` | 文字列の前後の空白(または指定文字)を除去する (`SELECT TRIM(‘ abc ‘); — ‘abc’`) | 
| 位置検索 | `POSITION(substr IN str)`, `INSTR(str, substr)`, `CHARINDEX(substr, str)` (SQL Server) | 文字列内で部分文字列が最初に出現する位置を返す (`SELECT POSITION(‘b’ IN ‘abc’); — 2`) | 
日付/時刻操作関数
データベース製品によって関数名や構文が大きく異なります。
| 機能 | 関数例 (代表的) | 説明 | 
|---|---|---|
| 現在日時取得 | `CURRENT_TIMESTAMP`, `NOW()`, `GETDATE()` (SQL Server), `SYSDATE` (Oracle) | 現在のサーバーの日付と時刻を取得する | 
| 現在日付取得 | `CURRENT_DATE`, `CURDATE()` (MySQL) | 現在の日付を取得する | 
| 日付/時刻要素抽出 | `EXTRACT(unit FROM date)`, `DATE_PART(unit, date)` (PostgreSQL), `YEAR()`, `MONTH()`, `DAY()` (MySQL, SQL Server) | 日付/時刻から年、月、日、時、分などを抽出する (`SELECT EXTRACT(YEAR FROM CURRENT_DATE);`) | 
| 日付/時刻加減算 | `date + INTERVAL ‘n unit’`, `DATE_ADD(date, INTERVAL n unit)`, `DATEADD(unit, n, date)` (SQL Server) | 日付/時刻に期間を加算/減算する (`SELECT CURRENT_DATE + INTERVAL ‘1’ MONTH;`) | 
| 日付/時刻差分計算 | `date1 – date2`, `DATEDIFF(unit, date1, date2)` (SQL Server, MySQL), `AGE(date1, date2)` (PostgreSQL) | 二つの日付/時刻の差を計算する | 
| 書式設定 | `TO_CHAR(date, format)` (Oracle, PostgreSQL), `FORMAT(date, format)` (SQL Server 2012+), `DATE_FORMAT(date, format)` (MySQL) | 日付/時刻を指定した書式に変換する (`SELECT TO_CHAR(NOW(), ‘YYYY/MM/DD HH24:MI:SS’);`) |