package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"log"
"os"
)
func main() {
//db, err := sql.Open("mysql", "계정명:계정패스워드@tcp(DB주소:DB포트)/데이터베이스명")
db, err := sql.Open("mysql", "test:test01@tcp(localhost:3306)/test01")
if err != nil {
log.Println(err)
os.Exit(1)
}
defer db.Close()
var name string = "rose"
var email string = "rose@test.net"
result, err := db.Exec("INSERT INTO tb_users (name, email) VALUES (?,?)",&name,&email)
if err != nil {
log.Fatal(err)
os.Exit(1)
}
// sql.Result.RowsAffected() 체크
n, err := result.RowsAffected()
if n == 1 {
fmt.Println("1 row inserted.")
}
}
- Prepared Statement는 데이타베이스 서버에 Placeholder를 가진 SQL문을 미리 준비시키는 것으로, 차후 해당 Statement를 호출할 때 준비된 SQL문을 빠르게 실행하도록 하는 기법이다. Go에서 Prepared Statement를 사용하기 위해서는 sql.DB의 Prepare() 메서드를 써서 Placeholder를 가진 SQL문을 미리 준비시키고, sql.Stmt 객체를 리턴받는다. 차후 이 sql.Stmt 객체의 Exec (혹은 Query/QueryRow) 메서드를 사용하여 준비된 SQL문을 실행한다.
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"log"
"os"
)
func main() {
//db, err := sql.Open("mysql", "계정명:계정패스워드@tcp(DB주소:DB포트)/데이터베이스명")
db, err := sql.Open("mysql", "test:test01@tcp(localhost:3306)/test01")
if err != nil {
log.Println(err)
os.Exit(1)
}
defer db.Close()
// Prepared Statement 생성
stmt, err := db.Prepare("UPDATE tb_users SET name=? WHERE uid=?")
checkError(err)
defer stmt.Close()
// Prepared Statement 실행
_, err = stmt.Exec("Tom", 1) //Placeholder 파라미터 순서대로 전달
checkError(err)
fmt.Println("1 row updated.")
_, err = stmt.Exec("Jack", 2)
checkError(err)
fmt.Println("1 row updated.")
_, err = stmt.Exec("Shawn", 3)
checkError(err)
fmt.Println("1 row updated.")
}
func checkError(err error) {
if err != nil {
panic(err)
}
}
- 복수 개의 SQL 문을 하나의 트랜잭션으로 묶기 위하여 sql.DB의 Begin() 메서드를 사용한다. 트랜잭션은 복수 개의 SQL 문을 실행하다 중간에 어떤 한 SQL문에서라도 에러가 발생하면 전체 SQL문을 취소하게 되고 (이를 롤백이라 한다), 모두 성공적으로 실행되어야 전체를 커밋하게 된다.
Begin() 메서드는 sql.Tx 객체를 리턴하는데, 이 Tx 객체로부터 Tx.Exec() 등을 실행하여 트랜잭션을 수행한 후, 마지막에 최종 Commit을 위해 Tx.Commit() 메서드를 호출한다. 트랜잭션을 취소하는 롤백을 위해서는 Tx.Rollback() 메서드를 호출하는데, 통상 Tx 객체를 얻은 직후 defer tx.Rollback() 을 호출하여 이후 문장들에서 에러가 발생하면 롤백하도록 defer로 지정해 준다.
func main() {
//db, err := sql.Open("mysql", "계정명:계정패스워드@tcp(DB주소:DB포트)/데이터베이스명")
db, err := sql.Open("mysql", "test:test01@tcp(localhost:3306)/test01")
if err != nil {
log.Println(err)
os.Exit(1)
}
defer db.Close()
// 트랜잭션 시작
tx, err := db.Begin()
if err != nil {
log.Panic(err)
}
defer tx.Rollback() //중간에 에러시 롤백하도록 defer 한다
// INSERT 문 실행
_, err = tx.Exec("INSERT INTO test1 VALUES (?, ?)", 15, "Jack")
if err != nil {
//에러메시지를 출력하고 panic() 호출.
//panic()은 defer를 실행한다.
log.Panic(err)
}
_, err = tx.Exec("INSERT INTO test2 VALUES (?, ?)", 15, "Data")
if err != nil {
log.Panic(err)
}
// 트랜잭션 커밋
err = tx.Commit()
if err != nil {
log.Panic(err)
}
}