Golang中如何处理PostgreSQL的多结果集查询
Golang中如何处理PostgreSQL的多结果集查询 大家好,我在Postgres数据库中有一个函数,它返回一组refcursors(4个)。如何在不知道refcursors名称的情况下获取数据?我认为应该有一种通过编程方式获取游标名称的方法,希望这说得通。
import (
"database/sql"
"fmt"
"log"
_ "github.com/lib/pq"
)
const (
host = "ip address goes here"
port = 5432
user = "postgres"
password = "*********"
dbname = "*********"
)
func main() {
psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+
"password=%s dbname=%s sslmode=disable",
host, port, user, password, dbname)
db, err := sql.Open("postgres", psqlInfo)
if err != nil {
log.Fatal(err)
}
defer db.Close()
tx, err := db.Begin()
// 这个函数返回4个游标
row := tx.QueryRow("SELECT public.spgetinvoicedata();")
var CursorName string
// 这里返回第一个游标的名称
err = row.Scan(&CursorName)
rows1, err := tx.Query("FETCH all from " + CursorName + ";" )
// 现在rows1中有数据
// 如何获取其他游标的名称
}
更多关于Golang中如何处理PostgreSQL的多结果集查询的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于Golang中如何处理PostgreSQL的多结果集查询的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在PostgreSQL中,当存储过程返回多个refcursor时,您可以使用pg_cursor系统视图来动态获取所有打开的游标名称。以下是完整的解决方案:
import (
"database/sql"
"fmt"
"log"
_ "github.com/lib/pq"
)
func main() {
psqlInfo := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",
host, port, user, password, dbname)
db, err := sql.Open("postgres", psqlInfo)
if err != nil {
log.Fatal(err)
}
defer db.Close()
tx, err := db.Begin()
if err != nil {
log.Fatal(err)
}
defer tx.Rollback()
// 执行存储过程
_, err = tx.Exec("SELECT public.spgetinvoicedata()")
if err != nil {
log.Fatal(err)
}
// 查询当前事务中打开的游标
cursorRows, err := tx.Query(`
SELECT name FROM pg_cursors
WHERE statement = 'SELECT public.spgetinvoicedata()'
`)
if err != nil {
log.Fatal(err)
}
defer cursorRows.Close()
var cursorNames []string
for cursorRows.Next() {
var cursorName string
if err := cursorRows.Scan(&cursorName); err != nil {
log.Fatal(err)
}
cursorNames = append(cursorNames, cursorName)
}
if err := cursorRows.Err(); err != nil {
log.Fatal(err)
}
// 遍历所有游标获取数据
for i, cursorName := range cursorNames {
fmt.Printf("Processing cursor %d: %s\n", i+1, cursorName)
rows, err := tx.Query("FETCH ALL FROM " + cursorName)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
// 获取列信息
columns, err := rows.Columns()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Columns for cursor %s: %v\n", cursorName, columns)
// 处理数据行
for rows.Next() {
// 根据实际表结构创建相应变量
// 这里使用通用方式处理
values := make([]interface{}, len(columns))
valuePtrs := make([]interface{}, len(columns))
for i := range values {
valuePtrs[i] = &values[i]
}
if err := rows.Scan(valuePtrs...); err != nil {
log.Fatal(err)
}
// 处理每一行数据
fmt.Printf("Row data: %v\n", values)
}
if err := rows.Err(); err != nil {
log.Fatal(err)
}
}
if err := tx.Commit(); err != nil {
log.Fatal(err)
}
}
如果您需要更精确地识别特定存储过程返回的游标,可以使用这个替代方案:
// 替代方案:通过游标创建时间识别
cursorRows, err := tx.Query(`
SELECT name FROM pg_cursors
WHERE substring(statement from 1 for 30) = 'SELECT public.spgetinvoicedata'
ORDER BY creation_time
`)
if err != nil {
log.Fatal(err)
}
defer cursorRows.Close()
如果您知道游标的数量但不知道名称,也可以使用这种方法:
// 如果知道有4个游标
cursorRows, err := tx.Query(`
SELECT name FROM pg_cursors
WHERE statement LIKE 'SELECT public.spgetinvoicedata%'
LIMIT 4
`)
if err != nil {
log.Fatal(err)
}
defer cursorRows.Close()
这种方法通过查询PostgreSQL的系统视图pg_cursors来动态获取当前事务中所有打开的游标名称,然后逐个处理每个游标的数据。

