SQL 작성 규칙
동적 SQL 태그 구문
동적 SQL 기능을 통해 조건에 따라 SQL 문장을 동적으로 생성할 수 있습니다. 특정 태그를 사용하면 복잡한 SQL 로직을 간편하게 구현할 수 있습니다. 다음은 동적 SQL에서 자주 사용되는 태그와 그 활용법입니다.
1. if 태그
if 태그는 조건 판단에 사용되며, Java의 if 문과 유사합니다.
SELECT * FROM BLOG WHERE state = 'ACTIVE'
<if test="title != null">
AND title like #{title}
</if>파라미터 예시
{
"title": "MyBlog"
}최종 SQL
SELECT * FROM BLOG WHERE state = 'ACTIVE' AND title like ?2. choose, when, otherwise 태그
이들 태그는 Java의 switch 문과 유사합니다.
SELECT * FROM BLOG WHERE state = 'ACTIVE'
<choose>
<when test="title != null">
AND title = #{title}
</when>
<when test="author != null and author.name != null">
AND author_name = #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>파라미터 예시
{
"title": "MyBlog",
"author": {
"name": "AuthorName"
}
}최종 SQL
SELECT * FROM BLOG WHERE state = 'ACTIVE' AND title = ? AND author_name = ?3. trim, where, set 태그
이들 태그는 SQL 문장에서 접두사, 접미사 및 연결어 처리에 사용됩니다.
trim 태그
trim 태그는 사용자 정의 문자열 잘라내기를 지원합니다.
SELECT * FROM BLOG
<trim prefix="WHERE" prefixOverrides="and |or ">
<if test="title != null">
and title like #{title}
</if>
<if test="author != null">
and author_name like #{author.name}
</if>
</trim>파라미터 예시
{
"title": "MyBlog",
"author": {
"name": "AuthorName"
}
}최종 SQL
SELECT * FROM BLOG WHERE title like ? AND author_name like ?where 태그
where 태그는 생성된 SQL 문장 앞에 where 키워드를 자동으로 추가하며, 첫 번째 and 또는 or 키워드를 제거합니다.
SELECT * FROM BLOG
<where>
<if test="title != null">
and title like #{title}
</if>
<if test="author != null">
and author_name like #{author.name}
</if>
</where>파라미터 예시
{
"title": "MyBlog",
"author": {
"name": "AuthorName"
}
}최종 SQL
SELECT * FROM BLOG WHERE title like ? AND author_name like ?set 태그
set 태그는 동적 UPDATE 문을 작성할 때 사용되며, SET 키워드를 자동으로 추가하고 마지막 쉼표를 제거합니다.
UPDATE BLOG
<set>
<if test="title != null">title = #{title},</if>
<if test="author != null">author_name = #{author.name},</if>
</set>
WHERE id = #{id}파라미터 예시
{
"title": "MyBlog",
"author": {
"name": "AuthorName"
},
"id": 123
}최종 SQL
UPDATE BLOG SET title = ?, author_name = ? WHERE id = ?4. foreach 태그
foreach 태그는 주로 컬렉션을 순회하여 IN 조건을 생성하는 데 사용됩니다.
SELECT * FROM BLOG
WHERE id in
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>파라미터 예시
{
"list": [1, 2, 3, 4, 5]
}최종 SQL
SELECT * FROM BLOG WHERE id in (?, ?, ?, ?, ?)5. bind 태그
bind 태그는 변수를 생성하고 OGNL 표현식의 값을 해당 변수에 바인딩하는 데 사용됩니다.
<bind name="pattern" value="'%' + title + '%'" />
SELECT * FROM BLOG
WHERE title LIKE #{pattern}파라미터 예시
{
"title": "MyBlog"
}최종 SQL
SELECT * FROM BLOG WHERE title LIKE ?SQL 파라미터 삽입
동적 SQL에서 #{}와 ${}는 모두 파라미터 참조에 사용되지만, 파라미터 처리 방식에는 몇 가지 중요한 차이가 있습니다.
#{}의 사용법
- 준비 컴파일 처리:
#{}는 JDBC의?자리표시자를 대체하는 역할을 하며, 준비 컴파일 과정을 거쳐PreparedStatement을 통해 파라미터를 설정합니다. - 자동 이스케이프 처리:
#{}는 전달된 파라미터를 자동으로 이스케이프 처리하므로 SQL 인젝션 공격을 효과적으로 방지합니다. - 타입 처리:
#{}는 전달된 파라미터의 타입 변환도 처리합니다.
예시:
SELECT * FROM BLOG WHERE title LIKE #{title}전달된 파라미터 title이 MyBlog일 경우, 최종 SQL은 다음과 같습니다:
SELECT * FROM BLOG WHERE title LIKE ?${}의 사용법
- 직접 치환:
${}는 파라미터 값을 직접 SQL 문장에 삽입하며, 준비 컴파일 과정을 거치지 않습니다. 따라서${}를 사용할 때는 SQL 인젝션 위험을 각별히 주의해야 합니다. - 이스케이프 없음:
${}는 전달된 파라미터를 이스케이프하지 않으므로 동적 테이블명이나 열명을 지정할 때 적합합니다. - 타입 미처리:
${}는 파라미터의 타입을 변환하지 않고, 단순히toString()메서드를 통해 값을 사용합니다.
예시:
SELECT * FROM BLOG WHERE title LIKE '${title}'전달된 파라미터 title이 MyBlog일 경우, 최종 SQL은 다음과 같습니다:
SELECT * FROM BLOG WHERE title LIKE 'MyBlog'사용 시 권장 사항
#{}사용: 대부분의 경우, 특히 사용자 입력이 포함된 상황에서는 SQL 인젝션을 방지하기 위해#{}를 우선적으로 사용하는 것이 좋습니다.${}사용: 동적 테이블명이나 열명을 생성해야 하며, 전달된 파라미터가 안전하다고 확신되는 경우에만${}를 사용합니다.
시스템 내장 변수
DBAPI 시스템에는 현재 클라이언트의 ID를 가져오는 내장 변수인 __clientId가 이미 존재하며, 이를 바로 SQL 파라미터로 사용할 수 있습니다.
사용 예시:
SELECT * FROM users WHERE client_id = #{__clientId}특수 문자 이스케이프
작은 괄호 < 이스케이프
SQL 문장에서 작은 괄호 <는 <로 이스케이프되어야 합니다.
잘못된 예시:
-- 오류: XML 해석 오류 발생
SELECT * FROM users WHERE age < 18올바른 예시:
-- 올바른 방법: 이스케이프 문자 사용
SELECT * FROM users WHERE age < 18