"SELECT * ..." mysqli parametrized query - how to store results without binding? - php

I want to store mysqli query results to array.
My code so far looks like this:
function get_nearby_users($Id, $MaxDistance, $RowLimit, $RowLimitOffset)
{
try
{
$query = "SELECT
others.*,
Distance(me.Latitude, me.Longitude, others.Latitude, others.Longitude) as Distance
from
Users me
join
Users others
where
me.Id = ?
and
others.Id != ?
having Distance < ?
limit ?,?
";
$stmt = $this->link->prepare($query);
$stmt->bind_param('iiiii', $Id, $Id, $MaxDistance, $RowLimitOffset, $RowLimit);
$stmt->execute();
// how to fill $rows_array?
}
catch(Exception $exc)
{
// ...
}
return $rows_array;
}
How can I put my results to array when my SQL contains something like "SELECT *"?
All tutorials with parametrized queries use bind_result function, but I don't want to create variables for all fields and bind them. There is no other way?

You do not need to use bind_result to store the record set.
Just use fetchAll() to store result set rows as an array.
$rows_array = $stmt->fetchAll();
I have modified your code. Use this:
function get_nearby_users($Id, $MaxDistance, $RowLimit, $RowLimitOffset)
{
try
{
$query = "SELECT
others.*,
Distance(me.Latitude, me.Longitude, others.Latitude, others.Longitude) as Distance
from
Users me
join
Users others
where
me.Id = ?
and
others.Id != ?
having Distance < ?
limit ?,?
";
$stmt = $this->link->prepare($query);
$stmt->bind_param('iiiii', $Id, $Id, $MaxDistance, $RowLimitOffset, $RowLimit);
$stmt->execute();
$rows_array = $stmt->fetchAll(); // store result set rows as an array
}
catch(Exception $exc)
{
// ...
}
return $rows_array;
}

Related

Prepared statement with PHP and MSSQL

I have an odd scenario about pdos. With prepared statements I get 0 results from database. But hardcoded I get normal results. This is a sql query for mssql (< 2012) to get limited results.
Prepared Statement (just do not wonder about the top and offset variable. I'm setting those in the function just for testing purpose. Also $conn is edited for stackoverflow. The prepare function is reachable from the function, so there is no problem):
public function myFunction($top, $offset) {
try {
$top = 20;
$offset = 1;
$sql = "SELECT TOP :top * FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY id) AS t1
FROM myTable) AS nU WHERE t1 >= :offset";
$statement = $conn->prepare($sql);
$statement->execute(array(':top' => $top, ':offset' => $offset));
return $statement->fetchAll();
} catch (Exception $e) {
echo $e->getMessage();
}
}
Result is an array with 0 elements.
But with this it works perfectly:
public function myFunction($top, $offset) {
try {
$top = 20;
$offset = 1;
$sql = "SELECT TOP 20 * FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY id) AS t1
FROM myTable) AS nU WHERE t1 >= 1";
$statement = $conn->prepare($sql);
$statement->execute();
return $statement->fetchAll();
} catch (Exception $e) {
echo $e->getMessage();
}
}
With this I get results correctly.
How this is possible? What's wrong with the prepared statement? I have a lot of prepared statements and it worked fine before.
Thanks for answers.
#EDIT - updated code - still not working:
public function myFunction($top, $offset) {
try {
$top = 20;
$offset = 1;
$sql = "SELECT TOP :top * FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY id) AS t1
FROM myTable) AS nU WHERE t1 >= :offset";
$statement = $conn->prepare($sql);
$statement->bindParam(':top', $top, PDO::PARAM_INT);
$statement->bindParam(':offset', $offset, PDO::PARAM_INT);
$statement->execute();
return $statement->fetchAll();
} catch (Exception $e) {
echo $e->getMessage();
}
}
It's not allowed to use parameter bindings in PDO for SELECT and FROM part of a sql query.
I replaced the whole query with another one where I don't have to set TOP

SQLITE build query string from values passed

