thanks for your time.
Below I have two prepared statements, query & query2;
con is the connection var
The first query is running perfectly and updating the database.
The second query is not updating anything, although it is not giving any error.
When I look at the second query that is logged after a "successful" run, the inserted variable is looking like an empty string. i.e. RESTI=''
Why is this happening? Is my code in the right order for the second query to run?
$row = 1;
$con=mysqli_connect("connect info");
if (mysqli_connect_errno())
{
//echo "Failed to connect to MySQL Error 1: " . mysqli_connect_error();
//error reporting done here
}
else
{
$con->autocommit(false);
$query = $con->prepare("UPDATE table where `INDEX`=?");
$query2 = $con->prepare("UPDATE table2 where (SELECT column from table where`RESTI`=?)");
$query->bind_param('i', $row);
$query2->bind_param('i', $row);
if($query->execute() == false)
{
//Failed!
/ERROR HANDLING
}
else
{
//SUCCESS
}
if($query2->execute() == false)
{
//Failed!
/ERROR HANDLING
}
else
{
//Success
}
$con->commit();
$query->close();
$query->close();
}
mysqli_close($con);
Here is how your update statement should be:
"UPDATE table SET column=<new value to set> WHERE INDEX=?"
"UPDATE table2 SET <col to update>= (SELECT column from table where`RESTI`=?) WHERE condition
Make sure RESTI is an unique field and the subquery would only return scalar value
Related
I have a script which is containing some queries:
$id = $_GET['id'];
$value = $_GET['val'];
// database connection here
// inserting
$stm1 = $db_conn->prepare("INSERT into table1 (col) VALUES (?)");
$stm1->execute(array($value));
// updating
$stm2 = $db_conn->prepare("UPDATE table2 SET col = "a new row inserted" WHERE id = ?");
$stm2->execute(array($id));
As you see there is two statements (insert and update). All I'm trying to do is making sure both of them work or none of them.
I mean I want to implement a dependency between those two statements. If updating fails, then inserting shouldn't work and vice versa. How can I do that?
You could use sql transactions
http://www.sqlteam.com/article/introduction-to-transactions
You can use transactions and PDO has an api for this (http://php.net/manual/en/pdo.begintransaction.php),
$id = $_GET['id'];
$value = $_GET['val'];
// database connection here
try{
$db_conn->beginTransaction();
// inserting
$stm1 = $db_conn->prepare("INSERT into table1 (col) VALUES (?)");
$stm1->execute(array($value));
// updating
$stm2 = $db_conn->prepare("UPDATE table2 SET col = "a new row inserted" WHERE id = ?");
$stm2->execute(array($id));
$db_conn->commit();
}
catch(PDOException $e){
$db_conn->rollBack();
}
As others said, you could use 'transactions'.
Or
you could mannualy check whether the data is right in the database. Just 'select' what you have inserted.
The 'execute' function return 'true' on success or 'false' on failure. You can do something like:
$isDone=$stm1->execute(array($value));
if(!$isDone){
echo 'Operation fails, I will stop.';
return false;
}
I have the following two queries. Second query is dependent on first one.
$query1 = mysql_query("Insert into table_one set ---- ");
if($query1)
{
$query2 = mysql_query("delete from table_two where condition---");
if($query2)
{
$message = "both queries executed successfully";
}
else
{
$del = mysql_query("delete record inserted by $query1");
}
}
Can we execute these two queries in a single statement so that both queries depend on each other.If INSERT query fail, DELETE query also fail it's execution as well as if DELETE query fail INSERTION in query first fail.
Thanks
If I good understand what you need, simply use transactions.
Run this query before your insertion:
mysql_query('begin');
And then, if everything went fine, commit the transaction:
mysql_query('commit');
In case of any failures, you may rollback every change you made:
mysql_query('rollback');
Note that in case of MySQL, the MyISAM engine does not support rollback in transactions, so use InnoDB.
Read more about transactions here: https://dev.mysql.com/doc/refman/5.0/en/commit.html
Example with your code:
<?PHP
mysql_query('begin'); //start transaction
$query1 = mysql_query("Insert into table_one set ---- ");
if($query1)
{
$query2 = mysql_query("delete from table_two where condition---");
if($query2)
{
mysql_query('commit'); //both queries went fine, so let's save your changes and end the transaction
$message = "both queries executed successfully";
}
else
{
mysql_query('rollback'); //query2 failed, so let's rollback changes made by query1 and end the transaction
}
}
else
mysql_query('rollback'); //query1 failed, so let's end the transaction
If query2 fails it doesn't check query1.
$query1 = mysql_query("Insert into table_one set ---- ");
$query2 = mysql_query("delete from table_two where condition---");
if( $query2 && $query1)
{
$message = "both queries executed successfully";
}
else if(!$query2)
{
$del = mysql_query("delete record inserted by $query1");
}
You can use transaction, if any query fails then call rollback, otherwise commit
I found a best solution.
Extending idea of #Luki i wrote the following code and it give me too much satisfied answer. First use the following function.
function multi_statement()
{
global $conn;
$total_args = func_get_args();
$args = implode($total_args,";");
$args = "begin;".$args.";commit;";
$number = 0;
if($conn->multi_query($args))
{
do
{
if ($conn->more_results())
{
$number++;
}
}
while($conn->next_result());
}
if($number < (count($total_args)+1))
{
$conn->query('rollback');
echo "Sorry..!!! Error found in Query no:".$number;
}
else
{
echo "All queries executed successfully";
}
}
Then I called the function with number of statements, all these statements are dependent on each other. In-case there is error in any query, no one query occur any changes in database.
$statement1 = "INSERT INTO `pic_gall`.`admin` (`admin_id`, `username`, `password`) VALUES (NULL, 'as1', 'as1')";
$statement2 = "INSERT INTO `pic_gall`.`admin` (`admin_id`, `username`, `password`) VALUES (NULL, 'as2', 'as2')";
$statement3 = "INSERT INTO `pic_gall`.`admin` (`admin_id`, `username`, `password`) VALUES (NULL, 'as3', 'as3')";
$statement4 = "INSERT INTO `pic_gall`.`admin` (`admin_id`, `username`, `password`) VALUES (NULL, 'as4', 'as4')";
$statement5 = "DELETE from user where user_id = '12'";
multi_statement($statement1,$statement2,$statement3,$statement4,$statement5);
I'm kind of a stuck in searching for a solution.
I need to check if an input data $coupon from the form (after "post" action) equals data in the existing MySQL table called Serial, in the row $Coupon. If those two entries match i need the one in table "Serial" removed (DELETED From). In the other case I need to display an Error, maybe like echo "The coupon number you've entered is invalid".
Now i have the following code, but it doesnt do the check.
$query4="SELECT EXISTS(SELECT 1 FROM serial WHERE Coupon='$coupon')";
$result = mysql_query($query4);
if($result){
echo "Bravo!";
}
else{
"The coupon number you've entered is invalid";
exit;
}
// Delete data from mysql
$query2="DELETE FROM serial WHERE Coupon = '$coupon'";
$result = mysql_query($query2);
// if successfully insert data into database, displays message "Successful".
if($result){
echo "Some info";
}
else {
die(mysql_error());
}
Appreciate any ideas greatly!
You've created a race condition for yourself. The fact that the coupon exists when you run the SELECT statement does not mean that it will exist when you run the delete statement, especially if this is a web app, or multi-threaded/multi-process.
The DELETE statement deletes rows from tbl_name and returns a count of the number of deleted rows. This count can be obtained by calling the ROW_COUNT() function.
Run your DELETE unconditionally, then use the ROW_COUNT to see if it was there and got deleted or wasn't ever there.
First of all phase out mysql_* functionality or you have bigger problems than checking the result. Your code is vulnerable to SQL Injection. Use PDO or MySQLi instead.
Secondly, why do you need EXISTS in the first query at all?
Here is the solution in PDO:
$query = 'SELECT 1 FROM serial WHERE Coupon = :coupon';
$stmt = PDO->prepare($query);
$stmt->bindParam(':coupon', $coupon, DB::PARAM_STR);
$stmt->execute();
if ($stmt->rowCount() > 0) {
//query 2
$query2 = "DELETE FROM serial WHERE Coupon = :coupon";
$stmt2 = PDO->prepare($query2);
$stmt2->bindParam(':coupon', $coupon, DB::PARAM_STR);
if ($stmt2->execute()) {
echo 'Success';
} else {
echo 'Unable to Delete';
}
} else {
echo 'Selected Coupon Is Invalid';
}
OR MORE SIMPLY IN ONE QUERY:
$query = 'DELETE FROM serial WHERE coupon = :coupon';
$stmt = PDO->prepare($query);
$stmt->bindParam(':coupon', $coupon, DB::PARAM_STR);
if ($stmt->execute()) {
echo 'Success';
} else {
echo 'failure, invalid coupon';
}
You can actually just do SELECT 1 FROM serial...
Then:
$result = mysql_query($query4);
if (mysql_num_rows($result)) {
If it returns a row, you know it exists. You can also add LIMIT 1 to the query to make it faster.
By the way, your code is vulnerable to injection. You should use properly parameterized queries with PDO or mysqli.
Following up from mluebke's answer:
// Delete data from mysql
$query="DELETE FROM serial WHERE Coupon = '$coupon'";
mysql_query($query);
//Did we delete something?
if (mysql_affected_rows()) {
echo "Bravo!";
}
else{
"The coupon number you've entered is invalid";
exit;
}
http://www.php.net/manual/en/function.mysql-affected-rows.php
http://dev.mysql.com/doc/refman/5.5/en/information-functions.html#function_row-count
I'm creating a class and I have a function with which I want to insert some data into an table from some inputs. It works if I check the table but I keep getting the error "number of arguments in prepare doesn't match the no of arg in bind_result". Also I don't know if my method is correct ..
private function insertData($foldName,$foldClass,$foldLink) {
$sql = "INSERT INTO folders (folder_name,folder_class,folder_link) VALUES ('$foldName','$foldClass','$foldLink')";
if($stmt = $this->connect->prepare($sql)) {
$stmt->execute();
$stmt->bind_result($foldName,$foldClass,$foldLink);
$stmt->close();
$error = false;
$message['error'] = false;
$message['message'] = "Data Successfuly Inserted";
return json_encode($message);
}
else {
$error = true;
$message['error'] = true;
$message['message'] = "Data Failed To Insert";
return json_encode($message);
}
}
You don't need bind_result at all as you are inserting data and not selecting any.
But you should use the core features of your prepared statement. That is: safely passing the variables to the statement object instead of inserting their "raw" values into the SQL string:
$sql = "INSERT INTO folders (folder_name,folder_class,folder_link) VALUES (?,?,?)";
$stmt = $this->connect->prepare($sql);
$stmt->bind_param("sss", $foldName, $foldClass, $foldLink);
$stmt->execute();
(I have not tested it.)
Look at the first example on this manual page: http://php.net/manual/en/mysqli-stmt.bind-param.php
If you are emptying the table's data as a whole, use the truncate query:
TRUNCATE TABLE `table_name`
This would reset the auto_increment to 1, but if you don't want to empty the whole table you can alter it instead:
ALTER TABLE `table_name` auto_increment = 1
How to return a boolean if the record has been updated on the database?
Example:
try {
$SQL = "UPDATE addressbook SET valid = '0' WHERE id = :id";
$query = $this->db->prepare($SQL);
$query->bindValue(":id", $id);
$query->execute();
//How do I know if record has been updated?
} catch (PDOException $e) {
$j['success'] = 'false';
echo json_encode($j);
return;
}
You can use:
PDOStatement::rowCount() returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement executed by the corresponding PDOStatement object.
If the last SQL statement executed by the associated PDOStatement was a SELECT statement, some databases may return the number of rows returned by that statement. However, this behaviour is not guaranteed for all databases and should not be relied on for portable applications.
PDOStatement::rowCount (PHP 5 >= 5.1.0, PECL pdo >= 0.1.0)
To your particular case, returning a boolean:
return $query->rowCount() ? true : false;
If something went wrong but your code was updated in the database, that sounds like a really precarious state to be in. It's probably better to use a transaction and rollback on exception.
Something like (untested):
$this->db->beginTransaction();
try {
$SQL = "UPDATE addressbook SET valid = '0' WHERE id = :id";
$query = $this->db->prepare($SQL);
$query->bindValue(":id", $id);
$query->execute();
$this->db->commit();
return true;
//How do I know if record has been updated?
} catch (PDOException $e) {
$this->db->rollback();
return false;
}
Also, you probably don't want to mix your JSON in with this code, separate it out and have something outside your class deal with JSON.