在Go语言里使用lib/pq驱动操作PostgreSQL数据库时,SQL占位符的写法和MySQL驱动并不一样。lib/pq采用的是PostgreSQL原生的占位符形式,也就是用美元符号加数字来表示参数位置。如果沿用问号占位符,运行时会直接报错。理解并正确使用这些占位符,是写出稳定数据库程序的基础。

lib/pq的占位符基本规则
lib/pq使用的占位符格式为 $1、$2、$3 这样依次递增的数字标记。第一个参数对应 $1,第二个对应 $2,在调用 Query 或 Exec 方法时按顺序传入即可。
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/lib/pq"
)
func main() {
connStr := "user=postgres password=123456 dbname=test sslmode=disable"
db, err := sql.Open("postgres", connStr)
if err != nil {
log.Fatal(err)
}
defer db.Close()
// 使用 $1 $2 作为占位符
var name string
err = db.QueryRow("SELECT username FROM users WHERE id = $1 AND status = $2", 10, 1).Scan(&name)
if err != nil {
log.Fatal(err)
}
fmt.Println(name)
}
批量插入时的占位符写法
当需要一次插入多行数据时,可以手动拼接占位符,也可以使用循环生成。下面示例展示一次插入三条记录的写法。
package main
import (
"database/sql"
"log"
_ "github.com/lib/pq"
)
func main() {
connStr := "user=postgres password=123456 dbname=test sslmode=disable"
db, err := sql.Open("postgres", connStr)
if err != nil {
log.Fatal(err)
}
defer db.Close()
// 批量插入使用 $1 $2 $3 $4 $5 $6
sqlStr := "INSERT INTO users (username, age) VALUES ($1, $2), ($3, $4), ($5, $6)"
_, err = db.Exec(sqlStr, "alice", 20, "bob", 25, "carol", 30)
if err != nil {
log.Fatal(err)
}
}
关于命名参数
lib/pq本身不支持像 :name 这样的命名占位符。如果业务里希望使用命名参数,可以借助第三方库,或者自己在代码里把命名参数替换为 $1 这样的数字占位符再执行。
简单的替换示例
package main
import (
"database/sql"
"log"
"strings"
_ "github.com/lib/pq"
)
func main() {
connStr := "user=postgres password=123456 dbname=test sslmode=disable"
db, err := sql.Open("postgres", connStr)
if err != nil {
log.Fatal(err)
}
defer db.Close()
// 原始SQL使用命名风格
rawSQL := "SELECT * FROM users WHERE username = :name AND age = :age"
// 简单替换为 lib/pq 风格
replaced := strings.Replace(rawSQL, ":name", "$1", 1)
replaced = strings.Replace(replaced, ":age", "$2", 1)
_, err = db.Query(replaced, "alice", 20)
if err != nil {
log.Fatal(err)
}
}
常见错误与注意点
- 使用问号占位符,例如
?,在lib/pq中会报语法错误。 - 占位符序号必须从1开始且连续,不能跳号。
- 同一SQL里重复引用同一参数时,也要写不同的序号并重复传值,或者使用支持的扩展库。
正确写法:SELECT * FROM t WHERE a = $1 AND b = $2;错误写法:SELECT * FROM t WHERE a = ? AND b = ?
只要记住lib/pq遵循PostgreSQL的 $n 占位符规则,并在代码里按顺序传参,就能避免绝大多数SQL占位符相关的问题。
Golib/pqPostgreSQL修改时间:2026-07-27 06:21:10