I am trying too input a new number into a databasee only if it does not already exist, in order to do this, I am doing the following
if (isset($_POST['Number'])) {
$number = ($_POST['Number']);
$NCheck = "SELECT COUNT(*) FROM `DS_Numbers` WHERE `Number` = '$number' ";
$stmt = $dbCon->prepare($sql);//* prepared statement for result which populates table
$stmt->execute();
$result = $stmt->fetchColumn(0);
if($result > 0){ // if there is a value then block
$ENumber = "This Number already exists";
$errors[] = 'error';
} else {
echo "number done";// echo statement to see that it has reached this
$number1 = ($_POST['Number']);
}
} else {
$errors[] = 'error';
$ENumber = "Please enter only digits from 0-9";
}
What is currently happening is that my PDO statement is not returning, so my result value is always 0, but none of my research has shown that I have an issue with it
any suggestions on where I am going wrong?
I am getting Number from an HTML form on the page, no issues on that side.
First thing to notice is that you are writing your query in a variable called $NCheck, not $sql.
So this line
$stmt = $dbCon->prepare($sql);
should be
$stmt = $dbCon->prepare($NCheck);
Also please note that one of the main advantages in using PDO is to use bound parameters, but you are not doing this and you are in fact exposed to SQL injection since you are just adding that value you get in POST in the query.
If the number must be unique in the table then you should probably add a UNIQUE constraint to the column. You can then just insert the number and if it was not unique the database will return a 'duplicate key' error.
If you use the 'check-first-insert-later' method you are open to race conditions; if two processes try to insert the same number at the same time they will both run the select at the same time and they will both get zero and try to insert, which without a unique constraint will work for both.
Related
I have a function which inserts multiple rows using the MySqli library with prepared statements. The inserts works great, the problem is the build in $stmt->affected_rows method always returns the number of affected rows as 1.
Now to move around the affected row issue I created a counter which counts each executed statement. This solution is accurate. But I enjoy using built in methods and functions, so why is the $stmt->affected_rows always returning one, even though I inserted multiple rows? Is my code defective in some way or form? Maybe there is a pure Sql solution.
Here is my code:
try {
$query = "INSERT INTO dryenrolltb(enroll_id,id_entity,bin_type,tara_weight,dtetime_created,enrollprint_status) VALUES(?,?,?,?,?,?)";
$stmt = $db->prepare($query);
$stmt->bind_param('iiidsi', $enroll,$ent,$bin,$tara,$dte_create,$enr_status);
$result['rows']['rowerrors'] = array();
$result['rows']['rowsaffected'] = [];
$cnt = 0;
foreach ($arr as $value) {
$enroll = $value['enroll'];
$ent = $value['entid'];
$bin = $value['bin_t'];
$tara = $value['tara'];
$dte_create = $value['dtecreat'];
$enr_status = $value['enr_status'];
if($stmt->execute()) {
$cnt++;
} else {
array_push($result['rows']['rowerrors'],$value['enroll']);
}
}
if ($stmt->affected_rows > 0) {
echo "Affectionately yours";
array_push($result['rows']['rowsaffected'], $stmt->affected_rows);
array_push($result['rows']['rowsaffected'], $cnt);
return $result;
} else {
return false;
}
} catch (Exception $e) {
echo "Danger exception caught";
return false;
}
Can someone please give me a clue on why the $stmt->affected_rows always returns one on multiple inserts?
No. It seems like MySQLi statement class has no way of storing a running total of affected rows. After I thought about it, it makes total sense. Let me explain.
Every time you execute the statement it will affect a given number of rows. In your case you have a simple INSERT statement, which will add records one by one. Therefore, each time you call execute() the affected_rows value is one.
The query could be something different. For example INSERT INTO ... SELECT or UPDATE could affect multiple rows.
You could also have INSERT INTO ... ON DUPLICATE KEY UPDATE. If the key exists in DB, then you are not inserting anything. If the values are the same, you are not even updating anything. The affected rows, could be 0 or more.
The reason why it would be unwise for the statement to keep a running total of the affected rows is that each execution affects certain rows, irrespective of the previous executions. They could be even the same records. Consider the following example:
$stmt = $mysqli->prepare('UPDATE users SET username=? WHERE id=?');
$stmt->bind_param('si', $name, $id);
$id = 102;
$name = 'Affected rows 1';
$stmt->execute();
echo $stmt->affected_rows; // 1
$name = 'Affected rows 2';
$stmt->execute();
echo $stmt->affected_rows; // 1
Both update statements updated the same row. If mysqli kept a running total it would report 2 affected rows, but in reality only 1 row was changed. If the number was summed, you would be losing information.
So, for your simple scenario, it is fine to keep the total on your own, for example by summing up the $stmt->affected_rows after each execution. Anything more than that, it would probably not make much sense.
I want my below PDO select to work with the bottom two IF statements?
The first IF I just want to make sure there is no error.
The second IF I want to check how many rows it returns. I know that this number of rows == 0 will not work.
Is there a way to do that?
try {
$conn = new PDO('mysql:host=localhost;dbname=zs', 'zs', 'rlkj08sfSsdf');
$conn ->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo $e->getMessage();
die();
}
$stmt = $conn->prepare("SELECT * FROM zip WHERE zip_code =:zip1");
$stmt->bindValue(':zip1', $_POST[zipcode], PDO::PARAM_INT);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
if($rows = "") {
echo "<p><strong>There was a database error attempting to retrieve your ZIP Code.</strong></p>\n";
}
if(number of rows == 0) {
echo "<p><strong>No database match for provided ZIP Code.</strong> Please enter a new ZIP Code.</p>\n";
}
You're interested only in whether there are records containing a particular value. It makes no sense to select everything and count the records in PHP. It's a waste of resources. Imagine what happens if there's a million records.
Solution you're after is to simply ask your database about the COUNT of rows containing a particular value. Your code should be quite simple:
$stmt = $conn->prepare("SELECT COUNT(*) AS num_rows FROM zip WHERE zip_code = :zip");
$stmt->bindValue(':zip', $_POST['zipcode'], PDO::PARAM_INT);
$stmt->execute();
$count = (int)$stmt->fetchColumn();
if($count)
{
echo "Success";
}
else
{
echo "Bummer";
}
Notes:
if successful, the above query will always return 1 row with 1 column, named num_rows which will be 0 for no matching records or an integer larger than 0 if there are records. If you use MySQL native driver with PHP, PHP will correctly represent this value as integer internally. I deliberately put typecasting in, you can remove it (the (int) part) if you have MySQL ND.
if something goes wrong during query execution, an exception will be thrown. The snippet doesn't cover that. You correctly set PDO in exception mode, and along with using bindValue instead of bindParam, this implies you did your research right and you're using PDO correctly which means that error handling should be implemented easily by you in this particular case.
I have the following code in my CRUD class
//function to execute prepared statement query
//$sql = select , insert, update and or delete query => insert into table(col,col,col,...col) values(?,?,?,...?);
//$dataTypes = "ssidb", it could be any char in s=>string, i=>integer, d=>double and b=>blob data
//$param = $val1,$val2,$val3,....$valn, this is an option coma separated values to bind with query
public function dbQuery($sql,$dataTypes="",$param=""){
try{
$this->connect();
$stmt = $this->con->stmt_init();
$stmt = $this->con->prepare($sql);
$stmt->bind_param($dataTypes, $param);
if($stmt->execute() === true){
return true;
}
else{
return false;
}
}catch(Exception $e){
$this->errorMsg = $e->getMessage();
}
$this->closeConnection();
}
I am calling this method from my index page like this:
if(isset($_POST['btnSearch'])){
//search for some record with primary key
$sno = intval($_POST['sno']);
$sql = "SELECT sno,std_name,email,roll_number FROM table_1 WHERE sno = ?";
$dTypes = "i";
$params = $sno;
if($db->dbQuery($sql,$dTypes,$params)){
echo('Record exists');
}
else{
echo('Record did not found'.$db->errorMsg);
}
}//search for record
//inserting values to table_1 table
This always return true either there is any record exists or not?
Whats going wrong with this code?
There are many flaws in your code, and it will never work as intended, even after fixing this particular problem.
Before starting with a class, you need to practice heavily with raw API functions, and learn how to use them by heart. Otherwise your class will be just a straw house that will crumble from a softest touch.
Now to your problem.
To solve it, you need to understand one very important mathematical conception, that reads "empty result is not an error". 10 - 5 - 5 = 0 doesn't mean there is an error in your calculations! It merely means that the result is zero.
Exacly the same is here. When a database returns no rows, it doesn't mean there is an error. It just meams that there is zero (no) data to return.
The opposite is true as well: if there is no error, it doesn't mean that there are rows found.
To see whether any row were returned or not, you need to fetch this very row.
Therefore, instead of checking execute() result, just fetch your row into a variable and then check whether it contains anything.
Would someone please me with the code below, I am inexperienced in this area and my class in SQL was "A long time ago in a galaxy far, far away..." I know the connection string works because I have used it in other functions with this app. I have even used the code below for retrieving *rows from another table in another function, for the most part, except that I didn't use the WHERE clause.
First, I am able to store IP addresses in the table using a function and it is working well. Now I want to check to see if a given one exist in this table. Partial code is given below.
What seems to always return is 0 rows. I have put in test data into the table and hard-coded the $ipA, but I still get 0 rows return. Please help if possible and thanks for the effort spent.
function checkDB($ipA) {
require_once('connection.inc.php');
$resultAns = "";
//create db connection
$conn = dbConnect();
//init prepared stmt
$stmt = $conn->stmt_init();
//Set sql query for ipAddress search
//prepare the SQL query
$sql = 'SELECT * FROM ipAddress WHERE ipA = ?';
//submit the query and capture the result
if ($stmt->prepare($sql)) {
$stmt->bind_param('s', $ipA);
$stmt = $stmt->execute();
//if qry triggers error affeted_rows value becomes -1 &
//php treats -1 as true; so test for greater than 0
$numRows = $stmt->num_rows; //not to sure about the syntax here
}
// I want to know if the query brought back something or not, I don't what
// to know exactly what, only that it found a match or did not find a match.
// echos are for testing purposes to show me where I am landing.
if ($numRows == 0) {
echo '<script type="text/javascript">window.alert("numRows = 0")</script>';
$resultAns = 0;
} elseif ($numRows == 1) {
echo '<script type="text/javascript">window.alert("numRows = 1")</script>';
$resultAns = 1;
}
return $resultAns;
}
Try storing the result after you execute
$stmt->store_result();
Use $stmt->store_result(); before you call num_rows.
While the others caught one reason that $numRows would never receive a value other than 0, the other piece of code that was flawed and caused problems was...
$stmt = $stmt->execute(); which should have been just $stmt->execute();
I must have mixed it up with other code I wrote from somewhere else.
Thanks for the answers, they did help.
considering the following for my question:
$success = false;
$err_msg = '';
$sql = 'UPDATE task SET title = ? WHERE task_id = ?';
$conn = connect('w'); // create database connection: r= read, w= write
$stmt = $conn->stmt_init(); // initialize a prepared statement
$stmt->prepare($sql);
$stmt->bind_param('si', $_POST['title'], $_POST['id']);
$stmt->execute();
If i want to check if an insert or a deletion was succesfull, i could easily check for the affected_rows, like this:
if ($stmt->affected_rows > 0) {
$success = true;
} else {
$err_msg = $stmt->error;
}
If $stmt->affected_rows equals -1, it means that $stmt->execute() executed correctly but did not insert the record or did not delete the record successfully.
But, what about an update ? What is the correct way to deal with an update?
The way i do it is by checking for the return value :
$isRecordUpdated = $stmt->execute();
if (!$isRecordUpdated) {
// execute failed, therefore NO record updated!
} else {
//execute success, record updated!
}
Is that the correct way you guys are doing it?
It seems to me that there are really two equivalent and correct ways of doing this: either by checking the return value of execute as you do, or by checking the affected_rows value. -1 means the query errored out; 0 means that it did not affect (delete or update) any rows because there were none matching the query.
Since it seems there is no "better" way, you should pick what would be most convenient for your code. If e.g. using one approach over the other means that you can then share code among all types of queries, you might want to pick that one.
Why not store the value from mysql-affected-rows into a property of that object when you call execute()?
http://php.net/manual/en/function.mysql-affected-rows.php