I am to php and I am trying to make a page where you can see the public uploads that are stored in a mysql server.
Out of not where the code I have been using starts giving me an error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'public' in 'where clause'
I am trying to see how many rows in my db have 'public'
// Find out how many items are in the table
$p = 'public';
$total = $db->query("SELECT COUNT(*) FROM uploads WHERE world_access = $p")->fetchColumn();
I don't know if it is the php or the sql.
// Prepare the paged query
$stmt = $db->prepare('SELECT * FROM uploads WHERE world_access = :y ORDER BY upload_time DESC LIMIT :limit OFFSET :offset');
// Bind the query params
$stmt->bindParam(':y', $p, PDO::PARAM_INT);
$stmt->bindParam(':limit', $limit, PDO::PARAM_INT);
$stmt->bindParam(':offset', $offset, PDO::PARAM_INT);
$stmt->execute();
pagination by Simple PHP Pagination script
Enclose $p with quotes
$total = $db->query("SELECT COUNT(*) FROM uploads WHERE world_access = '$p'")->fetchColumn();
Also in your PDO, :y is string right? then use PDO::PARAM_STR
Related
I have a PHP search that is giving me issues:
$filter = "123-N";
$qry = $pdo->prepare("SELECT * FROM MyTable WHERE MyField = :MyField LIMIT 1 ");
$qry->bindParam(':MyField', $filter);
$qry->execute();
$result = $qry->fetch();
It is giving me this error:
Failed: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'N' in
'where clause'
The same search in MySQL workbench works fine:
SELECT * FROM MyTable WHERE MyField = "123-N" LIMIT 1 ;
I have tried to encapsulate it, or write it in its own query and not bind it, but nothing seems to help. Any ideas please?
use
$filter = "'123-N'";
OR
$filter = "123-N";
...
$qry = $pdo->prepare("SELECT * FROM MyTable WHERE MyField = QUOTE(:MyField) LIMIT 1 ");
Both get you the same result and mysql recognizes a string
The basic problem is that MySQL tries to interpret the value and needs a hint
I'm working with a MySQL server Server version: 5.6.42-cll-lve - MySQL Community Server (GPL) and I'm having some major issues with CONCAT()
public function get_urls() {
// Create query
$query = "SELECT a.Name, a.PrimaryVersion, e1.URL
FROM " . $this->table . " a
INNER JOIN
FunnelsFlows b ON a.Funnel_ID = b.Funnel_ID
INNER JOIN
BackendFlows c ON b.BackendFlow_ID = c.BackendFlow_ID
INNER JOIN
BackendLevels d ON CONCAT(c.Level, :lv) = d.BackendLevel_ID
LEFT JOIN
BackendPages e1 ON d.Upsell = e1.BackendPage_ID
LEFT JOIN
BackendPages e2 ON d.Downsell1 = e2.BackendPage_ID
LEFT JOIN
BackendPages e3 ON d.Downsell2 = e3.BackendPage_ID
WHERE
a.Funnel_ID = :fid
LIMIT 0,1";
// Prepare statement
$stmt = $this->conn->prepare($query);
// Bind ID
$stmt->bindParam(':fid', $this->fid, PDO::PARAM_INT);
$stmt->bindValue(':lv', $this->lv, PDO::PARAM_STR);
// Execute query
$stmt->execute();
Running this code throws the following error: PHP Fatal error: Uncaught PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'c.Level' in 'on clause' in ...
The entire database structure you can view here:
https://app.sqldbm.com/MySQL/Share/wBAF2JMRFFSoPPjIPdYZc0GFrngIE8md_DYjF4jNYw0
Delete the quotes (both for column name and for the value):
CONCAT(a.Level, :level)
Also, you use a wrong parameter name:
$stmt->bindParam(':level', $this->lv, PDO::PARAM_INT);
// ^^^^^
Your query cannot work like that. You are trying to concat a field content CONCAT(c.Level, :lv) with a parameter :lv. This results in a string if there were a column Level. However, you rather want to build a dynamic column name like Level1 / Level2 aso.
Unfortunately this cannot be done by parameters. This is owing to the fact, that query plans are prepared. Changing column names at execution time would alter the query plan.
You either need to build dynamic SQL in such a case or write a complex ON clause.
The ON clause:
ON
(
(:lv = 1 AND c.Level1 = d.BackendLevel_ID)
OR
(:lv = 2 AND c.Level2 = d.BackendLevel_ID)
-- and so on
)
Dynamic SQL:
$sql = 'ON (c.Level' . inval($this->lv) . ' = d.BackendLevel_ID)'
Since PHP's intval function is considered to be safe, I would prefer the latter example in order to improve SQL performance.
What about this?
$query = "SELECT a.Name, b.URL
FROM " . $this->table . " a
INNER JOIN
FunnelsFlows b ON CONCAT(a.Level, ':lv') = b.Level_ID
WHERE
a.Funnel_ID = :fid
LIMIT 0,1";
// Prepare statement
$stmt = $this->conn->prepare($query);
// Bind ID
$stmt->bindParam(':fid', $this->fid, PDO::PARAM_INT);
$stmt->bindParam(':lv', $this->lv, PDO::PARAM_INT);
// Execute query
$stmt->execute();
That was a quick response, so I'll explain now.
What I'm seeing it that you want to concatenate a table column with a string, right?
First you had a wrong ident :level which you are trying to bind with the following statement $stmt->bindParam(':lv', $this->lv, PDO::PARAM_INT); so you have to change it with :lv or chenge the binding statement to $stmt->bindParam(':level', $this->lv, PDO::PARAM_INT);.
Second - while you are trying to concatenate a column you have to remove the quotes so it should be CONCAT('a.Level', and if the second operator is a string it should be in single quotes, so the full CONCAT operator should be written as follow CONCAT(a.Level, ':lv')
I'm having an issue with a prepared statement with a parameter, please see below.
I apologise in advance if this turns out to be some dumb mistake.
The error:
Failed to run query (Project List) - SQLSTATE[42000]: Syntax error or access violation: 1064
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''0,8'' at line 1
The code:
$limit = ($pagenum - 1) * $page_rows . "," . $page_rows;
print_r($limit); // Prints 0,8 as expected
$query = "SELECT * FROM projects INNER JOIN users ON projects.companyid = users.companyid ORDER BY projects.projectid DESC LIMIT :limit";
$query_params = array (
':limit' => $limit
);
try {
$stmt = $db->prepare($query);
$stmt->execute($query_params);
}
catch (PDOException $ex) {
die("Failed to run query (Project List)" . " - " . $ex->getMessage());
}
What I've tried so far:
Added the SQL Limit as part of the $limit string
Renamed the limit parameter/variables just in case (reserved keyword etc)
Tested the SQL query manually in SQLyog with the LIMIT 0,8 - works fine
Tested the prepared statement by directly passing the limit variable - works fine
Read all similar questions suggested, no similar issues found at least within my level of understanding.
Your $limit parameter is being escaped as one parameter, where it should be escaped as two. Your sql will currently look something like "limit '0, 8';" where it should look like "limit 0, 8";
To solve this, you should split your limit parameter into two. Edit the end of your SQL to look like:
LIMIT :offset, :limit
And your parameter list to look like:
$query_params = array (
':offset' => ($pagenum - 1) * $page_rows,
':limit' => $page_rows
);
As Mr Smith mentioned, you'll also have to add the line:
$db->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );
To ensure the limit parameters are correctly handled as integers rather than strings.
I'm having a little problem getting a sql query with prepare on PDO, I have this code:
$portfolio = $db->prepare("SELECT * FROM `news`, `:sub` WHERE `news`.`id` = `:sub`.`id_news` AND `page` = `:under` ORDER BY `date` DESC LIMIT :start, :limit");
$portfolio->bindParam(':under', $_GET['under'], PDO::PARAM_STR);
$portfolio->bindParam(':sub', $_GET['sub'], PDO::PARAM_STR);
$portfolio->bindParam(':start', $start, PDO::PARAM_INT);
$portfolio->bindParam(':limit', $limit, PDO::PARAM_INT);
$portfolio->execute();
But this doesn't give any value and my DB has the values correct, any one knows why this doesn't work?
PS: var $start and $limit are fine, no problem with it cuz it's pagination script, that work very fine in all the pages.
For exemple i'm in the url: mysite.com/index.php?sub=vid&under=info
so the query should be like this:
"SELECT * FROM `news`, `vid` WHERE `news`.`id` = `vid`.`id_news` AND `page` = `info` ORDER BY `date` DESC LIMIT 0, 10"
So for what i understood having this code before should work and still be safe right?
switch($_GET['sub']){
case "vid":
$table = "vid";
break;
case "img":
$table = "img";
break;
}
$portfolio = $db->prepare("SELECT * FROM `news`, `$table` WHERE `news`.`id` = `$table`.`id_news` AND `page` = :under ORDER BY `date` DESC LIMIT :start, :limit");
You can't use query parameter placeholders for table names or column names.
Use query parameters only to substitute for a literal value in an expression. I.e. a quoted string, quoted date, or numeric value.
Also, even if you are using a parameter for a string or date, the parameter doesn't go inside quotes.
To make table names or column names dynamic, you have to interpolate application variables into your SQL string before you submit the string to prepare().
But be careful to validate user input (e.g. $_GET variables) so you avoid SQL injection. For instance, test the input against a list of known legitimate table names.
Example:
$subtables = array(
"DEFAULT" => "text",
"text" => "text",
"vid" => "vid",
"pic" => "pic"
);
// if the key exists, use the table name, else use the default table name
$subtable = $subtables[ $_GET["sub"] ] ?: $subtables[ "DEFAULT" ];
// now $subtable is effectively whitelisted, and it is safe to use
// without risk of SQL injection
$portfolio = $db->prepare("SELECT *
FROM news, `$subtable` AS sub
WHERE news.id = sub.id_news
AND page = :under
ORDER BY date DESC LIMIT :start, :limit");
You can't use parameters for the names of tables and table object (i.e fields). See this question where this is covered.
Can PHP PDO Statements accept the table or column name as parameter?
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );
are two magical lines that will solve all your minor problems after you fix the BIGGEST one - a dynamically linked table.
What it have to be is a single table where "sub" is a field name to distinguish a category
SELECT * FROM news n, subnews s
WHERE n.id = id_news AND s.sub =:sub AND `page` = :under
ORDER BY `date` DESC LIMIT :start, :limit
Also you have to quit that habit of wrapping in backticks everything that moves.
Im using dbal on Symfony2 to retrieve some info from my table:
$social = $conn->fetchAll('SELECT * FROM page WHERE brand_id = :brand LIMIT :start,:limit', array('brand'=>$brand, 'start'=>(int) $start, 'limit'=>(int) $limit));
Im getting an error only when I add the last part (LIMIT ....), this make me think that i cant limit the result inside the sql query but outside using some kind of command. How can i solve this?
Error:
An exception occurred while executing 'SELECT * FROM page WHERE brand_id = :brand LIMIT :start,:limit' with params {"brand":1,"start":0,"limit":4}:
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''0','4'' at line 1
$statement = $connection->prepare(
'SELECT ... LIMIT :limit'
);
$statement->bindValue('limit', $limit, \PDO::PARAM_INT);
$statement->execute();
$result = $statement->fetchAll();
Or you can simply use 3rd argument in the fetchAll($sql, array $params = array(), $types = array()) like that:
$social = $conn->fetchAll('SELECT * FROM page WHERE brand_id = :brand LIMIT :start,:limit', array('brand'=>$brand, 'start'=>(int) $start, 'limit'=>(int) $limit), array(\PDO::PARAM_STR, \PDO::PARAM_INT, \PDO::PARAM_INT));