Golang database/sql 패키지 삽질기 - 1편 매개변수 표시자
필자는 주로 자바로 개발해 왔는데 최근 Golang으로 개발하면서 데이터베이스를 다룰 일이 생겼다. Golang에서는 자바의 JDBC와 같은 database/sql 패키지를 제공한다.
이 글은 Golang 초심자로서 필자가 database/sql 패키지를 사용하면서 겪었던 삽질기 중 1편으로 매개변수 표시자Parameter Placeholder에 대한 글이다.
- 매개변수 표시자
- SQLite 메모리 데이터베이스
- 커넥션 풀
Unknown column?
아래는 database/sql 패키지를 사용하여 데이터베이스 parent 테이블에서 id가 '1'인 열의 name 컬럼을 조회하는 코드이다. 데이터베이스로는 SQLite를 사용하고 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
package main import ( "database/sql" _ "github.com/mattn/go-sqlite3" "log" ) func main() { db, err := sql.Open("sqlite3", ":memory:") if err != nil { log.Fatal(err) } defer db.Close() // ... var parentName string row := db.QueryRow("SELECT name FROM parent WHERE id = $1", 1) err = row.Scan(&parentName) if err != nil { log.Fatal(err) } fmt.Println(parentName) }
코드를 실행해 보면 잘 동작하는 것을 확인할 수 있다.
이제 같은 코드를 데이터베이스만 MySQL로 변경해서 실행해 보면 Unknown column 오류를 만난다.
1 2 3 4 5 6 7 8 9 10
package main import ( // ... _ "github.com/go-sql-driver/mysql" ) func main() { db, err := sql.Open("mysql", "root:1111@tcp(127.0.0.1:3306)/article") // ... }
왜 같은 코드임에도 불구하고 SQLite는 동작하고 MySQL은 동작하지 않는 걸까? 답은 database/sql 패키지 문서에서 찾을 수 있다.
매개변수 표시자Parameter Placeholder
Golang에서는 Prepared Statement를 사용할 때 SQL문에 '$1'처럼 대체되는 것을 매개변수 표시자라고 한다. 아래 코드는 '$1' 매개변수 표시자에 실제 값 1로 대체하여 SQL을 실행한다.
1
row := db.QueryRow("SELECT name FROM parent WHERE id = $1", 1)
매개변수 표시자는 문법이 있으니... 데이터베이스마다 다르게 써야 한다는 것이다!

출처 : http://go-database-sql.org/prepared.html
결론
매개변수 표시자를 사용할 때에는 사용하는 데이터베이스마다 다르게 써야 한다. 예시 코드에서는 MySQL로 데이터베이스를 변경했기 때문에 매개변수 표시자를 '?'로 써야 한다. 아래와 같이 변경하고 실행하면 오류 없이 잘 동작한다.
1
row := db.QueryRow("SELECT name FROM parent WHERE id = ?", 1)