What does this SQL statement do? - php

I am trying to understand this SQL statements :
$id = 5;
$stmt = $conn->prepare('SELECT * FROM myTable WHERE id = :id');
$stmt->execute(array('id' => $id));
while($row = $stmt->fetch()) {
print_r($row);
}
Can someone please explain me step by step what exactly is going on here?
From what i understand :
$stmt = $conn->prepare('SELECT * FROM myTable WHERE id = :id');
1) $stmt is about to take as iinput an SQL query. The SQL query is to select all the rows from a table that their id is equal to 5.
$stmt->execute(array('id' => $id));
2) We execute the statement. Now the $stmt has these rows?
$row = $stmt->fetch()
3) This is the most confusing line for me. What exactly happens here? Variable "row" takes one by one the rows that have id = 5 ? Is that what fetch() does ? And if yes , how exaxtly does it return the results? Its an array of all the correct answers? EG all the rows that have id = 5 ? I dont understand how exactly this while loop works here.The first time it runs "row" will have the first row ? The second time it runs , will have the second row that satisfies our creteria (id = 5) and so on? Is it like that every time i run fetch one result will be returned? And next time i run fetch , the next result , till there is no more result to satisfy the query?
I thing i am so close to get this one. Anything that could help me understand it completely would be highly appreciated !

