SQL query fails but the transaction rollback doesn't work - php

The actual column names are account and passwd so the second query will failed, but the first query still inserted into database.
$sql1 = "INSERT INTO users (account, passwd) VALUES ('account+1', 'password+1')";
$sql2 = "INSERT INTO users (account, password) VALUES ('account+2', 'password+2')";
try {
$db->beginTransaction();
$db->query($sql1);
$db->query($sql2);
$db->commit();
} catch (Exception $e) {
$db->rollback();
die($e->getMessage());
}
The transaction started successfully with no errors, the problem is that it doesn't rollback, always rows are inserted regardless of failing queries.
MySQL version 5.5.25 and table type is InnoDB.

Did you turn on exceptions? By default pdo doesn't throw them and silently ignores errors.
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$sql1 = "INSERT INTO user (account, passwd) VALUES ('account+1', 'password+1')";
$sql2 = "INSERT INTO users (account, password) VALUES ('account+2', 'password+2')";
try {
$db->beginTransaction();
$db->query($sql1);
$db->query($sql2);
$db->commit();
} catch (Exception $e) {
$db->rollback();
die($e->getMessage());
}
$mysql refence is wrong, you have to use, $db->rollback();

Related

How to handle multiple insert requests if one fails?

My registration form inserts a row into two tables. How can I roll back all transactions if either doesn't complete?
Here is my snippet so far:
try {
// insert row for account
$stmt = $dbh->prepare("INSERT INTO accounts (account_num) VALUES (:account)");
$params = [
":account_num" => $account_num
]
$stmt=>execute($params);
// insert row for user
$stmt = $dbh->prepare("INSERT INTO users (email, account_num) VALUES (:email, :account_num)");
$params = [
":email" => $email,
":account_num" -> $account_num;
]
$stmt->execute($params);
} catch (PDOExeception $e) {
echo "error: could not create your account and profile";
}
You can do something inside a try catch like this-
$this->pdo->beginTransaction(); //prepare database for rollback changes if needed
try{
$stmt1 = $this->pdo->prepare(...); //prepare your first statement for execution
$stmt1->execute(...); //execute first statement
$stmt2 = $this->pdo->prepare(...); //prepare your second statement for execution
$stmt2->execute(...); //execute second statement
$this->pdo->commit(); //confirms that all statements are executed and no errors occured
} catch (\PDOException $e) {
$this->pdo->rollBack(); //if there is any error, the exception handler will rollback the operation
}
Please be noted that if you have an auto incremented primary key, then you may miss two auto-incremented values here because this rollback operation first creates/ inserts the data. If any error occurred then simply deletes them. So the auto incremented primary keys might be missing.

Is there any way to fix this code to avoid error : Duplicate entry '1' for key 'PRIMARY' each time

if(isset($_POST['submit']))
{
if ($firstName&&$lastName&&$email!=""){
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql= "UPDATE abonnenter SET id = (id+1)";
$conn->exec($sql);
$sql = "INSERT INTO abonnenter (id,firstname,lastname,mail)
VALUES (id,'$firstName','$lastName', '$email')";
// use exec() because no results are returned
$conn->exec($sql);
echo "Du blir nå sendt en mail når bloggen oppdateres";
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
}
}
is the code. It Works when I have id get -1 instead of +1, but having a primary key id be listed as negative numbers seem very bad when it comes to keeping the code semantic
Made the id auto increment. and update your sql query like
$sql = "INSERT INTO abonnenter (firstname,lastname,mail)
VALUES ('$firstName','$lastName', '$email')";
Also your code is open to sql injection use pdo or prepared statement

PHP PDO can't run query INSERT INTO with SELECT

