SQL: データ操作
倉庫の管理のようなものです — 荷受け(INSERT)、棚札の調整(UPDATE)、期限切れ商品の撤去(DELETE)、倉庫全体の空所化(TRUNCATE) — データベースのCRUD操作は日常的なデータ管理の核です。操作方法を学ぶことよりも、安全にデータを操作することの方が重要です。
1. 基本概念
| 概念 | 説明 |
|---|---|
INSERT INTO |
テーブルに新しいデータを挿入。単一行および複数行挿入に対応 |
UPDATE ... SET |
テーブルの既存データを変更。必ずWHEREを使用して範囲を限定 |
DELETE FROM |
テーブルから特定の行を削除。必ずWHEREを使用して範囲を限定 |
TRUNCATE TABLE |
テーブルの全データを高速にクリア。DELETEより高速だがより危険 |
| 安全な操作習慣 | DELETE/UPDATEを実行する前に、SELECTで影響範囲を確認 |
⚠️ 重要な警告: WHEREなしのUPDATEとDELETEはテーブルのすべての行に影響します!これは初心者が最もよく犯す壊滅的なミスです。
2. 基本構文
(1) INSERT INTO — データの挿入
SQL
-- 単一行を挿入(列を指定)
INSERT INTO テーブル名 (カラム1, カラム2, カラム3)
VALUES (値1, 値2, 値3);
-- 単一行を挿入(すべての列、テーブル作成順)
INSERT INTO テーブル名
VALUES (値1, 値2, 値3);
-- 複数行を挿入
INSERT INTO テーブル名 (カラム1, カラム2)
VALUES (値1, 値2),
(値3, 値4),
(値5, 値6);
💡 ヒント: 必ず列名を指定することを強く推奨します。 デフォルトの列順序に依存しないでください。テーブル構造が変更された場合(新しい列が追加されるなど)、列名なしのINSERTステートメントはエラーや誤ったデータの挿入を引き起こす可能性があります。
(2) UPDATE — データの更新
SQL
-- 特定の行を更新
UPDATE テーブル名
SET カラム1 = 新しい値1, カラム2 = 新しい値2
WHERE 条件;
-- 式を使用した更新
UPDATE employees
SET salary = salary * 1.1
WHERE department_id = 1;
💡 ヒント: UPDATEを実行する前に、SELECTでWHERE条件がどの行にマッチするか確認してください。例えば、まず
SELECT * FROM employees WHERE department_id = 1;を実行して、何行が影響を受けるかを確認します。
(3) DELETE — データの削除
SQL
-- 特定の行を削除
DELETE FROM テーブル名
WHERE 条件;
-- すべての行を削除(行ごとに削除、テーブル構造は保持)
DELETE FROM テーブル名;
💡 ヒント: 削除されたデータはトランザクションロールバックで回復可能です(トランザクション内であれば)。ただし、コミット後は回復できません。SELECTしてからDELETEする習慣をつけましょう。
(4) TRUNCATE — テーブルのクリア
SQL
-- テーブル全体をクリア(テーブル構造は保持)
TRUNCATE TABLE テーブル名;
💡 ヒント: SQLiteでのTRUNCATEは
DELETE FROM テーブル名と等価です(SQLiteはTRUNCATE構文をサポートしていません)。MySQL/PostgreSQLでは、TRUNCATEはDELETEよりはるかに高速です。行ごとに削除せず、自動採番IDをリセットします。
(5) INSERT vs DELETE vs TRUNCATEの比較
| 操作 | 効果 | ロールバック可能 | 自動採番IDリセット | 速度 |
|---|---|---|---|---|
INSERT |
新しい行を挿入 | ✅ | — | — |
DELETE |
行ごとに削除(WHERE使用可能) | ✅ | ❌ | 遅い |
TRUNCATE |
テーブル全体をクリア | ❌ | ✅ | 速い |
3. コード例
(1) サンプル:従業員と部署データの挿入(難易度⭐)
部署テーブルと従業員テーブルに初期データを挿入します。
SQL
-- まず部署データを挿入
INSERT INTO departments (name, location)
VALUES ('Engineering', 'New York'),
('Marketing', 'Los Angeles'),
('Finance', 'New York');
-- 次に従業員データを挿入
INSERT INTO employees (name, department_id, salary, hire_date)
VALUES ('John', 1, 15000.00, '2023-01-15'),
('Jane', 1, 18000.00, '2022-06-01'),
('Bob', 2, 12000.00, '2023-03-20'),
('Alice', 3, 13000.00, '2021-11-10');
-- 挿入結果を確認
SELECT * FROM departments;
出力:
TEXT
📖 参照専用
id name location
-- ----------- ----------
1 Engineering New York
2 Marketing Los Angeles
3 Finance New York
(2) サンプル:従業員給与の安全な更新(難易度⭐⭐)
エンジニアリング部門の全従業員に10%の昇給を与えます。まず確認してから実行します。
SQL
-- ステップ1:SELECTで影響範囲を確認
SELECT name, salary
FROM employees
WHERE department_id = 1;
更新前:
TEXT
📖 参照専用
name salary
------ --------
John 15000.00
Jane 18000.00
SQL
-- ステップ2:確認後に更新を実行
UPDATE employees
SET salary = salary * 1.1
WHERE department_id = 1;
-- ステップ3:更新結果を確認
SELECT name, salary
FROM employees
WHERE department_id = 1;
更新後:
TEXT
📖 参照専用
name salary
------ --------
John 16500.00
Jane 19800.00
(3) サンプル:削除とクリア操作の比較(難易度⭐⭐⭐)
DELETEとTRUNCATEの動作の違いを比較します。
SQL
-- 一時テストテーブルを作成
CREATE TABLE test_delete (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT
);
-- テストデータを挿入
INSERT INTO test_delete (name) VALUES ('A'), ('B'), ('C');
-- DELETEで特定の行を削除
DELETE FROM test_delete WHERE name = 'B';
SELECT * FROM test_delete;
出力:
TEXT
📖 参照専用
id name
-- ----
1 A
3 C
SQL
-- DELETEで残りのデータをクリア
DELETE FROM test_delete;
-- 新しいデータを挿入し、自動採番IDを確認
INSERT INTO test_delete (name) VALUES ('D');
SELECT * FROM test_delete;
出力(IDが4から始まっていることに注目。自動採番IDはリセットされていない):
TEXT
📖 参照専用
id name
-- ----
4 D
💡 MySQLでは、
TRUNCATE TABLE test_delete;でテーブルをクリアすると、新しいデータの挿入時にIDが1から再開します。
4. 主な応用シナリオ
(1) シナリオ1:バッチデータインポート
一時テーブルや外部データソースからバッチインポートします:
SQL
-- 高給従業員をバックアップテーブルにコピー
INSERT INTO employees_backup (name, department_id, salary, hire_date)
SELECT name, department_id, salary, hire_date
FROM employees
WHERE salary > 15000;
(2) シナリオ2:条件付きバッチ更新
特定の条件下でデータを調整します:
SQL
-- 入社から3年以上3年以上経過した従業員に5%の昇給
UPDATE employees
SET salary = salary * 1.05
WHERE hire_date < DATE('now', '-3 years');
▶ サンプル
SQL
INSERT INTO users (name, age) VALUES ('田中', 30);
❓ よくある質問
Q DELETEとTRUNCATEの両方でテーブルをクリアできます。どちらを使うべきですか?
A
Q WHERE条件を忘れてテーブル全体を更新してしまいましたどうすればいいですか?
A
Q INSERT時に特定の列を入力したくない場合はどうすればいいですか?
A
Q SQLiteはTRUNCATEをサポートしていますか?
A
📖 まとめ
- INSERT INTOはデータの挿入に使用。常に列名を指定。複数行の同時挿入に対応
- UPDATE SETはデータの更新に使用。必ずWHERE条件を使用。そうしないとテーブル全体が更新されます
- DELETE FROMはデータの削除に使用。必ずWHERE条件を使用。そうしないとテーブル全体が削除されます
- TRUNCATE TABLEはテーブル全体の高速クリアに使用。DELETEより高速だがロールバック不可
- 安全な習慣:DELETEまたはUPDATEを実行する前に、SELECTで影響範囲を確認
- SQLiteはTRUNCATEをサポートしていません。代わりに
DELETE FROM テーブル名を使用
📝 練習問題
(1) 演習1(⭐)
以下の商品データをproductsテーブルに挿入し、クエリで確認してください:
| name | category | price | stock |
|---|---|---|---|
| iPhone 15 | Phone | 5999.00 | 100 |
| MacBook Pro | Computer | 12999.00 | 50 |
| AirPods Pro | Accessory | 1899.00 | 200 |
| iPad Air | Tablet | 4799.00 | 80 |
(2) 演習2(⭐⭐)
以下の操作を完了してください。各ステップの前にSELECTで確認してください:
- 在庫が100未満のすべての商品の価格を5%引き上げ
- 「Accessory」カテゴリの商品の在庫を50増加
- 価格が2000未満の商品を削除
(3) 演習3(⭐⭐⭐)
「商品の販売停止」プロセスをシミュレート:
- 在庫が0の商品をproductsテーブルから新しいproducts_offlineテーブルにコピー(まずテーブルを作成)
- productsテーブルからこれらの在庫切れ商品を削除
- 両方のテーブルのデータが正しいことを確認
5. 次のレッスン
👉 05-データ型