I'll explain as comments:
$id = 5;
// Create a prepared statement - don't actually execute the statement yet.
// The :id value in the statement will be replaced by a parameter value (safely) when the
// statement is executed
$stmt = $conn->prepare('SELECT * FROM myTable WHERE id = :id');
// Execute the statement against the DB - the $stmt var now contains the result set for the
// executed statement. e.g. it contains *all* the results that the query fetched
$stmt->execute(array('id' => $id));
// Now we loop through the rows in the result set (they are all in memory at this point).
// "fetch" will start from row 1 and return the next result each time you call it again.
// when there are no more rows it returns FALSE and therefore breaks out of the while loop
while($row = $stmt->fetch()) {
print_r($row);
}
Just checking docs also and whilst this is how it was done previously (been years since I've touched PHP) it looks like stmt->fetch() actually places results into bound variables:
http://php.net/manual/en/mysqli-stmt.fetch.php
$row = array();
stmt_bind_assoc($stmt, $row);
// loop through all result rows
while ($stmt->fetch())
{
print_r($row);
}
Does the code you originally posted actually work? It doesn't appear you bind any variables and therefore since the $stmt-fetch() call returns bool TRUE/FALSE it would seem to be that $row would not get set to anything but TRUE/FALSE

here it uses PDO for execution,
Repeated SELECT using prepared statements through which you can call repeated query
$stmt = $conn->prepare('SELECT * FROM myTable WHERE id = :id');
it defines the prepared statement where :id is placeholder
$stmt->execute(array('id' => $id));
this places assigns the value to placeholder and execute the query
$row = $stmt->fetch()
it fetch the record from select
for more reference visit the link
http://www.php.net/manual/en/pdo.prepared-statements.php

Related

select id from table where it equals to row name

I am trying to store the id of a username which I got from $_SESSION to a variable but I can't get the SQL statement to work. The usernames are stored in a database called users and have an ID as primary key. Can someone tell me how I can correct this? Thanks
$name = $_SESSION['username']; //get username of user currently logged in
$rid = $db->exec("SELECT id FROM users WHERE username = '$name'");
From the PHP documentation on PDO::exec():
PDO::exec() does not return results from a SELECT statement. For a SELECT statement that you only need to issue once during your program, consider issuing PDO::query(). For a statement that you need to issue multiple times, prepare a PDOStatement object with PDO::prepare() and issue the statement with PDOStatement::execute().
This means that you cannot use exec() on a SELECT query - instead, you must use query() or prepare(). For any queries using variables or user-input, use prepare() and placeholders in the query for variables, like below, to protect your database against SQL-injection.
$stmt = $db->prepare("SELECT id FROM users WHERE username = :name");
$stmt->execute(["name" => $name]);
if ($row = $stmt->fetch()) {
// $row holds the id
} else {
// No rows were returned at all! No matches for $name
}
Now $row holds the id(s) if the query returned any result at all. Depending on your fetch-type, it might be $row['id'], $row[0], $row->id or a combination of these.
If you expect more than one result, you need to loop while ($row = $stmt->fetch()), or use $stmt->fetchAll();
http://php.net/manual/en/pdo.exec.php
How can I prevent SQL injection in PHP?

PHP Forloop loops through an array and insert current array item into sql database, only one record inserting

I have a script that gets data from a database, then loops through the results from the SELECT query by using a forloop and has a query that inserts the array data into another datbase. However only the first record gets inserted.
I get no errors
Here is the code.
//Get all from job
$getRecords = $connection->prepare("SELECT `CustomerFirstName`,`CustomerLastName`,`CASS_STD_LINE1`,`CASS_STD_LINE2`,`CASS_STD_CITY`,`CASS_STD_STATE`,`CASS_STD_ZIP`,`CustomerCounty`,`CustomerNumber`,`DealNumber`,`TradeIn_1_VIN`,`TradeIn_1_Make`,`TradeIn_1_Model`,`TradeIn_1_Year`,`FrontGross`,`BackGross`,`HoldBackAmount`,`VehicleYear`,`VehicleMake`,`VehicleModel`,`VehicleVIN`,`EntryDate`,`matched`,`notNew` FROM `auth` WHERE `matched` = ?");
$getRecords->execute(array($_POST['jobName']));
$gotRecords = $getRecords->fetchAll(PDO::FETCH_ASSOC);
$getRecords = null;
//Loop Through all records found with matching job name
for($i=0;$i<count($gotRecords); ++$i){
$rec = $remote->prepare("INSERT INTO `cob_matched_records`(first) VALUES (?)");
$rec->execute(array($gotRecords[$i]['CustomerFirstName']));
}
The problem with your script is most likely the line
$getRecords = null;
destroying the array before the code hits your for-loop.
(But that doesn't fit your description "However only the first record gets inserted.". Did you post the actual, unaltered code?)
The point (or one of the points) of prepared statements is that you prepare them once and then execute them multiple times with varying parameters. So, prepare the INSERT statement once before the loop and then execute it within with the current parameter(s):
// assuming PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION, otherwise error handling is missing....
// you might also be interested in http://docs.php.net/manual/en/pdo.begintransaction.php
$stmtSelect = $connection->prepare("SELECT `CustomerFirstName` FROM `auth` WHERE `matched` = ?");
$stmtInsert = $remote->prepare("INSERT INTO `cob_matched_records` (first) VALUES (?)");
$stmtSelect->execute( array($_POST['jobName']) );
foreach( $stmtSelect as $row ) {
$stmtInsert->execute( array($row['cob_matched_records']) );
}

Check if PDO prepare(), execute() returns at least one row

Before moving to PDO, I used
$result = mysqli_query ($conn, 'SELECT * FROM mytable WHERE id = 54');
if (mysqli_num_rows($result) >= 1) { ... }
to check if the query returns at least one result.
Now with PDO, I've seen in many SO questions (like get number of rows with pdo) that there is no direct function in PDO to check the number of rows of a query (there are warnings about the use of$result->rowCount();), but rather solutions like doing an extra query:
SELECT count(*) FROM mytable WHERE id = 54
But this is maybe too much for what I want : in fact, I don't need the exact number of rows, but just if there is at least one.
How to check if a prepared statement query returns at least one row ?
$stmt = $db->prepare('SELECT * FROM mytable WHERE id = 54');
$stmt.execute();
... // HOW TO CHECK HERE?
$stmt = $db->prepare('SELECT * FROM mytable WHERE id = 54');
$stmt.execute();
... // HOW TO CHECK HERE?
It's so simple, you're almost there already.
$stmt = $db->prepare('SELECT * FROM mytable WHERE id = 54');
$stmt.execute();
$result = $stmt->fetchAll(); // Even fetch() will do
if(count($result)>0)
{
// at least 1 row
}
And if you just want Yes/No answer then you should also add a LIMIT 1 to your query so mysql doesn't waste trying to look for more rows.

Mysql update query, what if value didn't change? how do I check for that?

When executing UPDATE statement, if value is same as new value than rowCount doesn't change. But for purposes of my application this is also a success. So how do I check for successful update no matter if value changed or not?
$stmt = $conn->prepare('UPDATE users SET name = :name WHERE id = :id');
$result = $stmt->rowCount(); // 1
if ($result == 1) {echo "success!";}
You're not executing the query, merely preparing it. So rowCount() will report an invalid number of rows (the one referring to the last executed query), since no rows were affected yet, and the system doesn't know beforehand how many will be, once you execute the prepared statement with specific param values.
You should check for success upon executing the statement. The execute() method will return true if it succeeds and false otherwise. So if execution success is the only thing you need, then you should do it along the lines of:
$stmt = $conn->prepare('UPDATE users SET name = :name WHERE id = :id');
$result = $stmt->execute($params); // <-- execute first!
if ($result) {echo "success!";}
I agree with Legionar. But instead of count I used to add a column that contains the last update time. So that I can use that to get the entries that got updated after a specific time. In this way I able to reduce the number of entries send to client. The final decision is based on your requirement.
$stmt = $conn->prepare('UPDATE users SET name = :name, updateTime = currentTime WHERE id = :id');
$result = $stmt->rowCount(); // 1
if ($result == 1) {echo "success!";}
I think this cant be done normally, but you can use another column for help.
Add column counter to your users table. And then just increase this value on each update.
$stmt = $conn->prepare('UPDATE users SET name = :name, counter = counter + 1 WHERE id = :id');
$result = $stmt->rowCount(); // 1
if ($result == 1) {echo "success!";}
So now, doesnt matter, if value name will change or not, counter will change each time, so it will return each time 1 if successed.
Or also as Damodaran answered, instead of counter you can use current datetime when doing update.

Add up all rows where value is equal to ID

I've been looking up around for a couple tutorials of this and I've seemed out of luck. Basically, I have a database containing a winner's user ID (corresponding to the winners user ID) and a loser's ID. I am trying to create a members profile where it counts up all the rows the member has won. Here is what I have came up with:
$web = mysqli_query("select SUM(matches) WHERE WinnerUID='".$req_user_info['id']."'");
$web_sum=mysqli_fetch_assoc($web);
echo $web_sum;
Unfortunately, it doesn't display any number. Can anyone help?
I think you're looking for COUNT() not SUM(). And you didn't include a table name. Also remember that mysqli_fetch_assoc() returns the row as an array, it doesn't return the first column's value. Also, mysqli_query() requires the connection as the first argument.
$web = mysqli_query($conn, "select COUNT(*) as total FROM matches WHERE WinnerUID='".(int)$req_user_info['id']."'");
$row = mysqli_fetch_assoc($web);
echo $row['total'];
Don't concatenate variables into your SQL. Use a Prepared Statement with bound parameters. I have casted your ID as an (int) in the above code, which is a quick fix but you should switch to a Prepared Statement.
Prepared Statement example (object oriented interface instead of procedural):
if ($stmt = $conn->prepare("select COUNT(*) from matches WHERE WinnerUID = ?")) {
$stmt->bind_param("i", $req_user_info['id']);
$stmt->execute();
$stmt->bind_result($web_sum);
$stmt->fetch();
echo $web_sum;
$stmt->close();
}

Categories