Hi have a function that gets passed strings via the below;
getFilterResults($id, $limit, $misc);
and in my function i connect to SQLite DB and build a query based on the values passed through, like so;
function getFilterResults($id, $limit, $misc) {
$dbConnect = new SQLite3(database);
if(!empty($limit) && !empty($id) && !empty($misc)){
$buildString = ('SELECT * FROM fields ORDER BY id DESC');
}else{
//no params filters arrived so dont filter - aka get all results
$buildString = ("SELECT * FROM fields ORDER BY id DESC");
}
$query = $dbConnect->query($buildString);
//...
}
Issue is how do I build the query if some of the values are empty and I have to decide which value uses/starts of the 'WHERE' query..obviously the first value return that is not null starts of the 'WHERE'..
I can see the long way would be to loop through each one and build - once the first value found that is not null and kick off from there but that seems unpractical and not good practice.
//check if limit set..
if($limit) {
$doLimit = 'LIMIT '.$limit.'';
}
WHERE 'id = '.id.' AND misc = '.$misc.' '.$doLimit.'
Your function taking in ($id, $limit, $misc) really prevents you from being able to do anything else than what you already are... I would recommend using prepared statements though
// Stores values for a prepared statement
$values = [];
$sqlite = new SQLite3(/* ... */);
$query = 'SELECT * FROM fields WHERE id = ? AND misc = ? ORDER BY id DESC';
$values[] = $id;
$values[] = $misc;
if ($limit) {
$query .= ' LIMIT ?';
$values[] = $limit;
}
// Use prepare and let SQLite3 escape the values for you
$stmt = $sqlite->prepare($query);
foreach ($values as $idx => $val) {
$stmt->bindValue($idx, $val);
}
$result = $stmt->execute();

Getting correct Total Row count and Row Numbers for Pagination