I can't run INSERT INTO and SELECT queries in one statement.
Have problem with this php code:
$db = connect_db_marketlist();
if($db != null) {
$sql = "INSERT INTO items (user_id, market_table_id, price, info )"
." VALUES ('$id', (SELECT table_id FROM markets WHERE city='$city' AND market='$market'), $price, '$info')";
echo $sql; // !!! DEBUG !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
try {
$db->query($sql);
echo "OKAY: ".$db->lastInsertId();
} catch (Exception $e) {
echo "ERROR: ".$e->getMessage();
}
}
And I got error:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column
'market_table_id' cannot be null
Error says SELECT query returns null but when I run $sql statement directly in phpmyadmin, it is working.
This is echo $sql output:
INSERT INTO items (user_id, market_table_id, price, info ) VALUES
('12345678', (SELECT table_id FROM markets WHERE city='ANKARA' AND market='MİGROS'), 22.33, 'TEST_INFO_MİGROS')
What's wrong with me? Maybe it's my db connection:
function connect_db_marketlist() {
$servername = "localhost";
$username = "marketuserdb";
$password = "pass1234";
$conn = null;
try {
$conn = new PDO("mysql:host=$servername;dbname=marketlist", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e)
{
echo "Connection failed: " . $e->getMessage();
}
return $conn;
}
Is it possible to run "INSERT INTO...SELECT..." query with PDO? If yes how, if no why?
P.S: It's working when I enter any integer instead of (SELECT....) query. So no problem with DB connection.
You should set connections charset to proper one in DSN like
"mysql:host=$servername;dbname=marketlist;charset=utf8mb4"
(This is for utf-8, you should set it for your tables encoding)
the var should be inside the select
This way
"INSERT INTO items (user_id, market_table_id, price, info )"
." SELECT '$id', table_id , $price, '$info'
FROM markets WHERE city= '$city' AND market='$market' ;";

PDO's lastInsertId() Returns the Correct ID on One Line But Not Another Where I Need It for a $_SESSION['xxxxxx'] =?

Im working on a login script but am having trouble with lastInsertId();
Here's the code;
<?php
session_start();
db = new PDO("mysql:host=hostname;dbname=database name", user, password);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
$db->beginTransaction();
$db->query("INSERT INTO `subscribers`(`subscribers`.`first_name`, `subscribers`.`last_name`) VALUES ('Jane', 'Doe')");
$db->query("UPDATE `subscribers` SET `first_name`='John' WHERE `ID` =".$db->lastInsertId());
$db->commit();
$LastID = $db->lastInsertId();
$_SESSION['user_id'] = $LastID;
} catch (PDOException $e) {
$db->rollBack();
die($e->getMessage());
}
?>
My problem is that the UPDATE query performs properly (based off of WHERE ID =".$db->lastInsertId());) but when I try to use the function for setting the $_SESSION as seen in the code all I get back is 0.
If anyone wouldn't mind showing me what's askew I'd be most appreciative and I thank you in advance.
Why not just:
$db->beginTransaction();
$db->query("INSERT INTO `subscribers`(`subscribers`.`first_name`, `subscribers`.`last_name`) VALUES ('Jane', 'Doe')");
// Grab, save
$LastID = $db->lastInsertId();
// Query by last ID
$db->query("UPDATE `subscribers` SET `first_name`='John' WHERE `ID` =".$LastID);
$db->commit();
// Write last ID to session
$_SESSION['user_id'] = $LastID;
My guess is that the update destroys the lastInsertId of your insert.
Try storing the id in a variable for use later:
$db->query("INSERT INTO `subscribers`(`subscribers`.`first_name`, `subscribers`.`last_name`) VALUES ('Jane', 'Doe')");
$last_id=$db->lastInsertId();
$db->query("UPDATE `subscribers` SET `first_name`='John' WHERE `ID` =".$last_id);
$db->commit();
$_SESSION['user_id'] = $last_id

will mysqli->rollback(), rollback every query that has been previously committed?

I want to know if mysqli->rollback will rollback all the queries that have been committed before the rollback.
For example, in the code below, the first query will be committed, but the second query will fail because of misspelling 'username'. Does that mean that the query before the rollback will or will not get executed?
$mysqli->autocommit(FALSE);
$query = "INSERT INTO users (username, password) VALUES ('user123', '1apple')";
$query2 = "INSERT INTO users (**usernam**, password) VALUES ('user987', '2apple')";
if($resrouce = $mysqli->query($query)){
$mysqli->commit();
if($resource2 = $mysqli->query($query2)){
$mysqli->commit();
}else{
$mysqli->rollback();
}
}else{
$mysqli->rollback();
}
Once you commit the transaction , you can not rollback it , you can only rollback the statement which is not comited yet
modify line 8 and add a line in the end in your code:
$mysqli->autocommit(FALSE);
$query = "INSERT INTO users (username, password) VALUES ('user123', '1apple')";
$query2 = "INSERT INTO users (**usernam**, password) VALUES ('user987', '2apple')";
if($resrouce = $mysqli->query($query)){
//$mysqli->commit(); this not necesary
if($resource2 = $mysqli->query($query2)){
$mysqli->commit();
}else{
$mysqli->rollback();
}
}else{
$mysqli->rollback();
}
$mysqli->close();
Personally I find the PDO library better for database access than mysqli. You can check:
http://php.net/manual/en/pdo.begintransaction.php
which does exactly what you need... Hope that helps

Categories