MeWrite Docs

SQL syntax error near

SQLクエリに構文エラーがある場合のエラー

概要

SQLクエリを実行する際に、構文エラーがある場合に発生するエラーです。キーワードのタイプミス、引用符の問題、予約語の使用などが原因です。

エラーメッセージ

You have an error in your SQL syntax; check the manual... near 'xxx' at line 1
ERROR: syntax error at or near "xxx"
sqlite3.OperationalError: near "xxx": syntax error

原因

  1. キーワードのタイプミス: SELECT、FROMなどのスペルミス
  2. 予約語をカラム名に使用: order、user、tableなどを引用符なしで使用
  3. 引用符の問題: シングルクォートとダブルクォートの混同
  4. カンマの過不足: 余分なカンマ、足りないカンマ
  5. 括弧の不一致: 開き括弧と閉じ括弧が合わない
  6. データベース方言の違い: MySQL、PostgreSQL、SQLiteでの構文差異

解決策

1. 予約語のエスケープ

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
-- Bad: 予約語をそのまま使用
SELECT order, user FROM orders;

-- Good: MySQL(バッククォート)
SELECT `order`, `user` FROM `orders`;

-- Good: PostgreSQL/標準SQL(ダブルクォート)
SELECT "order", "user" FROM "orders";

-- Good: SQL Server(角括弧)
SELECT [order], [user] FROM [orders];

2. 文字列の引用符

1
2
3
4
5
6
7
8
9
-- Bad: 文字列にダブルクォート(MySQLでエラーの可能性)
SELECT * FROM users WHERE name = "John";

-- Good: 文字列はシングルクォート
SELECT * FROM users WHERE name = 'John';

-- シングルクォートを含む文字列
SELECT * FROM users WHERE name = 'O''Brien';  -- エスケープ
SELECT * FROM users WHERE name = 'O\'Brien';   -- バックスラッシュ(MySQL)

3. カンマの確認

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
-- Bad: 余分なカンマ
SELECT name, email, FROM users;

-- Good: 正しいカンマ
SELECT name, email FROM users;

-- Bad: カンマ不足
SELECT name email FROM users;

-- Good: カンマを追加
SELECT name, email FROM users;

4. JOIN構文

1
2
3
4
5
6
7
8
-- Bad: ON句がない
SELECT * FROM users JOIN orders;

-- Good: ON句を追加
SELECT * FROM users JOIN orders ON users.id = orders.user_id;

-- Good: USING句
SELECT * FROM users JOIN orders USING (user_id);

5. INSERT構文

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
-- Bad: VALUESのスペルミス
INSERT INTO users (name, email) VALUE ('John', 'john@example.com');

-- Good: VALUES(複数形)
INSERT INTO users (name, email) VALUES ('John', 'john@example.com');

-- 複数行挿入
INSERT INTO users (name, email) VALUES
  ('John', 'john@example.com'),
  ('Jane', 'jane@example.com');

6. UPDATE構文

1
2
3
4
5
6
7
8
-- Bad: SETがない
UPDATE users name = 'John' WHERE id = 1;

-- Good: SET句を追加
UPDATE users SET name = 'John' WHERE id = 1;

-- 複数カラム更新
UPDATE users SET name = 'John', email = 'john@example.com' WHERE id = 1;

7. GROUP BY / ORDER BY

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
-- Bad: HAVING without GROUP BY
SELECT category, COUNT(*)
FROM products
HAVING COUNT(*) > 5;

-- Good: GROUP BY を追加
SELECT category, COUNT(*)
FROM products
GROUP BY category
HAVING COUNT(*) > 5;

-- ORDER BY の位置
SELECT * FROM users
WHERE active = true
ORDER BY created_at DESC  -- ORDER BY は最後
LIMIT 10;

8. LIMIT / OFFSET(方言の違い)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
-- MySQL / PostgreSQL / SQLite
SELECT * FROM users LIMIT 10 OFFSET 20;

-- SQL Server
SELECT * FROM users
ORDER BY id
OFFSET 20 ROWS
FETCH NEXT 10 ROWS ONLY;

-- Oracle
SELECT * FROM users
WHERE ROWNUM <= 10;

9. サブクエリ

1
2
3
4
5
-- Bad: サブクエリにエイリアスがない(MySQLでエラー)
SELECT * FROM (SELECT * FROM users WHERE active = true);

-- Good: エイリアスを追加
SELECT * FROM (SELECT * FROM users WHERE active = true) AS active_users;

10. CASE文

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
-- Bad: 構文エラー
SELECT
  CASE status
    WHEN 'active' 'Active User'
  END
FROM users;

-- Good: THENを追加
SELECT
  CASE status
    WHEN 'active' THEN 'Active User'
    WHEN 'inactive' THEN 'Inactive User'
    ELSE 'Unknown'
  END AS status_label
FROM users;

11. データ型のキャスト

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
-- PostgreSQL
SELECT CAST(id AS VARCHAR(10)) FROM users;
SELECT id::VARCHAR(10) FROM users;

-- MySQL
SELECT CAST(id AS CHAR(10)) FROM users;

-- SQL Server
SELECT CAST(id AS NVARCHAR(10)) FROM users;
SELECT CONVERT(NVARCHAR(10), id) FROM users;

12. 動的SQLのエスケープ

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// Bad: SQLインジェクションの脆弱性
const query = `SELECT * FROM users WHERE name = '${name}'`;

// Good: プレースホルダーを使用
const query = 'SELECT * FROM users WHERE name = ?';
connection.query(query, [name]);

// Good: Named parameters
const query = 'SELECT * FROM users WHERE name = :name';
connection.query(query, { name: name });

データベース別の違い

機能MySQLPostgreSQLSQLite
識別子引用符`backtick`“double”“double” または `backtick`
文字列連結CONCAT()||||
自動増分AUTO_INCREMENTSERIALAUTOINCREMENT
LIMITLIMIT nLIMIT nLIMIT n

よくある間違い

  • 文字列にダブルクォートを使用(MySQLのSTRICTモード)
  • 予約語をカラム名に使用してエスケープしない
  • クエリの最後にセミコロンを複数つける
  • プレースホルダーを使わず文字列連結

関連エラー

参考リンク

SQL の他のエラー

最終更新: 2025-12-13