When using the GORM ORM library in Go to interact with a PostgreSQL database and you want to process data in batches via a cursor, the standard practice is to manage cursor operations through native SQL statements, as GORM does not natively support setting the cursor batch size.
-
Establish Database Connection: First, we need to establish a connection to the PostgreSQL database using GORM.
gopackage main import ( "gorm.io/driver/postgres" "gorm.io/gorm" ) func setupDB() *gorm.DB { dsn := "host=localhost user=gorm password=gorm dbname=gorm port=9920 sslmode=disable TimeZone=Asia/Shanghai" db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{}) if err != nil { panic("failed to connect database") } return db } -
Using Native SQL and Cursors: In this step, we declare a cursor using native SQL and process data in batches with the specified batch size.
gofunc processWithCursor(db *gorm.DB, batchSize int) { // Start a transaction tx := db.Begin() defer tx.Commit() // Declare the cursor tx.Exec("DECLARE my_cursor CURSOR FOR SELECT * FROM my_table") // Process data in batches using the cursor for { rows, err := tx.Raw("FETCH " + strconv.Itoa(batchSize) + " FROM my_cursor").Rows() if err != nil { panic(err) } defer rows.Close() for rows.Next() { // Process each row var column1, column2 string // Assuming these fields exist in the table err = rows.Scan(&column1, &column2) if err != nil { panic(err) } // Process column1 and column2 fmt.Println(column1, column2) } // Check if more data exists moreData := rows.NextResultSet() if !moreData { break } } // Close the cursor tx.Exec("CLOSE my_cursor") } -
Calling the Processing Function: Finally, in the main function, we call the previously defined
processWithCursorfunction and pass the batch size.gofunc main() { db := setupDB() batchSize := 100 // Set batch size to 100 processWithCursor(db, batchSize) }
In this example, by directly using the native SQL FETCH statement from PostgreSQL to specify how many rows to retrieve at a time from the cursor, we achieve batch processing. Although this approach does not directly set the cursor batch size through GORM, it effectively combines GORM's transaction management with the flexibility of native SQL.