Reputation: 2274
I have the need to make the table names dynamic in my queries. I've read that you can't bind them like you would with parameters, so I figured I'd do something like this:
$table_unsafe = $_GET['table'];
$table_safe = get_safe_table($mysqli, $table_unsafe);
$query = "SELECT * FROM " . $table_safe . " WHERE user=?";
$stmt = $mysqli->prepare($query);
$stmt->bind_param('i', $user_id);
function get_safe_table($mysqli, $table)
{
$query = "SELECT table_name FROM tables WHERE table_name=?";
$stmt = $mysqli->prepare($query);
$stmt->bind_param('s', $table);
$stmt->execute();
$result = $stmt->get_result();
$result = $result->fetch_row();
if ($result) {
return $result[0];
} else {
exit;
}
}
The table tables
is just a table that holds all the available table names:
+-----+------------------+
| id | table_name |
+-----+------------------+
| 1 | user_statistics |
| 2 | user_information |
| ... | ... |
+-----+------------------+
Is this practice safe? If not, what can I do to make it more safe? The reason why I put the available tables in a table, is because of the amount of tables I have (+300). Each time a new table gets created, I simply add a row to tables
instead of having to update my code all the time. There is no public code that can insert to or update tables
.
Upvotes: 0
Views: 562
Reputation: 158005
Yes, it is possible but you don't have to create a table to hold the table names and maintain it manually - of course mysql already has such a table. So it could be just
$sql = "SELECT 1 FROM information_schema.TABLES
WHERE TABLE_NAME = ? AND TABLE_SCHEMA IN (SELECT DATABASE())";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param("s", $table);
$stmt->execute();
return (bool)$stmt->get_result()->fetch_row();
However, the usage should be a bit different. It makes no sense to run a query like SELECT * FROM WHERE
with just empty table name. You should only verify the function's result and throw an error in case it is empty.
Upvotes: 2