SQL 쿼리를 실행할 때 갑자기 ERROR 1064가 튀어나오면 당황스럽다. 특히 복잡한 JOIN이나 서브쿼리를 작성했을 때는 어디가 문제인지 찾기도 힘들다. 다만 대부분의 개발자들은 에러 메시지의 "near ~" 부분을 무시하고, 스택오버플로우에서 임의로 찾은 쿼리를 복사 붙여넣기만 한다. 이번에는 ERROR 1064가 정확히 뭔지, 왜 발생하는지, 그리고 실제 프로젝트에서 빠르게 해결하는 방법을 완벽하게 정리해서 소개하겠다.

 

MySQL ERROR 1064란 무엇인가
SQL 문법이 MySQL 서버가 인식하지 못하는 형태로 작성되었을 때 발생하는 에러다. 단순한 오타부터 시작해서 MySQL 버전 호환성, 예약어 충돌, 따옴표 오류까지 다양한 원인이 있다. 에러 메시지를 자세히 보면 "near '문제 부분' at line X" 형태로 문제가 발생한 지점을 지시해준다.

예를 들어 다음과 같은 쿼리를 실행하면 ERROR 1064를 만난다.

SELECT * FROM users WHERE user_id = 1 GROUP BY user_id HAVING COUNT(*) > 1;

이건 문법상 문제는 없지만, SELECT 뒤에 모든 칼럼을 선택했는데 GROUP BY로 묶었으므로 실제로는 다른 에러(ONLY_FULL_GROUP_BY)가 난다. ERROR 1064는 더 근본적인 SQL 문법 자체가 틀렸을 때 발생한다.

 

ERROR 1064 발생 원인과 해결법 5가지
1. 예약어를 칼럼명으로 사용한 경우

MySQL의 예약어(SELECT, FROM, WHERE 등)를 칼럼명으로 그냥 사용하면 문법 오류가 난다.

✗ 잘못된 코드
SELECT id, select, name FROM users;

✓ 올바른 코드
SELECT id, `select`, name FROM users;

