问题
I have the following code so far it dows 2 queries both based on the $_GET term passed to the page.
Query 1) retrieves the column names based on the table name passed from $_GET -> Works.
Query 2) Retrieves data from that table -> Doesn't work.
The 2nd query is this:
$table_data = db_adminQuery('SELECT * FROM :tbl_name', array(':tbl_name' => $p ));
When I change the query to:
$table_data = db_adminQuery('SELECT * FROM events', array());
it works but I can't understand why it doesn't on the first place. If I missed something or there is some silly error please let me know because I don't know what's wrong with this.
Here is the complete source:
if(isset($_GET['page']))
{
$pages = array('events','news','ads','slider');
$page = trim($_GET['page']);
if(in_array($page, $pages))
{
include 'db.php';
administer($page);
}
}
function administer($p)
{
/*
*
* TABLE COLUMN NAMES & TYPES
*
*/
$columns_tmp = db_adminQuery('SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = \'evented\' AND TABLE_Name = :table_name', array(':table_name' => $p));
if(!empty($columns_tmp))
{
$columns = array();
foreach ($columns_tmp as $key => $value)
{
array_push($columns, array('name' => $value['COLUMN_NAME'], 'type' => $value['DATA_TYPE']));
}
}
/*
*
* TABLE DATA
*
*/
$table_data = db_adminQuery('SELECT * FROM :tbl_name', array(':tbl_name' => $p ));
print_r($table_data);
$table = '<table cellpadding="0" cellspacing ="0">'.PHP_EOL;
$table .= '<tr>'.PHP_EOL;
foreach ($columns as $key => $value)
{
$table .= '<th style="padding:5px;">'.$value['name'].'</th>';
}
$table .= '</tr>'.PHP_EOL;
foreach ($table_data as $data_key => $data_value)
{
$table .= '<tr>'.PHP_EOL;
//$table .= '<td>'.$data_value.'</td>';
$table .= '</tr>'.PHP_EOL;
}
$table .= '</table>';
echo $table;
}
function db_adminQuery($query, $params = array(), $return = true)
{
global $db;
if($stmt = $db->prepare($query))
{
// PARAMETERS
if(!empty($params))
{
foreach($params as $key => $value)
{
$stmt->bindParam($key, $value);
echo $key.' - '.$value.'<br>';
}
}
$stmt->execute();
if($return == true)
{
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $result;
}
}
return false;
}
回答1:
In SQL, all table names and all column names and other SQL syntax need to be fixed before you prepare() the query. Otherwise the parsing can't validate that the table you name actually exists, and you have enough privileges to act on it, etc. Also the query optimizer may make decisions about which indexes it uses at that time (although I believe in MySQL's case, the optimizer doesn't do that until execute() time).
So you can't parameterize table names, column names, expressions, SQL keywords, etc.
Use query parameters only in place where you would normally use a constant value, like a quoted string literal, quoted date literal, or a numeric constant.
To interpolate table names safely into an SQL string, make sure you whitelist the value before you interpolate it. That is, match the table-name input against a list of known tables that you have in your code. Either hard-code it, or put it in a config file, or query the database instance to discover what tables exist.
If the user inputs a string that doesn't match something known to exist, they must have made a mistake, or else they are trying to perpetrate SQL injection. Either way, don't use their input. Either use some default table name, or else give them an error and let them try again.
来源:https://stackoverflow.com/questions/15282028/php-mysql-pdo-bindparam-working-occasionally