diff --git a/rows.go b/rows.go
index 23f33efc..409885e0 100644
--- a/rows.go
+++ b/rows.go
@@ -546,16 +546,19 @@ func (rs *positionalStructRowScanner) appendScanTargets(dstElemValue reflect.Val
 	return scanTargets
 }
 
-// RowToStructByName returns a T scanned from row. T must be a struct. T must have the same number a named public fields as row
-// has fields. The row and T fields will by matched by name.
+// RowToStructByName returns a T scanned from row. T must be a struct. T must have the same number of named public
+// fields as row has fields. The row and T fields will by matched by name. The match is case-insensitive. The database
+// column name can be overridden with a "db" struct tag. If the "db" struct tag is "-" then the field will be ignored.
 func RowToStructByName[T any](row CollectableRow) (T, error) {
 	var value T
 	err := row.Scan(&namedStructRowScanner{ptrToStruct: &value})
 	return value, err
 }
 
-// RowToAddrOfStructByPos returns the address of a T scanned from row. T must be a struct. T must have the same number a
-// named public fields as row has fields. The row and T fields will by matched by name.
+// RowToAddrOfStructByPos returns the address of a T scanned from row. T must be a struct. T must have the same number
+// of named public fields as row has fields. The row and T fields will by matched by name. The match is
+// case-insensitive. The database column name can be overridden with a "db" struct tag. If the "db" struct tag is "-"
+// then the field will be ignored.
 func RowToAddrOfStructByName[T any](row CollectableRow) (*T, error) {
 	var value T
 	err := row.Scan(&namedStructRowScanner{ptrToStruct: &value})
diff --git a/rows_test.go b/rows_test.go
index aacd3def..ca9c3010 100644
--- a/rows_test.go
+++ b/rows_test.go
@@ -509,6 +509,37 @@ func TestRowToAddrOfStructPos(t *testing.T) {
 	})
 }
 
+func TestRowToStructByName(t *testing.T) {
+	type person struct {
+		Last  string
+		First string
+		Age   int32
+	}
+
+	defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
+		rows, _ := conn.Query(ctx, `select 'John' as first, 'Smith' as last, n as age from generate_series(0, 9) n`)
+		slice, err := pgx.CollectRows(rows, pgx.RowToStructByName[person])
+		assert.NoError(t, err)
+
+		assert.Len(t, slice, 10)
+		for i := range slice {
+			assert.Equal(t, "Smith", slice[i].Last)
+			assert.Equal(t, "John", slice[i].First)
+			assert.EqualValues(t, i, slice[i].Age)
+		}
+
+		// check missing fields in a returned row
+		rows, _ = conn.Query(ctx, `select 'Smith' as last, n as age from generate_series(0, 9) n`)
+		_, err = pgx.CollectRows(rows, pgx.RowToStructByName[person])
+		assert.ErrorContains(t, err, "cannot find field First in returned row")
+
+		// check missing field in a destination struct
+		rows, _ = conn.Query(ctx, `select 'John' as first, 'Smith' as last, n as age, null as ignore from generate_series(0, 9) n`)
+		_, err = pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[person])
+		assert.ErrorContains(t, err, "struct doesn't have corresponding row field ignore")
+	})
+}
+
 func TestRowToStructByNameEmbeddedStruct(t *testing.T) {
 	type Name struct {
 		Last  string `db:"last_name"`
@@ -544,3 +575,63 @@ func TestRowToStructByNameEmbeddedStruct(t *testing.T) {
 		assert.ErrorContains(t, err, "struct doesn't have corresponding row field ignore")
 	})
 }
+
+func ExampleRowToStructByName() {
+	ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
+	defer cancel()
+
+	conn, err := pgx.Connect(ctx, os.Getenv("PGX_TEST_DATABASE"))
+	if err != nil {
+		fmt.Printf("Unable to establish connection: %v", err)
+		return
+	}
+
+	if conn.PgConn().ParameterStatus("crdb_version") != "" {
+		// Skip test / example when running on CockroachDB. Since an example can't be skipped fake success instead.
+		fmt.Println(`Cheeseburger: $10
+Fries: $5
+Soft Drink: $3`)
+		return
+	}
+
+	// Setup example schema and data.
+	_, err = conn.Exec(ctx, `
+create temporary table products (
+	id int primary key generated by default as identity,
+	name varchar(100) not null,
+	price int not null
+);
+
+insert into products (name, price) values
+	('Cheeseburger', 10),
+	('Double Cheeseburger', 14),
+	('Fries', 5),
+	('Soft Drink', 3);
+`)
+	if err != nil {
+		fmt.Printf("Unable to setup example schema and data: %v", err)
+		return
+	}
+
+	type product struct {
+		ID    int32
+		Name  string
+		Price int32
+	}
+
+	rows, _ := conn.Query(ctx, "select * from products where price < $1 order by price desc", 12)
+	products, err := pgx.CollectRows(rows, pgx.RowToStructByName[product])
+	if err != nil {
+		fmt.Printf("CollectRows error: %v", err)
+		return
+	}
+
+	for _, p := range products {
+		fmt.Printf("%s: $%d\n", p.Name, p.Price)
+	}
+
+	// Output:
+	// Cheeseburger: $10
+	// Fries: $5
+	// Soft Drink: $3
+}