백틱(backtick, `) 기호로 감싸면 MySQL은 이를 식별자로 인식한다. 예약어뿐만 아니라 공백이나 특수문자가 포함된 칼럼명도 백틱으로 감싸야 한다.

2. 따옴표 불일치 또는 이스케이프 누락

문자열을 싱글 쿼트로 감싸면서, 문자열 내부에 싱글 쿼트가 있으면 이스케이프 처리를 해야 한다.

✗ 잘못된 코드
SELECT * FROM users WHERE name = 'John's';

✓ 올바른 코드
SELECT * FROM users WHERE name = 'John\'s';
또는
SELECT * FROM users WHERE name = 'John''s';

PHP에서 mysqli나 PDO를 사용한다면 Prepared Statement를 쓰는 게 훨씬 낫다. 자동으로 이스케이프 처리된다.

✓ Prepared Statement 사용
$stmt = $mysqli->prepare("SELECT * FROM users WHERE name = ?");
$stmt->bind_param("s", $name);
$name = "John's";
$stmt->execute();
3. 함수명 오타나 지원하지 않는 함수

MySQL 버전에 따라 지원하지 않는 함수가 있다. 또는 함수명을 잘못 입력했을 수도 있다.

✗ 잘못된 코드 (함수명 오타)
SELECT CONCAT_WS(', ', firstname, lastname) FROM users;
-- CONCAT_WS는 MySQL 4.0.6+에서 지원하는데, 오래된 버전에서는 작동 안 함

✓ 올바른 코드 (호환성 확인)
SELECT CONCAT(firstname, ' ', lastname) FROM users;
4. 괄호 불일치

복잡한 쿼리에서 괄호를 빼먹거나 과도하게 넣으면 ERROR 1064가 발생한다.

✗ 잘못된 코드
SELECT * FROM users WHERE (id = 1 AND name = 'John';

✓ 올바른 코드
SELECT * FROM users WHERE (id = 1 AND name = 'John');
5. MySQL 버전 호환성 문제

MySQL 5.7과 8.0 사이에 문법이 바뀐 부분들이 있다. 특히 윈도우 함수나 CTE(Common Table Expression) 같은 기능은 8.0 이상에서만 지원된다.

✗ MySQL 5.7에서 에러 발생
WITH user_rank AS (
  SELECT id, name, ROW_NUMBER() OVER (ORDER BY id) as rank FROM users
)
SELECT * FROM user_rank WHERE rank = 1;

✓ MySQL 5.7 호환성 유지
SELECT id, name FROM users ORDER BY id LIMIT 1;

 

PHP에서 ERROR 1064 디버깅하기

쿼리 문법 오류는 PHP 측에서도 감지할 수 있다. 에러 메시지를 정확히 출력하는 습관을 들이자.

✗ 나쁜 예 (에러 메시지 무시)
$result = $mysqli->query("SELECT * FROM users WHERE user_id = 1");
if (!$result) {
  echo "쿼리 실패";
}

✓ 좋은 예 (에러 메시지 출력)
$result = $mysqli->query("SELECT * FROM users WHERE user_id = 1");
if (!$result) {
  echo "에러: " . $mysqli->error;
  echo "에러 번호: " . $mysqli->errno;
}

PDO를 사용한다면 예외 처리로 더 명확하게 에러를 잡을 수 있다.

try {
  $pdo = new PDO("mysql:host=localhost;dbname=test", "user", "password");
  $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  $stmt = $pdo->query("SELECT * FROM users WHERE user_id = 1");
} catch (PDOException $e) {
  echo "쿼리 에러: " . $e->getMessage();
}

 

쿼리 에러 빠르게 찾는 팁
상황 해결 방법
긴 쿼리에서 에러 위치를 모를 때 에러 메시지의 "near" 부분 앞뒤로 부분 쿼리를 만들어 테스트해보기
WHERE 절에만 조건이 있을 때 WHERE 뒤에 공백 확인, 연산자(=, <>, IN 등) 철저히 검토
JOIN 쿼리 오류 ON 절의 테이블 별칭 일치 확인, 괄호 개수 재확인
동적으로 쿼리를 조립할 때 Prepared Statement 또는 query builder(예: Doctrine, Eloquent) 사용 강력 추천

 

실전 예제: 자주 마주치는 ERROR 1064

사용자 이름에 특수문자가 있는데 WHERE 절을 동적으로 만드는 경우를 보자.

✗ 위험한 방식
$name = "O'Brien";
$query = "SELECT * FROM users WHERE name = '" . $name . "'";
// 결과: SELECT * FROM users WHERE name = 'O'Brien';
// ERROR 1064 발생

✓ Prepared Statement 사용
$stmt = $mysqli->prepare("SELECT * FROM users WHERE name = ?");
$stmt->bind_param("s", $name);
$name = "O'Brien";
$stmt->execute();
$result = $stmt->get_result();

또 다른 흔한 사례로, 칼럼명이 MySQL 예약어인 경우가 있다.

✗ 위험한 방식
$query = "SELECT id, select, status FROM users";
// ERROR 1064: 'select'는 예약어

✓ 올바른 방식
$query = "SELECT id, `select`, status FROM users";

✓ 또는 칼럼 별칭 사용
$query = "SELECT id, `select` AS select_type, status FROM users";

 

ERROR 1064 예방 체크리스트
  • 모든 문자열 값은 싱글 쿼트로 감싸기
  • 칼럼명이나 테이블명에 공백이나 특수문자가 있으면 백틱으로 감싸기
  • WHERE, JOIN 조건문에서 괄호 개수 확인하기
  • 복잡한 쿼리는 Prepared Statement로 작성하기
  • MySQL 버전 호환성 확인하기(특히 8.0 이상의 새 기능 사용 시)
  • 에러 메시지를 무시하지 말고, 정확한 "near" 부분 확인하기

ERROR 1064는 단순한 오타나 문법 실수로 인한 것이 대부분이므로, 에러 메시지를 꼼꼼히 읽고 해당 부분을 차근차근 점검하면 쉽게 해결된다. 특히 Prepared Statement를 습관처럼 사용하면 이런 문제의 절반 이상을 미리 방지할 수 있다. 이 글의 Prepared Statement와 백틱 처리 부분을 참고해 현재 프로젝트의 쿼리들을 점검해보면, 숨겨진 SQL 버그들을 미리 찾아낼 수 있을 것이다.