Now I have done this easily with PDO and SQL server however I am struggling getting this working correctly for any general Query. Since I do want this to be reusable by our MySQL tables over any project I am turning here for help.
So the way I used it for PDO and SQL server
function pagedQuery($dbh,$q,$sort,$offset,$limit,$params = array()) {
$limit = preg_replace("/[^0-9]]/","",$limit);
$offset = preg_replace("/[^0-9]]/","",$offset);
$q = preg_replace("/^[^\w]*SELECT/i","SELECT COUNT(*) OVER() as num_rows, ROW_NUMBER() OVER(ORDER BY $sort) AS rownum,",$q);
$q = "SELECT * FROM (".$q.") as pagingTable WHERE rownum > $offset AND rownum <= ($offset+$limit)";
## Prepare Query
$stmt = $dbh->prepare($q);
try {
$stmt->execute($params);
} catch(PDOException $e) {
print $e->getMessage();
}
## Return Results
return $stmt->fetchAll();
Now obviously the OVER functionality does not exist and MySQL and this has to be modified. Here is my attempt at a new version:
function mysqlPagedQuery($dbh,$q,$table,$sort,$offset,$limit,$params = array()) {
$limit = preg_replace("/[^0-9]]/","",$limit);
$offset = preg_replace("/[^0-9]]/","",$offset);
$q = preg_replace("/^[^\w]*SELECT/i","SELECT (SELECT COUNT(*) as num_rows FROM ".$table.") AS num_rows, #rowN := #rowN + 1 AS rownum,",$q);
$q = "SELECT * FROM (".$q.") as pagingTable WHERE rownum > $offset AND rownum <= ($offset+$limit)";
## Prepare Query
$stmt = $dbh->prepare($q);
try {
$query = $dbh->query("set #rowN = 0;");
$stmt->execute($params);
} catch(PDOException $e) {
print $e->getMessage();
}
## Return Results
return $stmt->fetchAll();
Now this will "work" given that you give it a table but I soon realized that the num_rows will not return the correct value unless given all of the WHERE clause of the query sent into it. I would have to parse that in an inefficient manner and I feel there is a much easier way to do this than I am making it out to be.
I ended up with this thanks to bobkingof12vs posted link. Can't give answer credit to him directly because it was not posted here :(
function mysqlPagedQuery($dbh,$q,$sort,$offset,$limit,$params = array()){
$limit = preg_replace("/[^0-9]]/","",$limit);
$offset = preg_replace("/[^0-9]]/","",$offset);
//need to use the original query a few times to create paged
$tempQuery = $q;
//replaces query's select with a count to get numrows
$q1 = "SELECT sql_calc_found_rows * FROM (".$tempQuery.") AS tempTable";
## Prepare Query
$stmt1 = $dbh->prepare($q1);
$q2 = preg_replace("/^[^\w]*SELECT/i","SELECT FOUND_ROWS() as num_rows,",$tempQuery);
$q2 .= " ORDER BY ".$sort;
$q2 .= " LIMIT ".$offset.",".$limit;
//print $q2;
## Prepare Query
$stmt2 = $dbh->prepare($q2);
try{
$stmt1->execute();
$stmt2->execute($params);
}
catch(PDOException $e){
print $e->getMessage();
}
## Return Results
return $stmt2->fetchAll();
}

count rows and echo the result

I am trying to do a row count, I want to count a row (nummer) and if there is more then 1 row with the same number then echo. but no matter how many rows I have in my tabel, it only returs 0
$nummer = $_GET['nummer'];
$pdo = Database::connect();
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$result = $pdo->prepare("select count(*) from rum where nummer=:n");
$result->bindParam(':n', $nummer, PDO::PARAM_INT);
$result->execute();
$rows = $result->fetchAll;
if(count($rows) >1) {
echo "1";}
else {
echo "0";
}
The following statement
$result = $pdo->prepare("select count(*) from rum where nummer=:n");
will always return one row with the count number, so doing
$rows = $result->fetchAll;
will always return one.
You may do as
$result = $pdo->prepare("select count(*) as tot from rum where nummer=:n");
....
....
$rows = $result->fetchAll();
if($rows["tot"] > 0 ){
echo 'something'
}else{
echo 'something else'
}
just use fetch() instead of fetchAll()
$rows = $result->fetch();
if($rows[0]) >1) {
echo "1";
} else {
echo "0";
}
It looks like you're having two mistakes.
First one: If you're querying for COUNT(*) - you are getting a number of rows. For example: You're return will be a field named COUNT(*) with one row containing the number of rows found.
If you replace
$result = $pdo->prepare("select count(*) from rum where nummer=:n");
with
$result = $pdo->prepare("select * from rum where nummer=:n");
Second one:
Replace
$rows = $result->fetchAll;
With
$rows = $result->fetchAll();
fetchAll() is no property but a method.
The other way would be your query but naming the field (MySQL AS keyword) and calling $rows = $result->fetch(); afterwards and checking $rows->fieldName for the number of found rows.
Use PDOStatement::fetchColumn(). It is useful for "one-column" resultsets (which relatively often produced by queries like SELECT COUNT(...) FROM ...). Example:
$nummer = isset($_GET['nummer']) ? $_GET['nummer'] : null;
$pdo = Database::connect();
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $pdo->prepare('SELECT COUNT(*) FROM rum WHERE (nummer = :n)');
$stmt->bindParam(':n', $nummer, PDO::PARAM_INT);
$stmt->execute();
$rows = $stmt->fetchColumn();
echo $rows > 1 ? "1" : "0";

Fetching data from database into array

I am using mysqli to fetch data from the database and put it into an array with a while loop. When i echo out the array i get an empty array however in a function i previously did this code worked but it had a different result from the database. I know that the database is giving out good data because when i echo out the result $idGroup it gives me 2 which is correct.
Ps i know it will keep replacing itself because i don't specify an index
private function Groups()
{
$functionRun = 0;
$i = 0;
$helperArray = array();
$this->grouplist = array();
$query = "SELECT GroupName, Groups.idGroup
FROM Groups
INNER JOIN Members
ON Groups.idGroup = Members.idGroup
WHERE Members.idMember = ? ";
//prepare query and execute
if($stmt = $this->connection->prepare($query))
{
$stmt->bind_param('s', $this->id);
$stmt->execute();
$stmt->bind_result($GroupName, $idGroup);
while ($stmt->fetch())
{
$helperArray[] = $idGroup;
}
echo $helperArray;
}
Use print_r when dealing with arrays. Use echo on strings.
Try this
$query = "SELECT GroupName, Groups.idGroup
FROM Groups
INNER JOIN Members
ON Groups.idGroup = Members.idGroup
WHERE Members.idMember = ? ";
//prepare query and execute
if($stmt = $this->connection->prepare($query))
{
$stmt->bind_param('s', $this->id);
$stmt->execute();
$stmt->bind_result($GroupName, $idGroup);
$helperArray =array();
while ($stmt->fetch())
{
$helperArray[] = $idGroup;
}
print_r($helperArray);
}

Categories