Skip to content

Instantly share code, notes, and snippets.

@crgimenes
Last active July 12, 2023 09:42
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save crgimenes/dc7723bf1d156fd0a29bce444a665e43 to your computer and use it in GitHub Desktop.
Save crgimenes/dc7723bf1d156fd0a29bce444a665e43 to your computer and use it in GitHub Desktop.
Example of pagination using PostgreSQL, Golang and SQLx

Configure environment variable

export DATABASE_URL=postgres://postgres@localhost/dbname?sslmode=disable 

Run in CLI

go run main.go -page 1
CREATE TABLE clientes
(
id serial NOT NULL,
nome character varying(255) NOT NULL,
PRIMARY KEY (id)
);
INSERT INTO clientes(nome) VALUES ('cliente 1');
INSERT INTO clientes(nome) VALUES ('cliente 2');
INSERT INTO clientes(nome) VALUES ('cliente 3');
INSERT INTO clientes(nome) VALUES ('cliente 4');
INSERT INTO clientes(nome) VALUES ('cliente 5');
INSERT INTO clientes(nome) VALUES ('cliente 6');
INSERT INTO clientes(nome) VALUES ('cliente 7');
INSERT INTO clientes(nome) VALUES ('cliente 8');
INSERT INTO clientes(nome) VALUES ('cliente 9');
INSERT INTO clientes(nome) VALUES ('cliente 10');
INSERT INTO clientes(nome) VALUES ('cliente 11');
INSERT INTO clientes(nome) VALUES ('cliente 12');
INSERT INTO clientes(nome) VALUES ('cliente 13');
INSERT INTO clientes(nome) VALUES ('cliente 14');
INSERT INTO clientes(nome) VALUES ('cliente 15');
INSERT INTO clientes(nome) VALUES ('cliente 16');
INSERT INTO clientes(nome) VALUES ('cliente 17');
INSERT INTO clientes(nome) VALUES ('cliente 18');
INSERT INTO clientes(nome) VALUES ('cliente 19');
INSERT INTO clientes(nome) VALUES ('cliente 20');
INSERT INTO clientes(nome) VALUES ('cliente 21');
INSERT INTO clientes(nome) VALUES ('cliente 22');
INSERT INTO clientes(nome) VALUES ('cliente 23');
INSERT INTO clientes(nome) VALUES ('cliente 24');
package main
import (
"fmt"
"log"
"github.com/gosidekick/goconfig"
"github.com/jmoiron/sqlx"
_ "github.com/lib/pq"
)
type config struct {
DatabaseURL string `cfg:"database_url" cfgRequired:"true"`
Page int `cfg:"page" cfgRequired:"true"`
}
var db *sqlx.DB
func listRecords(page int) {
limit := 10
offset := limit * (page - 1)
SQL := `SELECT "id","nome" FROM "clientes" ORDER BY "id" LIMIT $2 OFFSET $1`
rows, err := db.Queryx(SQL, offset, limit)
if err != nil {
log.Println(err)
return
}
for rows.Next() {
p := struct {
ID int `db:"id"`
Nome string `db:"nome"`
}{}
err = rows.StructScan(&p)
if err != nil {
log.Println(err)
return
}
fmt.Printf("ID: %v\tNome: %v\n", p.ID, p.Nome)
}
}
func main() {
cfg := config{}
err := goconfig.Parse(&cfg)
if err != nil {
fmt.Println(err)
return
}
db, err = sqlx.Connect("postgres", cfg.DatabaseURL)
if err != nil {
fmt.Printf("error open db: %v\n", err)
return
}
listRecords(cfg.Page)
}
@kabaluyot
Copy link

I think the order should be,

`ORDER BY "id" LIMIT $2 OFFSET $1`` instead of writing OFFSET than LIMIT. I encountered a SQL syntax error with that. Please refer here stackoverflow

@crgimenes
Copy link
Author

Hello @kabaluyot,

I will do some tests, I believe that oderm is irrelevant for PostgreSQL.

If it works both ways in PostgreSQL I can update the order without any problems.

@WahidinAji
Copy link

WahidinAji commented Aug 22, 2022

just improve to add total rows in the tables with this query, maybe somebody needed it.

select count(*) over() as total, column1, column2, .. from tables order by id limit $1 offset $2

@dayuoba
Copy link

dayuoba commented Sep 13, 2022

just improve to add total rows in the tables with this query, maybe somebody needed it.

select count(*) over() as total, column1, column2, .. from tables order by id limit $1 offset $2

this doesn't work for mysql

@WahidinAji
Copy link

just improve to add total rows in the tables with this query, maybe somebody needed it.

select count(*) over() as total, column1, column2, .. from tables order by id limit $1 offset $2

this doesn't work for MySQL

absolutely, 'cuz this one is for PGSQL. in MySQL you need no over() just count and combine with limit offset. for example, you can read this official documentation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment