Prepared Statement with ON DUPLICATE KEY - php

I think this one should be pretty easy but I am having trouble getting it right. I have searched a bit but being new to prepared statements I can't quite figure out the syntax from looking at other examples I have found here and elsewhere. Anyhow here is my code.
if($stmt = $mysqli -> prepare("INSERT INTO user_info (city, state, website, public_contact, user, zipcode, pic, emailme) VALUES (?, ?, ?, ?, ?, ?, ?,?)
ON DUPLICATE KEY UPDATE (city, state, website, public_contact, user, zipcode, pic, emailme) VALUES (?, ?, ?, ?, ?, ?, ?,?)")) {
$stmt -> bind_param("sssssssi",$city, $state, $website, $public_contact, $user, $zipcode, $pic, $emailme);
$stmt -> execute();
$stmt -> bind_result($result);
$stmt -> close();
}
user is the unique. This IMO is just a syntax problem so could somebody help me out with the correct syntax? Much appreciated.
ETA: just to help trouble shooting this does work as intended when I remove the ON DUPLICATE KEY UPDATE part but obviously, it only allows the one record per user and will not update
UPDATE: was never able to find a working syntax to use the ON DUPLICATE KEY UPDATE so what I did instead (admittedly probably not the most efficient way) was check the table before hand for the user. If the user exist I run and UPDATE, if not I run a INSERT. Below is my working code. Hope this helps somebody who gets stuck in my situation.
$sql = "SELECT * FROM user_info WHERE user='$user'";
if ($result=mysqli_query($mysqli,$sql))
{
/* Return the number of rows in result set */
$rows=mysqli_num_rows($result);
/* Free result set */
mysqli_free_result($result);
}
if($rows == 0) {
if($stmt = $mysqli -> prepare("INSERT INTO user_info (city, state, website, public_contact, user, zipcode, pic, emailme) VALUES (?, ?, ?, ?, ?, ?, ?,?) ")) {
$stmt -> bind_param("sssssssi",$city, $state, $website, $public_contact, $user, $zipcode, $pic, $emailme);
$stmt -> execute();
$stmt -> bind_result($result);
$stmt -> close();
}
} else {
if($stmt = $mysqli -> prepare("UPDATE user_info SET city=?, state=?, website=?, public_contact=?, zipcode=?, pic=?, emailme=? WHERE user='$user'")) {
$stmt -> bind_param("ssssssi",$city, $state, $website, $public_contact, $zipcode, $pic, $emailme);
$stmt -> execute();
$stmt -> bind_result($result);
$stmt -> close();
}
}

The easiest way to use INSERT...ON DUPLICATE KEY UPDATE is to use the VALUES clause in the following way, so you don't need to repeat the parameters in the UPDATE clause. They just use the same values for each column that you passed in the VALUES clause:
if($stmt = $mysqli -> prepare("
INSERT INTO user_info (city, state, website, public_contact,
user, zipcode, pic, emailme)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
city = VALUES(city),
state = VALUES(state),
website = VALUES(website),
public_contact = VALUES(public_contact),
user = VALUES(user),
zipcode = VALUES(zipcode),
pic = VALUES(pic),
emailme = VALUES(emailme)") {
$stmt -> bind_param("sssssssi",$city, $state, $website, $public_contact,
$user, $zipcode, $pic, $emailme);
$stmt -> execute();
$stmt -> close();
}
The IODKU syntax requires that you set each column individually. You can't list them all in one clause like you were trying to do.
You should always report any errors from any call to prepare() or execute(). Or you can make mysqli throw exceptions:
$mysqli -> report_mode = MYSQLI_REPORT_STRICT;
Also, you don't need to bind_result(), since there is no result set from INSERT:
// NO: $stmt -> bind_result($result);

I'd strongly suggest having a look at something like Doctrine DBAL (not ORM) - it allows you to heave key => value pairs and makes these types of operations easier to wield when there's so many values.
You can then do something like:
try {
$conn->insert(
'db.`table`',
[
'city' => $city,
'state' => $state
]);
} catch (Exception $e) {
if( $e->getCode() !== '23000' ) {
throw $e;
}
$conn->update(
'db.`table`',
[
'city' => $city,
'state' => $state
],
[
'user' => $user
]);
}

Related

How to run multiple INSERT queries in a transaction and use insert id?

I need to insert data into 3 tables and need to get the id of last inserted query into shopper table. I know this is doable by running
$conn -> insert_id;
in a single query but in my case I need to create a transaction with rollback in case of any failure. something like
$conn = new mysqli(DBHOST, DBUSER, DBPASS, DBNAME);
$stmt1 = $conn->prepare("INSERT INTO shopper (usersID, parentJob, phoneNumber,address) VALUES (?, ?, ?, ?)");
$stmt1->bind_param("ssss", $userId, $parentJob, $phoneB, $addressB);
$stmt2 = $conn->prepare("INSERT INTO shipment (shipmentID, usersID,..) VALUES (?, ?, ?, ?)");
$stmt2->bind_param("ssss", $userId, ...);
$stmt3 = $conn->prepare("INSERT INTO address (addressID, usersID, ...) VALUES (?, ?, ?, ?)");
$stmt3->bind_param("ss", $userId, ...);
$conn->begin_transaction();
if ($stmt1->execute() && $stmt2->execute() && $stmt3->execute()) {
$conn->commit();
} else {
$conn->rollback();
}
$conn->close();
As you can see I am trying to pass last inserted usersID as Foreign Key into shipment and address tables. so how can I do this when committing all of them together like
if ($stmt1->execute() && $stmt2->execute() && $stmt3->execute()) {
$conn->commit();
} else {
$conn->rollback();
}
Exceptions offer enormous help with transactions. Hence configure mysqli to throw exceptions. Not only for transactions but because it's the only proper way to report errors in general.
With exceptions your code will be plain and simple
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$conn = new mysqli(DBHOST, DBUSER, DBPASS, DBNAME);
$conn->set_charset('utf8mb4');
$conn->begin_transaction();
$stmt = $conn->prepare("INSERT INTO shopper (usersID, parentJob, phoneNumber,address) VALUES (null, ?, ?, ?)");
$stmt->bind_param("sss", $parentJob, $phoneB, $addressB);
$stmt->execute();
$userId = $conn->insert_id;
$stmt = $conn->prepare("INSERT INTO shipment (shipmentID, usersID,..) VALUES (?, ?, ?, ?)");
$stmt->bind_param("ssss", $userId, ...);
$stmt->execute();
$stmt = $conn->prepare("INSERT INTO address (addressID, usersID, ...) VALUES (?, ?, ?, ?)");
$stmt->bind_param("ss", $userId, ...);
$stmt->execute();
$conn->commit();
in case of error an exception will be thrown and a transaction will be rolled back automatically.

Data Not inserted in Database php, mysql

Can't insert data into DB . When i remove user_id then data is inserted. Please check below my code and help me.
function adddata($data) {
global $db;
if (is_array($data)) {
$stmt = $db->prepare('INSERT INTO `pay` (id, payment, status, itemid, time, user_id) VALUES(?, ?, ?, ?, ?, ?');
$userid = 2;
$stmt->bind_param(
'sdssss',
$data['txn_id'],
$data['payment_amount'],
$data['payment_status'],
$data['item_number'],
date('Y-m-d H:i:s'),
$userid
);
$stmt->execute();
$stmt->close();
return $db->insert_id;
}
return false;
}
It's subtle, but your SQL string is missing a closing bracket:
$stmt = $db->prepare('INSERT INTO `pay` (...) VALUES (?, ?, ?, ?, ?, ?)');
Where the VALUES list was not properly closed.
A lot of problems can be detected and resolved by enabling exceptions in mysqli so mistakes aren't easily ignored. This should show up as a SQL error in your logs.

INSERT no Result Value

I'm trying to insert some value into my database, but I got no result, but the code got no error, and the result label said it is succeed. My database connection working. How to check the issue here, I confused.
My Code Here
// insert new data to menu table
$sql_query = "INSERT INTO tbl_jadwal (Nama_Lokasi, Category_ID, Longitude, Latitude, Phone, Email, Menu_image, Description)
VALUES(?, ?, ?, ?, ?, ?, ?, ?)";
$upload_image = 'upload/images/' . $menu_image;
$stmt = $connect->stmt_init();
if ($stmt->prepare($sql_query))
{
// Bind your variables to replace the ?s
$stmt->bind_param('sssssss',
$nama_lokasi,
$category_ID,
$longitude,
$latitude,
$phone,
$email,
$upload_image,
$description
);
// Execute query
$stmt->execute();
// store result
$result = $stmt->store_result();
$stmt->close();
}
This should do, you were missing one s in the param string
$stmt->bind_param('ssssssss',
$nama_lokasi,
$category_ID,
$longitude,
$latitude,
$phone,
$email,
$upload_image,
$description
And you have way too much code. Only a very little part of it is relevant

If statement on PHP (inserting data)

I have to register a costumer and/or a manager into the database. I just have one form for the information, the only difference is the ID number (valid for managers). The costumers should leave this form blank. I was trying to save the data just using an if statement (If it is blank, save the information in costumer table. If it is not, save in manager). I have not seen this on my classes so I am not sure if it is possible.
Is it possible to use an if statement to insert data? What I mean is, I have two different tables but just one form (one of the forms will make the difference for which table the data will be saved.
The data in the manager table is ok, but when I try to insert data into costumer it is not working. I am not sure that I can use this.
if($_SESSION['id'] != null){
$sql = "INSERT INTO manager (id,magname,maglname,maguser,magpass) VALUES (?, ?, ?, ?, ?);";
$sth = $DBH->prepare($sql);
$sth->bindParam(1, $_SESSION['id'], PDO::PARAM_INT);
$sth->bindParam(2, $_SESSION['firstname'], PDO::PARAM_INT);
$sth->bindParam(3, $_SESSION['secondname'], PDO::PARAM_INT);
$sth->bindParam(4, $_SESSION['username'], PDO::PARAM_INT);
$sth->bindParam(5, $_SESSION['password'], PDO::PARAM_INT);
$sth->execute();
}
if(empty($_SESSION['id']){
$sql = "INSERT INTO costumer (fisrtname,lastname,username,password) VALUES (?, ?, ?, ?);";
$sth = $DBH->prepare($sql);
$sth->bindParam(1, $_SESSION['firstname'], PDO::PARAM_INT);
$sth->bindParam(2, $_SESSION['lastname'], PDO::PARAM_INT);
$sth->bindParam(3, $_SESSION['username'], PDO::PARAM_INT);
$sth->bindParam(4, $_SESSION['password'], PDO::PARAM_INT);
$sth->execute();
}
you can do it directly through following code
if(isset($_SESSION['id']))
$sql = "INSERT INTO `manager`..."
else
$sql = "INSERT INTO `customer`..."
or something like this
if(!empty($_SESSION['id']))
{ $sql = "INSERT INTO `manager`..."}
else
{ $sql = "INSERT INTO `customer`..."}

PHP mysqli Insert not working, but not giving any errors

As the title says Im trying to do a simple insert, but nothing actually is inserted into the table. I try to print out errors, but nothing is reported.
My users table has many more fields than these 4, but they should all default.
$query = 'INSERT INTO users (username, password, level, name) VALUES (?, ?, ?, ?)';
if($stmt = $db -> prepare($query))
{
$stmt -> bind_param('ssis', $username, $password, $newlevel, $realname);
$stmt -> execute();
$stmt -> close();
echo 'Any Errors: '.$db->error.PHP_EOL;
}
There are no errors given, but when I go to look at the table in phpmyadmin there is not a new row added. I know for sure that the types are correct (strings and integers). Is there something really wrong here or does it have something to do with the fact that I'm ignoring other columns. I have about 8 columns in the user table.
If you have turned auto commit off, you will have to explicitly call the commit method after you execute the query.
$stmt->execute();
$db->commit();
$stmt->close();
You have to check for errors at each stage of the process: When you connect, when you prepare the statement, when you bind, when you execute, and when you close. In your code, assuming the $db handle was properly created, the error check happens after the ->close() call, which should succeed, so there won't be any error at that point.
Something along these lines will show where things blew up:
$query = 'INSERT INTO users (username, password, level, name) VALUES (?, ?, ?, ?)';
$stmt = $db->prepare($query);
echo 'prepare error: ', $db->error, PHP_EOL;
$stmt->execute();
echo 'execute error: ', $db->error
etc....
Check if the string "Any Errors" is being printed. If not, then the statement:
if ($stmt = $db->prepare($query))
is returning false. You should move echo 'Any Errors: '.$db->error.PHP_EOL; outside of the conditional block.
Do u initialize the values of $username, $password, $newlevel, $realname before the
$stmt -> execute(); statement. Otherwise you have to initialize and try
$query = 'INSERT INTO users (username, password, level, name) VALUES (?, ?, ?, ?)';
if($stmt = $db -> prepare($query)){
$stmt -> bind_param('ssis', $username, $password, $newlevel, $realname);
$username='testname';$password='testpwd';$level=5;$realname='testrealname';
$stmt -> execute(); echo "inserted SuccessFully"; $stmt -> close(); }
else { printf("Prepared Statement Error: %s\n", $mysqli->error);}
try this code. If the query is executed successfully it show the "Inserted Successfully" otherwise it shows the error.

Categories