I have a series of links that pass information to a new page to run a MySQL query. This is one of the links from source code:
<a class="bloglink" href="parknews.php?tpf_news.park_id=5">
and this is the code that generates the links:
<a class="bloglink" href="parknews.php?tpf_news.park_id=<?php echo $row2['park_id'];?>">
<?php echo $row2['name']; ?>
</a>
The query that uses that info is here:
$park_id = $_GET['tpf_news.park_id'];
$sql = 'SELECT headline, story, DATE_FORMAT(date, "%d-%M-%Y") AS date, name
FROM tpf_news
INNER JOIN tpf_parks ON tpf_news.park_id = tpf_parks.park_id WHERE tpf_news.park_id = $park_id ORDER BY date DESC' ;
This causes this error to display:
Error fetching news: SQLSTATE[42S22]: Column not found: 1054 Unknown column '$park_id' in 'where clause'
I can't work out why it is not working. If in the query I replace WHERE tpf_news.park_id = $park_id with WHERE tpf_news.park_id = 6 (or any other number), it works fine.
Any ideas?
When your strings are in quotes your variables aren't interpolated. So you need to use double quotes instead:
$sql = "SELECT headline, story, DATE_FORMAT(date, '%d-%M-%Y') AS date, name
FROM tpf_news
INNER JOIN tpf_parks ON tpf_news.park_id = tpf_parks.park_id WHERE tpf_news.park_id = $park_id ORDER BY date DESC" ;
Or use concatenation:
$sql = 'SELECT headline, story, DATE_FORMAT(date, "%d-%M-%Y") AS date, name
FROM tpf_news
INNER JOIN tpf_parks ON tpf_news.park_id = tpf_parks.park_id WHERE tpf_news.park_id =' . $park_id .' ORDER BY date DESC' ;
FYI, you also wide open to SQL injections
You have your SQL in single quotes. That means the variable will not be displayed as you think. Use double quotes.
And for the love of GOD us prepared statements.
$sql = "SELECT headline, story, DATE_FORMAT(date, "%d-%M-%Y") AS date, name
FROM tpf_news
INNER JOIN tpf_parks ON tpf_news.park_id = tpf_parks.park_id WHERE tpf_news.park_id=$park_id ORDER BY date DESC" ;
$sql = 'SELECT headline, story, DATE_FORMAT(date, "%d-%M-%Y") AS date, name
FROM tpf_news
INNER JOIN tpf_parks ON tpf_news.park_id = tpf_parks.park_id WHERE tpf_news.park_id='.$park_id.' ORDER BY date DESC' ;
Related
I found myself in a really weird situation in PDO. A query doesn't want to execute when called from PhP but it does when called from HeidiSQL.
The error is in title.
SQL query from statement debugDumpParams :
SELECT s_id AS id,
s_title AS title,
genre.g_name AS genreName,
accounts.ac_public_name AS producerName,
s_price AS price,
DATE_FORMAT(s_last_modified_date, '%d/%m/%Y %H:%i:%s') AS lastModifiedDate,
DATE_FORMAT(s_added_date, '%d/%m/%Y %H:%i:%s') AS addedDate,
s_downloads AS downloads,
s_sales AS sales,
s_rating AS rating,
s_status AS STATUS
FROM song
JOIN accounts ON accounts.ac_id = song.s_producer
JOIN genre ON genre.g_id = song.s_genre
WHERE 1=1 AND genre.g_id = '1'
ORDER BY s_status ASC, s_added_date DESC
LIMIT 0, 5;
Next is the part where I add genre.g_id = :id in the query string
if(isset($filterData["genreId"]) && $filterData["genreId"] !== ""){
$queryString .= " AND genre.g_id = :genreId";
}
And where I bind it
if(isset($filterData["genreId"]) && $filterData["genreId"] !== ""){
$genreParam = $filterData["genreId"];
$stmt->bindParam('genreId', $genreParam);
}
In both cases $filterData["genreId"] is set and it have a value, so no problems with the if. And if $filterData["genreId"] would be empy or not set there would be no problem with the query.
And the error : SQLSTATE[42S22]: Column not found: 1054 Unknown column \'genre.g_id\' in \'where clause\'
But wait, there is more.
If I put genre.g_id2 instead of genre.g_id it will look like this:
if(isset($filterData["genreId"]) && $filterData["genreId"] !== ""){
$queryString .= " AND genre.g_id2 = :genreId";
}
Now it won't even reach $stmt->debugDumpParams();
And all it gives out it's this error: SQLSTATE[42S22]: Column not found: 1054 Unknown column \'genre.g_id2\' in \'where clause\ , no query like before.
The column 100% exists in the table. Similar problem whith this query:
SELECT s_id AS id,
s_title AS title,
genre.g_name AS genreName,
accounts.ac_public_name AS producerName,
s_price AS price,
DATE_FORMAT(s_last_modified_date, '%d/%m/%Y %H:%i:%s') AS lastModifiedDate,
DATE_FORMAT(s_added_date, '%d/%m/%Y %H:%i:%s') AS addedDate,
s_downloads AS downloads,
s_sales AS sales,
s_rating AS rating,
s_status AS STATUS
FROM song
JOIN accounts ON accounts.ac_id = song.s_producer
JOIN genre ON genre.g_id = song.s_genre
WHERE 1=1 AND accounts.ac_id = '999999'
ORDER BY s_status ASC, s_added_date DESC
LIMIT 0, 5;
It seems the problem is only with columns that are from the tables that table song JOIN with.
Next query works perfectly.
SELECT s_id AS id,
s_title AS title,
genre.g_name AS genreName,
accounts.ac_public_name AS producerName,
s_price AS price,
DATE_FORMAT(s_last_modified_date, '%d/%m/%Y %H:%i:%s') AS lastModifiedDate,
DATE_FORMAT(s_added_date, '%d/%m/%Y %H:%i:%s') AS addedDate,
s_downloads AS downloads,
s_sales AS sales,
s_rating AS rating,
s_status AS STATUS
FROM song
JOIN accounts ON accounts.ac_id = song.s_producer
JOIN genre ON genre.g_id = song.s_genre
WHERE 1=1 AND s_status = '0'
ORDER BY s_status ASC, s_added_date DESC
LIMIT 0, 5;
2 days on this and no solutons. Most solutions I find are to check again if the column really exists :|
Does any one have a better solution for this specific problem ?
The goal is to select the data where the g_id is equal with the value I pass to it.
How I create the query string:
$queryString = "SELECT s_id as id,
s_title as title,
genre.g_name as genreName,
accounts.ac_public_name as producerName,
s_price as price,
DATE_FORMAT(s_last_modified_date, '%d/%m/%Y %H:%i:%s') as lastModifiedDate,
DATE_FORMAT(s_added_date, '%d/%m/%Y %H:%i:%s') as addedDate,
s_downloads as downloads,
s_sales as sales,
s_rating as rating,
s_status as status
FROM song
JOIN accounts on accounts.ac_id = song.s_producer
JOIN genre on genre.g_id = song.s_genre
WHERE 1=1 ";
then in a function I add this
if(isset($filterData["genreId"]) && $filterData["genreId"] !== ""){
$queryString .= " AND genre.g_id = :genreId";
}
then I do this
$queryString .= " ORDER BY s_status asc, s_added_date desc";
$queryString .= " LIMIT :offset, :limit;";
and finally
$stmt = $dbConnector->getConnection()->prepare($queryString);
This is the part that is related to the problem. I can't post the entire function, it's really long.
This is used to search data based on some inputs or combinations of inputs. The entire DAO class is really big :)
OS: Windows 10,
PhP version: 7.2.19,
Apache version: 2.4.35,
MariaDB version: 10.4
Heidi SQL: 10.2.0.5599
One more edit:
If I add the columun in the queryString when I first declare it:
$queryString = "SELECT s_id as id,
s_title as title,
genre.g_name as genreName,
accounts.ac_public_name as producerName,
s_price as price,
DATE_FORMAT(s_last_modified_date, '%d/%m/%Y %H:%i:%s') as lastModifiedDate,
DATE_FORMAT(s_added_date, '%d/%m/%Y %H:%i:%s') as addedDate,
s_downloads as downloads,
s_sales as sales,
s_rating as rating,
s_status as status
FROM song
JOIN accounts on accounts.ac_id = song.s_producer
JOIN genre on genre.g_id = song.s_genre
WHERE 1=1 AND genre.g_id = :genreId";
$queryString = $this->filterDataQuery($queryString, $filterData, "songs");
$queryString .= " ORDER BY s_status asc, s_added_date desc";
$queryString .= " LIMIT :offset, :limit;";
$stmt = $dbConnector->getConnection()->prepare($queryString);
$genreParam = $filterData["genreId"];
$stmt->bindParam(':genreId', $genreParam);
and not inside $this->filterDataQuery($queryString, $filterData, "songs"); when I build the queryString based on selected filters it works perfectly.
This is the select from the browser console now:
SELECT s_id AS id,
s_title AS title,
genre.g_name AS genreName,
accounts.ac_public_name AS producerName,
s_price AS price, DATE_FORMAT(s_last_modified_date, '%d/%m/%Y %H:%i:%s') AS lastModifiedDate, DATE_FORMAT(s_added_date, '%d/%m/%Y %H:%i:%s') AS addedDate,
s_downloads AS downloads,
s_sales AS sales,
s_rating AS rating,
s_status AS STATUS
FROM song
JOIN accounts ON accounts.ac_id = song.s_producer
JOIN genre ON genre.g_id = song.s_genre
WHERE 1=1 AND genre.g_id = '1'
ORDER BY s_status ASC, s_added_date DESC
LIMIT 0, 5;
Isn't this one the same with the first? For it is. I am blind ?
After rereading your first post dozens of times and testing locally all sorts of normal things without getting the same error, I think the $stmt variable inside filterDataQuery() holds a total different query than posted here. And it just doesn't include the table genre as shown in the error message.
If you're not using that function, seeing your second last code block, all works well (if I understand you correctly).
Also according to the code shown, I don't understand how you would call filterDataQuery() to add criteria to the querystring, and directly binding the params to the statement object that's prepared later on and thus is not available there (or not the one you would expect).
To prove my theory my complete test code, still using this db-fiddle:
ini_set('display_errors', 1);
error_reporting(E_ALL);
$DB_USER = '*****';
$DB_PASS = '*****';
$db = new PDO('mysql:host=localhost;dbname=testing.project', $DB_USER, $DB_PASS);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$select = 'SELECT s_id AS id,
s_title AS title,
genre.g_name AS genreName,
accounts.ac_public_name AS producerName,
s_price AS price,
DATE_FORMAT(s_last_modified_date, "%d/%m/%Y %H:%i:%s") AS lastModifiedDate,
DATE_FORMAT(s_added_date, "%d/%m/%Y %H:%i:%s") AS addedDate,
s_downloads AS downloads,
s_sales AS sales,
s_rating AS rating,
s_status AS STATUS
FROM song
JOIN accounts ON accounts.ac_id = song.s_producer
JOIN genre ON genre.g_id = song.s_genre';
$where = ' WHERE genre.g_id = :genreId';
$order = ' ORDER BY s_status ASC, s_added_date DESC';
$limit = ' LIMIT 0, 5';
// No problemo:
$sql = $select . $where . $order . $limit;
$stmt = $db->prepare($sql);
$genreId = 1;
$stmt->bindParam(':genreId', $genreId);
$stmt->execute();
// Trigger error column not found, $stmt containing an unexpected query:
$select = 'SELECT * FROM `song`';
$sql = $select . $where . $order . $limit;
$stmt = $db->prepare($sql);
$genreId = 1;
$stmt->bindParam(':genreId', $genreId);
$stmt->execute();
First, I don't pass the $stmt variable to filterDataQuery. I pass it to bindParams. bindParams function is called aftert filterDataQuery is done and after adding the strings for order by and limit.
I really have to thank you,Piemol , for trying to help me.
I checked Maria DB logs after a professor from my college adviced me to do so, and I found the problem there
In the same controller I was calling two DAO methods, one after another, one to bring the data, and the sencond to do a count.
$responseMessage = json_encode(AdminDAO::getInstance()->getFilteredSongsList($message));
$count = AdminDAO::getInstance()->getFilteredSongsListItemsCount($message); // this one was the problem
The problem was not in the one that was getting the data, the one I posted about. The problem was with the one doing the count. I did not added the joins there :| .
Alose there where no indication from what method the error was comming so I focused on the wrong one(the one that was displayed in log). Something like this would have never happened if I would have used a logger like I do in Java.
Here are the queries from MariaDB log file: https://www.heypasteit.com/clip/0IUPWG
First one is the one that fails and the 2nd one is the one that works.
I miss log4j from Java so much.
Thanks to everybody who tried to help me.
For those who have this kind of weird problems, check logs, put echos, don't focus on the first thing you see in a AJAX response log.
I'm trying to join two strings together in a prepare statement (table name & column which is dynamic) but I am getting
Uncaught PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'exp.$getSkill' in 'field list'
My code is:
$query = $db->prepare('SELECT members.*, exp.*, lvl.*, exp.$getSkill AS exp_skill, lvl.$getSkill AS level_skill FROM members INNER JOIN exp ON members.id = exp.member_id INNER JOIN lvl ON members.id = lvl.member_id ORDER BY lvl.$getSkill DESC, exp.$getSkill DESC');
$query->execute();
$row = $query->fetch();
Is there a way I can join exp. and $getSkill properly?
Variable aren't evaluated inside strings with single quotes. You'd need to use double quotes, and surround the name with curly braces ({}):
$query = $db->prepare("SELECT members.*, exp.*, lvl.*, exp.${getSkill} AS exp_skill, lvl.$getSkill AS level_skill FROM members INNER JOIN exp ON members.id = exp.member_id INNER JOIN lvl ON members.id = lvl.member_id ORDER BY lvl.$getSkill DESC, exp.$getSkill DESC");
Mandatory note:
Using string concatenation in an SQL query could potentially expose your code to SQL Ijection attacks. You should be very careful if you intend to use such a technique.
Try something like this:
$query = 'SELECT members.*,
exp.*,
lvl.*,
exp.'.$getSkill.' AS exp_skill,
lvl.$getSkill AS level_skill
FROM members
INNER JOIN exp ON members.id = exp.member_id
INNER JOIN lvl ON members.id = lvl.member_id
ORDER BY lvl.$getSkill DESC, exp.$getSkill DESC';
$query = $db->prepare($query);
$query->execute();
$row = $query->fetch();
my code worked good , but when i add
GROUP_CONCAT(CONCAT("<a href='index.php?id=", awards_user.userid, "'>", awards_user.username, "</a>")) AS userlist
to get users-id with username , show me error
Parse error: syntax error, unexpected T_STRING [in this line]
SELECT awards.name as name, awards.link as link,
GROUP_CONCAT(DISTINCT awards_user.username) AS username,
GROUP_CONCAT(DISTINCT awards_user.userid) AS userid,
GROUP_CONCAT(CONCAT("<a href='index.php?id=", awards_user.userid, "'>", awards_user.username, "</a>")) AS userlist
FROM awards LEFT JOIN awards_user ON (awards_user.awardid = awards.awardid)
where awards.forumid = '".$_REQUEST['forumid']."'
GROUP BY awards.awardid, awards.name, awards.link
You should escape double quotes " with backslash \ otherwise php will understand this as the end of the string :
$sql = "SELECT awards.name as name
, awards.link as link
, GROUP_CONCAT(DISTINCT awards_user.username) AS username
, GROUP_CONCAT(DISTINCT awards_user.userid) AS userid
, GROUP_CONCAT(CONCAT(\"<a href='index.php?id=\", awards_user.userid, \"'>\"
, awards_user.username, \"</a>\")) AS userlist
FROM awards LEFT JOIN awards_user ON (awards_user.awardid = awards.awardid)
WHERE awards.forumid = '" . $_REQUEST['forumid'] . "'
GROUP BY awards.awardid
, awards.name
, awards.link";
The escaping of quotes is an issue. So why not use heredoc syntax like this.
$formid = $_REQUEST['forumid'];
$query = <<<EOT
SELECT awards.name as name, awards.link as link,
GROUP_CONCAT(DISTINCT awards_user.username) AS username,
GROUP_CONCAT(DISTINCT awards_user.userid) AS userid,
GROUP_CONCAT(CONCAT("<a href='index.php?id=", awards_user.userid, "'>", awards_user.username, "</a>")) AS userlist
FROM awards LEFT JOIN awards_user ON (awards_user.awardid = awards.awardid)
where awards.forumid = '$formid'
GROUP BY awards.awardid, awards.name, awards.link
EOT;
The idea is heredoc syntax allows for a full string with string replacement & without having to worry about escaping quotes. Or knowing that you can set variables for "<a href='index.php?id=", '> and </a> like this:
$formid = $_REQUEST['forumid'];
$id_link_1 = "<a href='index.php?id=";
$id_link_2 = "'>";
$id_link_3 = "</a>";
$query = <<<EOT
SELECT awards.name as name, awards.link as link,
GROUP_CONCAT(DISTINCT awards_user.username) AS username,
GROUP_CONCAT(DISTINCT awards_user.userid) AS userid,
GROUP_CONCAT(CONCAT($id_link_1, awards_user.userid, $id_link_2, awards_user.username, $id_link_3)) AS userlist
FROM awards LEFT JOIN awards_user ON (awards_user.awardid = awards.awardid)
where awards.forumid = '$formid'
GROUP BY awards.awardid, awards.name, awards.link
EOT;
I have a question how do I add a query for a date range here in my MySQL query. The date is generated only.
Here is my Query:
SELECT TS.id AS TSid, employeeid, `date` AS date_d, TS.TI1 AS TI1, TS.TO1 AS TO1,
CONCAT(E.lastName,', ',E.firstName,' ',E.middleInitial,'.') AS 'fullname',
(TIME_TO_SEC(CAST(TS.`TI1` AS time))/3600) AS 'timeinint',
(TIME_TO_SEC(CAST(TS.`TO1` AS time))/3600) AS 'timeoutint',
E.startDate, C.companyName, B.branchName,
R.mon, R.tue, R.wed, R.thu, R.fri, R.sat, R.sun
FROM timeschedule AS TS
LEFT JOIN employee AS E ON TS.employeeid = E.id
LEFT JOIN company AS C ON E.companyid = C.id
LEFT JOIN branch AS B ON E.branchid = B.id
LEFT JOIN restday AS R ON R.id = E.restDayid
WHERE TS.`show` = '1'
ORDER BY employeeid ASC
HEre is how I get the input:
$mfrom = $this->input->get('mfroma'); //From: Month
$yfrom = $this->input->get('yfroma'); //From: Year
$yto = $this->input->get('ytoa'); //To : Year
With the fields you've specified (from month and year and to year) you can add these conditions into your WHERE clause. I'm going to use the E.startDate field for this example:
$sql = "-- your query here...
WHERE
TS.`show` = '1'
AND MONTH(E.startDate) >= " . $mfrom . "
AND YEAR(E.startDate) BETWEEN " . $yfrom . " AND " . $yto . "
ORDER BY employeeid ASC";
Docs:
- MONTH()
- YEAR()
Note: PHP parses variables inside double quotes, but I personally prefer to keep PHP variables outside of them.
I have the following code:
try
{
$sql = 'SELECT id, type, date, amount, description, category
FROM `transactions`
WHERE type = "income"
AND month(date) = '$monthselect'
ORDER BY `transactions`.`id` DESC
LIMIT 0,50';
$result2 = $pdo->query($sql);
}
Now, I want to give this month(Date) a variable which month I want to select. if I put 1, it will give me January. So i thought, if I define a variable with 1, I can use it to select a month, right?
$monthselect = 1;
It doesnt work. What am I doing wrong?
Use prepared statements:
$stm = $pdo->prepare('SELECT id, type, date, amount, description, category
FROM `transactions`
WHERE type = "income"
AND month(date) = ?
ORDER BY `transactions`.`id` DESC
LIMIT 0,50');
$stm->execute(compact('monthselect'));
$result2 = $stm->fetchAll();
Since you're not adding "1" directly in your query, I'm assuming here that the variable comes from user input.
To concatenate strings in PHP you need to use the . operator.
$sql = 'SELECT id, type, date, amount, description, category
FROM `transactions`
WHERE type = "income"
AND month(date) = ' . $monthselect . '
ORDER BY `transactions`.`id` DESC
LIMIT 0,50';
I'll frequently use double quotes to substitute variables in PHP:
$sql = "SELECT id, type, date, amount, description, category
FROM `transactions`
WHERE type = 'income'
AND month(date) = $monthselect
ORDER BY `transactions`.`id` DESC
LIMIT 0,50";
Note that you need to swap the existing double quotes (inside the string) to single quotes. You can escape them too, but I find this way makes it much more readable.
Your issue is that you are trying to use a variable inside single quotes, inside which php is not translated
I find by using double quote marks around my queries it allows me to not only use variables in them but to also be able to use single quote mark around the values passed to the db
$sql = "SELECT id, type, date, amount, description, category
FROM `transactions`
WHERE type = 'income'
AND month(date) = $monthselect
ORDER BY `transactions`.`id` DESC
LIMIT 0,50";