Skip to content

SQL 작성 규칙

동적 SQL 태그 구문

동적 SQL 기능을 통해 조건에 따라 SQL 문장을 동적으로 생성할 수 있습니다. 특정 태그를 사용하면 복잡한 SQL 로직을 간편하게 구현할 수 있습니다. 다음은 동적 SQL에서 자주 사용되는 태그와 그 활용법입니다.

1. if 태그

if 태그는 조건 판단에 사용되며, Java의 if 문과 유사합니다.

xml
SELECT * FROM BLOG WHERE state = 'ACTIVE'
<if test="title != null">
  AND title like #{title}
</if>

파라미터 예시

json
{
  "title": "MyBlog"
}

최종 SQL

sql
SELECT * FROM BLOG WHERE state = 'ACTIVE' AND title like ?

2. choose, when, otherwise 태그

이들 태그는 Java의 switch 문과 유사합니다.

xml
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>

파라미터 예시

json
{
  "title": "MyBlog",
  "author": {
    "name": "AuthorName"
  }
}

최종 SQL

sql
SELECT * FROM BLOG WHERE state = 'ACTIVE' AND title = ? AND author_name = ?

3. trim, where, set 태그

이들 태그는 SQL 문장에서 접두사, 접미사 및 연결어 처리에 사용됩니다.

trim 태그

trim 태그는 사용자 정의 문자열 잘라내기를 지원합니다.

xml
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>
파라미터 예시
json
{
  "title": "MyBlog",
  "author": {
    "name": "AuthorName"
  }
}
최종 SQL
sql
SELECT * FROM BLOG WHERE title like ? AND author_name like ?

where 태그

where 태그는 생성된 SQL 문장 앞에 where 키워드를 자동으로 추가하며, 첫 번째 and 또는 or 키워드를 제거합니다.

xml
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>
파라미터 예시
json
{
  "title": "MyBlog",
  "author": {
    "name": "AuthorName"
  }
}
최종 SQL
sql
SELECT * FROM BLOG WHERE title like ? AND author_name like ?

set 태그

set 태그는 동적 UPDATE 문을 작성할 때 사용되며, SET 키워드를 자동으로 추가하고 마지막 쉼표를 제거합니다.

xml
UPDATE BLOG
<set>
  <if test="title != null">title = #{title},</if>
  <if test="author != null">author_name = #{author.name},</if>
</set>
WHERE id = #{id}
파라미터 예시
json
{
  "title": "MyBlog",
  "author": {
    "name": "AuthorName"
  },
  "id": 123
}
최종 SQL
sql
UPDATE BLOG SET title = ?, author_name = ? WHERE id = ?

4. foreach 태그

foreach 태그는 주로 컬렉션을 순회하여 IN 조건을 생성하는 데 사용됩니다.

xml
SELECT * FROM BLOG
WHERE id in
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
  #{item}
</foreach>

파라미터 예시

json
{
  "list": [1, 2, 3, 4, 5]
}

최종 SQL

sql
SELECT * FROM BLOG WHERE id in (?, ?, ?, ?, ?)

5. bind 태그

bind 태그는 변수를 생성하고 OGNL 표현식의 값을 해당 변수에 바인딩하는 데 사용됩니다.

xml
<bind name="pattern" value="'%' + title + '%'" />
SELECT * FROM BLOG
WHERE title LIKE #{pattern}

파라미터 예시

json
{
  "title": "MyBlog"
}

최종 SQL

sql
SELECT * FROM BLOG WHERE title LIKE ?

SQL 파라미터 삽입

동적 SQL에서 #{}${}는 모두 파라미터 참조에 사용되지만, 파라미터 처리 방식에는 몇 가지 중요한 차이가 있습니다.

#{}의 사용법

  1. 준비 컴파일 처리: #{}는 JDBC의 ? 자리표시자를 대체하는 역할을 하며, 준비 컴파일 과정을 거쳐 PreparedStatement을 통해 파라미터를 설정합니다.
  2. 자동 이스케이프 처리: #{}는 전달된 파라미터를 자동으로 이스케이프 처리하므로 SQL 인젝션 공격을 효과적으로 방지합니다.
  3. 타입 처리: #{}는 전달된 파라미터의 타입 변환도 처리합니다.

예시:

sql
SELECT * FROM BLOG WHERE title LIKE #{title}

전달된 파라미터 titleMyBlog일 경우, 최종 SQL은 다음과 같습니다:

sql
SELECT * FROM BLOG WHERE title LIKE ?

${}의 사용법

  1. 직접 치환: ${}는 파라미터 값을 직접 SQL 문장에 삽입하며, 준비 컴파일 과정을 거치지 않습니다. 따라서 ${}를 사용할 때는 SQL 인젝션 위험을 각별히 주의해야 합니다.
  2. 이스케이프 없음: ${}는 전달된 파라미터를 이스케이프하지 않으므로 동적 테이블명이나 열명을 지정할 때 적합합니다.
  3. 타입 미처리: ${}는 파라미터의 타입을 변환하지 않고, 단순히 toString() 메서드를 통해 값을 사용합니다.

예시:

xml
SELECT * FROM BLOG WHERE title LIKE '${title}'

전달된 파라미터 titleMyBlog일 경우, 최종 SQL은 다음과 같습니다:

sql
SELECT * FROM BLOG WHERE title LIKE 'MyBlog'

사용 시 권장 사항

  • #{} 사용: 대부분의 경우, 특히 사용자 입력이 포함된 상황에서는 SQL 인젝션을 방지하기 위해 #{}를 우선적으로 사용하는 것이 좋습니다.
  • ${} 사용: 동적 테이블명이나 열명을 생성해야 하며, 전달된 파라미터가 안전하다고 확신되는 경우에만 ${}를 사용합니다.

시스템 내장 변수

DBAPI 시스템에는 현재 클라이언트의 ID를 가져오는 내장 변수인 __clientId가 이미 존재하며, 이를 바로 SQL 파라미터로 사용할 수 있습니다.

사용 예시:

sql
SELECT * FROM users WHERE client_id = #{__clientId}

특수 문자 이스케이프

작은 괄호 < 이스케이프

SQL 문장에서 작은 괄호 <&lt;로 이스케이프되어야 합니다.

잘못된 예시:

sql
-- 오류: XML 해석 오류 발생
SELECT * FROM users WHERE age < 18

올바른 예시:

sql
-- 올바른 방법: 이스케이프 문자 사용
SELECT * FROM users WHERE age &lt; 18