준비된 문 사용하기

준비된 문 사용하기 (Using prepared statements)

반복해서 쓰려고 준비된 문(prepared statement)을 정의할 수 있어요. 코드가 데이터베이스 연산을 수행할 때마다 문을 다시 만드는 오버헤드를 피할 수 있어서, 코드가 조금 더 빠르게 동작하는 데 도움이 됩니다.

출처: Go 공식 문서

참고: 준비된 문 안의 파라미터 자리 표시자는 사용하는 DBMS와 드라이버에 따라 달라져요. 예를 들어 Postgres용 pq 드라이버? 대신 $1 같은 자리 표시자를 요구합니다.

준비된 문이란?

준비된 문은 DBMS가 파싱해서 저장해 두는 SQL입니다. 대개 자리 표시자를 포함하지만 실제 파라미터 값은 없어요. 나중에 그 문을 파라미터 값 집합과 함께 실행할 수 있습니다.

준비된 문 사용 방법

같은 SQL을 반복해서 실행할 것 같다면, sql.Stmt로 SQL 문을 미리 준비해 두고 필요할 때마다 실행할 수 있어요.

다음 예시는 데이터베이스에서 특정 앨범을 선택하는 준비된 문을 만듭니다. DB.Prepare는 주어진 SQL 텍스트에 대한 준비된 문을 나타내는 sql.Stmt를 반환해요. SQL 문의 파라미터를 Stmt.Exec, Stmt.QueryRow, Stmt.Query에 넘겨 문을 실행할 수 있습니다.

// AlbumByID retrieves the specified album.
func AlbumByID(id int) (Album, error) {
    // Define a prepared statement. You'd typically define the statement
    // elsewhere and save it for use in functions such as this one.
    stmt, err := db.Prepare("SELECT * FROM album WHERE id = ?")
    if err != nil {
        log.Fatal(err)
    }
    defer stmt.Close()

    var album Album

    // Execute the prepared statement, passing in an id value for the
    // parameter whose placeholder is ?
    err := stmt.QueryRow(id).Scan(&album.ID, &album.Title, &album.Artist, &album.Price, &album.Quantity)
    if err != nil {
        if err == sql.ErrNoRows {
            // Handle the case of no rows returned.
        }
        return album, err
    }
    return album, nil
}

준비된 문의 동작

준비된 sql.Stmt는 문을 호출하기 위한 일반적인 Exec, QueryRow, Query 메서드를 제공합니다. 이 메서드들의 사용법은 Querying for dataExecuting SQL statements that don't return data에서 더 자세히 볼 수 있어요.

다만 sql.Stmt는 이미 미리 설정된 SQL 문을 나타내므로, 그 Exec, QueryRow, Query 메서드는 SQL 텍스트를 생략하고 자리 표시자에 해당하는 SQL 파라미터 값만 받습니다.

sql.Stmt는 어떻게 사용할지에 따라 여러 방식으로 정의할 수 있어요.

  • DB.PrepareDB.PrepareContextDB.ExecDB.Query처럼, 트랜잭션 밖에서 단독으로 실행할 수 있는 준비된 문을 만듭니다.
  • Tx.Prepare, Tx.PrepareContext, Tx.Stmt, Tx.StmtContext는 특정 트랜잭션 안에서 사용할 준비된 문을 만듭니다. PreparePrepareContext는 SQL 텍스트로 문을 정의하고, StmtStmtContextDB.PrepareDB.PrepareContext의 결과를 사용합니다. 즉, 트랜잭션용이 아닌 sql.Stmt를 이 트랜잭션용 sql.Stmt로 변환하는 것이죠.
  • Conn.PrepareContext는 예약된 연결을 나타내는 sql.Conn에서 준비된 문을 만듭니다.

코드가 문 사용을 마쳤을 때 stmt.Close가 호출되도록 하세요. 이렇게 하면 그 문과 연관된 데이터베이스 리소스(예: 기본 연결)를 해제합니다. 함수의 지역 변수로만 쓰이는 문이라면 defer stmt.Close()로 충분해요.

준비된 문을 만드는 함수

함수 설명
DB.Prepare
DB.PrepareContext
단독으로 실행하거나 Tx.Stmt로 트랜잭션 내부 문으로 변환할 문을 준비합니다.
Tx.Prepare
Tx.PrepareContext
Tx.Stmt
Tx.StmtContext
특정 트랜잭션에서 사용할 문을 준비합니다. 자세한 내용은 Executing transactions 참고.
Conn.PrepareContext 예약된 연결과 함께 사용합니다. 자세한 내용은 Managing connections 참고.

더 알아보기 (Learn more)