Recent chats
ASKGEEZ Q&A GUIDETechnology & devices

Why can’t a bound SQLite parameter stand in for a table name?

Quick answer

A bound parameter supplies a value to a prepared SQL statement; it does not rewrite the statement’s SQL syntax. SQLite’s C interface allows parameters where literal values are permitted, not where a table or column name must be written. [S1] If an application needs to choose a table, select the identifier from a controlled set of valid choices, then bind ordinary data values separately. Check your language wrapper’s documentation for its API-specific behavior. [S2]

LET’S WORK THROUGH IT

The question, the details, the next step.

Question

I’m building a query where the table changes depending on a selection. Why doesn’t SELECT * FROM ? work if I bind the table name?

Geez

A parameter is a slot for a value, not a blank space where SQLite inserts SQL words. The statement’s structure is prepared first; binding supplies values for its placeholders afterward. In SQLite’s C interface, parameters can occupy places where literal values are allowed, but not positions for table or column names. [S1]

So in SELECT * FROM ?, SQLite does not treat the bound text as a table identifier. The statement needs its table name in the SQL structure before values are bound. Think of parameters as filling in answers on a form, not changing its labels.

Follow-up question

What should I do if the application has a few legitimate tables to choose from?

Geez

Keep the permitted choices under application control. Map each supported choice to a known SQL statement or identifier, and bind user-supplied values—such as a row ID—as parameters. SQLite’s C interface guidance recommends choosing from controlled valid statement or identifier options for a variable table choice, while binding ordinary data values separately. [S1]

For example, suppose an application offers reports for orders and returns. It could map each report choice to one of two statements written in the application, with a WHERE placeholder for a value such as a record ID. The chosen statement contains its table name; the data value is bound afterward. This is an illustrative pattern, not a guarantee about every programming-language wrapper.

Follow-up question

Could I put the selected name into the SQL string? Does quoting it solve the problem?

Geez

If a table choice must be assembled into SQL text, first resolve it to an exact identifier from a fixed, approved mapping—not directly from arbitrary input. Keep that identifier separate from values that can be bound. Quoting an identifier and binding a value are different operations. The cited material establishes that a bound parameter cannot serve as a table or column name, but does not specify quoting rules or a universal quoting method for every wrapper. [S1][S2]

A reviewable pattern is report choice → fixed statement; if the choice is not in the mapping, do not construct a statement from it. For language-specific quoting, placeholder syntax, or binding calls, consult that wrapper’s documentation. The cited binding page describes the C API and notes that other bindings may have API-specific details. [S2]

Follow-up question

What should I check in a code review to confirm table selection and data values are handled separately?

Geez

Trace both inputs from where they enter the application to where the SQL is prepared. Confirm that the table choice resolves only to an approved statement or identifier, while ordinary values use the binding API. In SQLite’s C interface, host parameters are placeholders in SQL text whose values are supplied through sqlite3_bind_*() routines; documented forms include ?, ?NNN, :VVV, @VVV, and $VVV. [S2]

Check the documentation and tests for the application’s language wrapper too. A useful test plan covers each approved table choice, an unsupported choice, and representative bound values. The cited guidance does not establish how every wrapper behaves or provide a universal identifier-quoting rule, so verify those details in the relevant API documentation.

A practical checklist

  • Identify table or column choices assembled dynamically.

  • Confirm each dynamic identifier resolves only to an explicit, controlled set of valid choices.

  • Bind ordinary data values separately from SQL identifiers.

  • Reject or handle choices that do not match the approved mapping.

  • Check placeholder and binding behavior in the documentation for your SQLite language wrapper.

  • Review tests for approved choices, unsupported choices, and representative bound values.

A few more useful answers

Can a parameter represent a column name instead of a table name?

No, not in SQLite’s C prepared-statement interface: parameters stand for literal values, not table or column identifiers. [S1] Use a controlled identifier choice and verify your wrapper’s details.

What are SQLite placeholders for?

They mark positions for values supplied when binding to a prepared statement. The C API documents forms including ?, ?NNN, :VVV, @VVV, and $VVV. [S2]

Does this guidance cover every SQLite programming language?

No. The cited material describes SQLite’s C interface, and the binding documentation notes that other language bindings can have API-specific details. Check the documentation for the wrapper you use. [S1][S2]

Sources

References used for this guide.

  1. [S1] An Introduction to the SQLite C/C++ Interface
    sqlite.org · Checked
  2. [S2] SQLite C Interface: Binding Values to Prepared Statements
    sqlite.org · Checked

YOUR QUESTION. YOUR DETAILS.

Let’s work through your situation.

Get a tailored answer or help with your next task. Starts at $1, with a quote before you pay.

Ask your own question
← Back to Geez at Work