MySQL
SQL queries
dynamic table selection
variable table name
database management

How to select from MySQL where Table name is Variable

Master System Design with Codemia

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

Introduction

In MySQL, you cannot parameterize a table name in a normal prepared statement placeholder the way you parameterize a value. If the table name must vary, the usual solution is dynamic SQL: build the statement as a string, validate the table name carefully, then prepare and execute it.

Core Sections

Why placeholders do not work for table names

This does not work:

sql
SELECT * FROM ? WHERE id = ?;

The reason is that ? placeholders are for values, not SQL identifiers such as table names, column names, or database names. MySQL parses the structure of the SQL statement before binding values, so the table must already be part of the statement text.

Build the SQL dynamically

The standard MySQL pattern is:

  1. put the table name into a string
  2. concatenate the SQL text
  3. PREPARE the statement
  4. EXECUTE it
sql
1SET @table_name = 'orders';
2SET @sql = CONCAT('SELECT * FROM ', @table_name, ' WHERE id = ?');
3PREPARE stmt FROM @sql;
4SET @id = 10;
5EXECUTE stmt USING @id;
6DEALLOCATE PREPARE stmt;

The table name is injected into the SQL text itself, while the id value remains a normal bound parameter.

Validate the table name before executing

This is the critical safety rule. If the table name comes from user input, do not concatenate it blindly. Since identifiers cannot use placeholders, you must whitelist acceptable names yourself.

For example, in application code:

python
1allowed_tables = {"orders", "customers", "invoices"}
2user_table = "orders"
3
4if user_table not in allowed_tables:
5    raise ValueError("invalid table name")

Then build the SQL only after the identifier has passed validation. Dynamic SQL with unvalidated identifiers is an SQL injection risk.

Stored procedure example

If the logic lives inside MySQL, a stored procedure can wrap the dynamic query:

sql
1DELIMITER //
2
3CREATE PROCEDURE get_row_from_table(IN p_table VARCHAR(64), IN p_id INT)
4BEGIN
5    SET @sql = CONCAT('SELECT * FROM ', p_table, ' WHERE id = ?');
6    PREPARE stmt FROM @sql;
7    SET @v_id = p_id;
8    EXECUTE stmt USING @v_id;
9    DEALLOCATE PREPARE stmt;
10END //
11
12DELIMITER ;

Even here, the procedure should still enforce a whitelist if p_table can vary freely.

Often the design should be reconsidered

A variable table name is sometimes a sign that the schema design is fighting the query. If several tables have the same structure and differ only by a category, a single table with a type column is often easier to query, index, and maintain.

Dynamic table selection is still valid in some cases, such as partitioned historical tables or admin tooling, but it should be a deliberate design choice rather than the default answer.

Common Pitfalls

  • Trying to use ? placeholders for table names even though placeholders only work for values.
  • Concatenating untrusted user input directly into SQL identifiers.
  • Forgetting to DEALLOCATE PREPARE after executing dynamic SQL repeatedly.
  • Using dynamic table names where a cleaner schema could avoid the problem entirely.
  • Treating identifier validation as optional just because the query is built on the server side.

Summary

  • MySQL does not let you bind a table name through a normal placeholder.
  • Use dynamic SQL with CONCAT, PREPARE, and EXECUTE when the table name must vary.
  • Keep values parameterized even when the identifier itself is dynamic.
  • Always validate dynamic table names against a trusted whitelist.
  • If variable table names appear everywhere, revisit the schema before doubling down on dynamic SQL.

Course illustration
Course illustration

All Rights Reserved.