PHP PDO: Can't bind value to multiple variables? - php

I am trying to execute a query that joins several tables using the same foreign key via the below query but it returns false.
$question_id = 11406;
$query = $db->prepare("SELECT q.question_attempts_permitted, q.question_range, a.answer_text, r.attempt_count
FROM checkup_questions q, checkup_answers a, user_responses r
WHERE a.question_id=:question_id AND q.question_id=:question_id AND r.question_id=:question_id");
$query->bindValue(':question_id', $question_id, PDO::PARAM_INT);
$query->execute();
However, if I inject the question_id directly the query returns the desired result.
$query = $db->prepare("SELECT q.question_attempts_permitted, q.question_range, a.answer_text, r.attempt_count
FROM checkup_questions q, checkup_answers a, user_responses r
WHERE a.question_id=11406 AND q.question_id=11406 AND r.question_id=11406");
$query->execute();
Is there some limitation with the bindValue interface that causes the first query to fail while the second one returns as expected?

Query text should be rewritten using JOIN:
$query = $db->prepare("
SELECT q.question_attempts_permitted, q.question_range, a.answer_text, r.attempt_count
FROM checkup_questions q
JOIN checkup_answers a ON a.question_id = q.question_id
JOIN user_responses r ON r.question_id = q.question_id
WHERE q.question_id=:question_id
");
// you can provide placeholder without `:`
$query->bindValue('question_id', $question_id, PDO::PARAM_INT);
$query->execute();
Here you have only one placeholder.

Related

PHP MySQLi get columns from foreign key

I have the following tables:
'auktionen'
id|uid|typ(FK)|min|max|menge|...
'typen'
id|typ
1|Hack
2|Schredder
where typ in typen is just a textutal representation, which I would like to get.
$prep_stmt = "SELECT anzeigentyp, typ, holzart,
qualitaet, rinde, min, max, menge FROM auktionen WHERE uid = ?";
$stmt = $mysqli->prepare($prep_stmt);
$stmt->bind_param('i', $user_id);
$stmt->execute();
$stmt->bind_result($anzeigentyp, $typ, $holzart, $qualitaet, $rinde, $min, $max, $menge);
$stmt->store_result();
So when fetching all my results I want to get "Hack" instead of the referencing id (in case it is 1). I guess it needs some JOIN to be achieved and I tried it like this without success:
$prep_stmt = "SELECT anzeigentyp, typen.typ, holzart,
qualitaet, rinde, min, max, menge FROM auktionen WHERE uid = ?
JOIN typen ON auktionen.typ = typen.typ";
What is the proper way to do it?
You must move the where clause to the end and join the corresponding columns typen.id and auktionen.typ
select a.anzeigentyp, t.typ, a.holzart, a.qualitaet, a.rinde, a.`min`, a.`max`, a.menge
from auktionen a
join typen t on t.id = a.typ
where ...

Query works on Sequel Pro but not on my php script

This query works fine on Sequel Pro:
SELECT t1.* FROM `erapido_messages` t1
LEFT OUTER JOIN `erapido_messages` t2 ON `t1.sender_id` = `t2.sender_id`
AND (`t1.msg_date` < `t2.msg_date` OR `t1.msg_date` = `t2.msg_date` AND `t1.sender_id` != `t2.sender_id`)
WHERE `t2.sender_id` IS NULL AND `t1.sender_id`!= `0` AND `t1.receiver_id`= 28
ORDER BY `t1.msg_date` DESC;
When I use it on my php script it returns an error. This is the complete query in php:
$query = "SELECT t1.* FROM `erapido_messages` t1
LEFT OUTER JOIN `erapido_messages` t2 ON `t1.sender_id` = `t2.sender_id`
AND (`t1.msg_date` < `t2.msg_date` OR `t1.msg_date` = `t2.msg_date` AND `t1.sender_id` != `t2.sender_id`)
WHERE `t2.sender_id` IS NULL AND `t1.sender_id`!= `0` AND `t1.receiver_id`= ?
ORDER BY `t1.msg_date` DESC";
//$sql is my connection and it works fine on other queries
$statement = $sql->prepare($query);
//bind parameters for markers: s = string, i = integer, d = double, b = blob
$statement->bind_param('i', $receiver_id);//$receiver_id is defined
//execute query
$statement->execute();
//store the results; allows to count the rows
$statement->store_result();
//bind result variables
$statement->bind_result($id, $receiver_name, $receiver_img, $receiver_email, $sender_id, $sender_name, $sender_email, $sender_img, $subject, $message, $msg_date);
This is the error:
Fatal error: Call to a member function bind_param() on boolean in /messages.php on line 53
I understand that this statement may return 'false' if the query fails:
$statement = $sql->prepare($query);
However, I can't see what is wrong in the query. Any help is welcome!
Thanks much.
Your prepare statement is returning false due to not valid query string. Change your query like the one below. Currently you are escaping your column names because they are in back-tick which results in an error while preparing it
$query = "select * from `dbname` table where `table`.column= ?
ORDER BY `table`.column DESC LIMIT 2 ";
That should fix this error.

How to use common parameter for Mysql PDO query

I have tried to make a search query and my query statement is like the following:
<?php
$query= $db->prepare("SELECT
p.id,
p.name,
p.surname,
p.phone,
t.title,
j.job,
d.department
FROM
People p
JOIN
Titles t ON p.title_id = t.id
JOIN
Departments d ON p.dept_id = d.id
JOIN
Jobs j ON p.job_id = j.id
WHERE
p.name LIKE :v1 OR
p.surname LIKE :v2 OR
p.phone LIKE :v3 OR
ORDER BY
d.department,
p.name,
p.surname"
);
$query->bindValue(":v1", $value, PDO::PARAM_STR);
$query->bindValue(":v2", $value, PDO::PARAM_STR);
$query->bindValue(":v3", $value, PDO::PARAM_STR);
?>
$value comes from a textbox in which search string is typed. The query works fine.
What I want to learn is why I have to use 3 parameters for just one value. Why cannot I type the statement like:
p.name LIKE :v1 OR
p.surname LIKE :v1 OR
p.phone LIKE :v1 OR
and then bind the parameter once only?
$query->bindValue(":v1", $value, PDO::PARAM_STR);
http://paul-m-jones.com/archives/243
Something about stability in memory handling..
I wrote this as an answer because I cant comment yet.
The doc of PDO::prepare() says:
You cannot use a named parameter marker of the same name twice in a prepared statement.

bindParam is not completing the sql query

I'm new to PDO statements and so far I've managed to work with it, use prepared statements and many things, until today.
I have two querys, the first retrieve some data, store the results and then the second query uses that data to retrieve the final data. I'm working on a bad designed DB, that's why I have to do weird things.
The first query gets the year of start and the year of end of a sport league. Then, the year is passed to the second query to get data between those years (WHERE).
The problem is that bindParam seems to not work, it doesn't bind the parameter, shows a ?, and then the SQL throws the following exception:
Connection failed: 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 ''0701' AND ?'0630' ORDER BY e.FECHA DESC' at line 5
The SQL:
$sqlQueryAuxiliar = "SELECT ano_inicio, ano_fin
FROM TEMPORADAS
ORDER BY ano_inicio DESC
LIMIT 1;";
$sqlQuery = "SELECT e.id, e.JORNADA, DATE_FORMAT(e.FECHA, '%Y-%m-%d'),
e.HORA, c1.nombre_temporada, c2.nombre_temporada
FROM ENCUENTROS AS e
JOIN CLUBS AS c1 ON (e.COD_EQUIL = c1.siglas)
JOIN CLUBS AS c2 ON (e.COD_EQUIV = c2.siglas)
WHERE e.FECHA BETWEEN :anoInicio'0701' AND :anoFinal'0630'
ORDER BY e.FECHA DESC;";
And this is the PHP code:
$this->_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmtAux = $this->_db->prepare($sqlQueryAuxiliar);
$stmtAux->execute();
$fetched = $stmtAux->fetchAll();
$stmtAux = null;
$stmt = $this->_db->prepare($sqlQuery);
$stmt->bindParam(':anoInicio', $fetched[0][0], PDO::PARAM_STR, 12);
$stmt->bindParam(':anoFinal', $fetched[0][1], PDO::PARAM_STR, 12);
$stmt->execute();
while ($row = $stmt->fetch()) {
$partidos[] = $row;
}
$stmt = null;
You cannot concatenate strings in your query this way. Change your query to
SELECT e.id, e.JORNADA, DATE_FORMAT(e.FECHA, '%Y-%m-%d'), e.HORA, c1.nombre_temporada, c2.nombre_temporada
FROM ENCUENTROS AS e
JOIN CLUBS AS c1 ON (e.COD_EQUIL = c1.siglas)
JOIN CLUBS AS c2 ON (e.COD_EQUIV = c2.siglas)
WHERE e.FECHA BETWEEN :anoInicio AND :anoFinal
ORDER BY e.FECHA DESC
and the bindParams to
$stmt->bindValue(':anoInicio', $fetched[0][0] . '0701', PDO::PARAM_STR);
$stmt->bindValue(':anoFinal', $fetched[0][1] . '0630', PDO::PARAM_STR);
Stands to reason, you're building invalid sql:
WHERE e.FECHA BETWEEN :anoInicio'0701' AND :anoFinal'0630'
would be built as basically
WHERE e.FETCHA BETWEEN foobar'0701' AND barbaz'0630'
which is a syntax error.
You probably want
WHERE e.FETCH BETWEEN concat(:anoInicio, '0701') AND concat(:anoFinal, '0630')
instead.
If you are using bound parameters you should not also be passing in a hard-coded value in your query..
"SELECT e.id, e.JORNADA, DATE_FORMAT(e.FECHA, '%Y-%m-%d'), e.HORA, c1.nombre_temporada, c2.nombre_temporada
FROM ENCUENTROS AS e
JOIN CLUBS AS c1 ON (e.COD_EQUIL = c1.siglas)
JOIN CLUBS AS c2 ON (e.COD_EQUIV = c2.siglas)
WHERE e.FECHA BETWEEN :anoInicio AND :anoFinal
ORDER BY e.FECHA DESC;";

PHP: output count()

How do i work with the COUNT()
$sql = $connect->prepare("SELECT COUNT() FROM discos_events e INNER JOIN discos_events_guests eg ON (e.ID = eg.eID) INNER JOIN users u ON (eg.uID = u.id) WHERE e.dID =:id");
$sql->bindValue(":id", $cID);
$sql->execute();
...then what? echo $sql["count"]; ? to output the count?
You need an alias name for your COUNT() column:
$sql = $connect->prepare("SELECT COUNT() AS num_events FROM discos_events e INNER JOIN discos_events_guests eg ON (e.ID = eg.eID) INNER JOIN users u ON (eg.uID = u.id) WHERE e.dID =:id");
$sql->bindValue(":id", $cID);
// Fetch the results and then access the alias
$sql->execute();
$result = $sql->fetch();
echo $result['num_events'];
you need to execute() the query, so:
$result = $sql->execute(array('id' => $cId)); // just to illustrate that you can use this instead of bindParam
if ($result) {
$row = $sql->fetch();
}
after execute, you have to store_result() and fetch()
As #Michael suggests, you may alias the count(), to get it in more reatable form.
Your query needs to assign the count value to a name, like so:
SELECT COUNT() n FROM discos_events ...
Then you can reference the name n in your PHP array:
echo $sql["n"];
You can, of course, call it 'count' or any other name you prefer, but be careful of using names which are reserved words in SQL (such as 'count'). If you want to give it a reserved name, you need to enclose it in backtick characters so that SQL recognises that it's a name you want to use rather than its own reserved word.

Categories