사실 모든 SQL 문을 준비(prepare)할 수 있는 것은 아닙니다. MySQL은 서버 자원 보호와 보안상의 이유로 특정 종류의 SQL 문만 PREPARE 구문으로 준비할 수 있도록 허용하고 있습니다. 이 글에서는 MySQL에서 준비 가능한 SQL 문의 종류를 하나씩 살펴보고, 각 유형별 실제 실행 예제도 함께 확인해 보겠습니다.
준비 가능한 SQL 문의 종류
- SELECT 문 : 테이블에서 데이터를 조회하는 문
- INSERT, REPLACE, UPDATE, DELETE 문 : 데이터를 추가·변경·삭제하는 DML 문
- CREATE TABLE 문 : 새로운 테이블을 생성하는 DDL 문
- SET, DO 및 다양한 SHOW 문 : 변수 설정, 쿼리 실행, 스키마 정보 확인 등에 사용되는 문
그 외에도 ALTER TABLE, CALL, GRANT 등 일부 관리·유틸리티 구문이 준비를 지원하지만, 실무에서 가장 널리 쓰이는 위 네 가지 유형을 중심으로 예제를 살펴보겠습니다.
1. SELECT 문
조회 쿼리에 물음표(?) 플레이스홀더를 배치하고, 실행 시점에 USING 절로 실제 값을 전달하는 방식입니다.
예시
mysql> PREPARE stmt FROM 'SELECT tender_value from Tender WHERE Companyname = ?'; Query OK, 0 rows affected (0.09 sec) Statement prepared mysql> SET @A = 'Singla Group.'; Query OK, 0 rows affected (0.00 sec) mysql> EXECUTE stmt using @A; +--------------+ | tender_value | +--------------+ | 220.255997 | +--------------+ 1 row in set (0.07 sec) mysql> DEALLOCATE PREPARE stmt; Query OK, 0 rows affected (0.00 sec)
2. INSERT, REPLACE, UPDATE, DELETE 문
테이블의 데이터를 수정하는 모든 DML 문도 준비할 수 있습니다. 조건값을 플레이스홀더로 처리하면 동일한 쿼리를 값만 바꿔가며 반복 실행할 때 특히 유용합니다.
예시
mysql> PREPARE stmt1 FROM 'DELETE from Tender WHERE Sr = ?'; Query OK, 0 rows affected (0.00 sec) Statement prepared mysql> SET @A = 4; Query OK, 0 rows affected (0.00 sec) mysql> EXECUTE stmt1; ERROR 1210 (HY000): Unknown error 1210 mysql> EXECUTE stmt1 using @A; Query OK, 1 row affected (0.08 sec) mysql> DEALLOCATE PREPARE stmt1; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM tender; +----+---------------+--------------+ | Sr | CompanyName | Tender_value | +----+---------------+--------------+ | 1 | Abc Corp. | 250.369003 | | 2 | Khaitan Corp. | 265.588989 | | 3 | Singla group. | 220.255997 | +----+---------------+--------------+ 3 rows in set (0.00 sec)
참고 : 플레이스홀더(?)가 포함된 문은 반드시 EXECUTE stmt USING @변수 형태로 값을 전달해야 합니다. 위 예제에서처럼 값을 전달하지 않고 실행하면 ERROR 1210 오류가 발생합니다.
3. CREATE TABLE 문
테이블 구조를 생성하는 DDL 문 역시 준비 대상에 포함됩니다. 다만 테이블 이름이나 컬럼 정의처럼 구조 자체를 동적으로 바꿔야 하는 경우에는 준비된 문보다 별도의 동적 쿼리 처리가 더 적합할 수 있습니다.
예시
mysql> PREPARE stmt3 FROM 'CREATE TABLE Student(Id INT, Name VARCHAR(20))'; Query OK, 0 rows affected (0.00 sec) Statement prepared mysql> EXECUTE stmt3; Query OK, 0 rows affected (0.73 sec) mysql> DEALLOCATE PREPARE stmt3; Query OK, 0 rows affected (0.00 sec)
4. SET, DO 및 SHOW 문
세션 변수 설정에 쓰이는 SET, 단순히 쿼리를 실행만 하는 DO, 그리고 테이블 목록·DB 정보 등을 확인하는 다양한 SHOW 문도 준비할 수 있습니다.
예시
mysql> PREPARE stmt10 FROM 'SHOW TABLES'; Query OK, 0 rows affected (0.00 sec) Statement prepared mysql> EXECUTE stmt10; +-------------------+ | Tables_in_query | +-------------------+ | emp | | emp123 | | emp_t | | examination_btech | | new_number | | student | | student_detail | | student_info | | tender | | website | +-------------------+ 10 rows in set (0.00 sec)
마무리 : 준비된 문의 생명주기
준비된 문(prepared statement)은 다음 세 단계로 관리됩니다.
PREPARE stmt FROM '쿼리': 문을 준비EXECUTE stmt [USING @변수]: 문을 실행DEALLOCATE PREPARE stmt: 문을 해제하여 자원 반환
준비된 문은 세션이 종료되면 자동으로 해제되지만, 같은 문을 반복해서 실행하는 경우라면 사용이 끝난 뒤 명시적으로 DEALLOCATE PREPARE로 해제해 주는 것이 좋습니다. 또한 값이 매번 달라지는 쿼리를 플레이스홀더와 함께 사용하면 SQL 주입 공격을 예방할 수 있고, 쿼리 파싱 비용이 줄어들어 성능 향상에도 도움이 됩니다.