MySQL
LIMIT clause
SQL variables
database optimization
SQL tutorial

Using variable in a LIMIT clause in MySQL

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Using variables with LIMIT is a common need for pagination, batch jobs, and configurable query windows. In MySQL, the safest and most portable approach is to pass limit values through prepared statement parameters. Relying on ad hoc string concatenation is error-prone and increases SQL injection risk.

Basic LIMIT Patterns

MySQL supports two common forms:

sql
SELECT id, name
FROM users
LIMIT 10;
sql
SELECT id, name
FROM users
LIMIT 20 OFFSET 40;

The first returns a fixed row count. The second supports pagination by offset and page size.

Using Variables with Prepared Statements

When the row count is dynamic, use parameter markers.

sql
1SET @row_count = 25;
2SET @offset = 50;
3
4PREPARE stmt FROM '
5  SELECT id, name
6  FROM users
7  ORDER BY id
8  LIMIT ? OFFSET ?
9';
10
11EXECUTE stmt USING @row_count, @offset;
12DEALLOCATE PREPARE stmt;

This is the most reliable method for runtime-provided values because SQL parsing remains stable and values are bound safely.

Stored Procedure Example

Inside procedures, you often receive page inputs and convert them to LIMIT arguments.

sql
1DELIMITER $$
2
3CREATE PROCEDURE GetUsersPage(IN p_page INT, IN p_size INT)
4BEGIN
5  DECLARE v_offset INT;
6
7  SET v_offset = (p_page - 1) * p_size;
8
9  SET @sql = '
10    SELECT id, name, email
11    FROM users
12    ORDER BY id
13    LIMIT ? OFFSET ?
14  ';
15
16  PREPARE stmt FROM @sql;
17  SET @size = p_size;
18  SET @off = v_offset;
19  EXECUTE stmt USING @size, @off;
20  DEALLOCATE PREPARE stmt;
21END$$
22
23DELIMITER ;

Calling it:

sql
CALL GetUsersPage(3, 20);

This returns rows 41 through 60 in id order.

Application-Side Parameter Binding

In app code, keep LIMIT values as parameters instead of string interpolation.

Python example with MySQL connector:

python
1import mysql.connector
2
3conn = mysql.connector.connect(
4    host="localhost",
5    user="app",
6    password="secret",
7    database="demo"
8)
9
10page_size = 20
11page = 2
12offset = (page - 1) * page_size
13
14query = """
15SELECT id, name
16FROM users
17ORDER BY id
18LIMIT %s OFFSET %s
19"""
20
21with conn.cursor() as cur:
22    cur.execute(query, (page_size, offset))
23    rows = cur.fetchall()
24    for row in rows:
25        print(row)
26
27conn.close()

Client libraries usually map these values safely to prepared execution under the hood.

Input Validation Rules

Always validate runtime values before execution:

  • page_size must be positive.
  • offset must be zero or positive.
  • Enforce maximum page size to avoid huge scans.

Example guard in SQL procedure:

sql
1IF p_size < 1 OR p_size > 1000 THEN
2  SIGNAL SQLSTATE '45000'
3    SET MESSAGE_TEXT = 'Invalid page size';
4END IF;

Validation protects database resources and avoids accidental full-table retrieval.

Performance Considerations

Large offsets can become expensive because MySQL still scans and skips rows. For deep pagination, keyset pagination is usually faster.

Keyset pattern:

sql
1SELECT id, name
2FROM users
3WHERE id > 50000
4ORDER BY id
5LIMIT 20;

This avoids scanning all prior rows and scales better for large tables.

If offset pagination is required, index the sort column and keep page sizes controlled.

Combining Total Count and Paged Rows

Many APIs need both current page rows and a total count. Keep these as two explicit queries so each concern is clear and optimizer behavior is predictable.

sql
1SELECT COUNT(*) AS total_rows
2FROM users
3WHERE status = 'active';
4
5SELECT id, name
6FROM users
7WHERE status = 'active'
8ORDER BY id
9LIMIT 20 OFFSET 40;

Return both values in one API payload. This keeps client pagination controls accurate while avoiding hidden query side effects.

Security Notes

Do not concatenate untrusted input directly into SQL strings for LIMIT.

Bad pattern:

sql
SET @sql = CONCAT('SELECT * FROM users LIMIT ', @unsafe_input);

Even if input looks numeric, weak validation can still introduce risk in dynamic SQL scenarios. Parameter binding plus strict numeric validation is safer.

Common Pitfalls

  • Concatenating LIMIT values into SQL text. Fix by using prepared statement parameters.
  • Allowing negative or huge limits from user input. Fix by applying strict bounds checks.
  • Using high offsets on very large tables. Fix by switching to keyset pagination where possible.
  • Forgetting deterministic ordering with LIMIT. Fix by always specifying ORDER BY.
  • Keeping prepared statements open unnecessarily. Fix by deallocating after execution.

Summary

  • Dynamic LIMIT values are best handled with prepared statements.
  • Validate all pagination inputs before query execution.
  • Always pair LIMIT with explicit ordering for stable results.
  • Large offsets can hurt performance; keyset pagination can scale better.
  • Avoid SQL string concatenation for safety and maintainability.

Course illustration
Course illustration

All Rights Reserved.