Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prepared Statement with ON DUPLICATE KEY

Tags:

php

mysql

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();
}
    }
like image 684
ButterDog Avatar asked Mar 27 '14 21:03

ButterDog


People also ask

What is on duplicate key?

The Insert on Duplicate Key Update statement is the extension of the INSERT statement in MySQL. When we specify the ON DUPLICATE KEY UPDATE clause in a SQL statement and a row would cause duplicate error value in a UNIQUE or PRIMARY KEY index column, then updation of the existing row occurs.

How does on duplicate key update work?

ON DUPLICATE KEY UPDATE is a MariaDB/MySQL extension to the INSERT statement that, if it finds a duplicate unique or primary key, will instead perform an UPDATE. The row/s affected value is reported as 1 if a row is inserted, and 2 if a row is updated, unless the API's CLIENT_FOUND_ROWS flag is set.

What are prepared statements IN SQL?

A prepared statement is a feature used to execute the same (or similar) SQL statements repeatedly with high efficiency. Prepared statements basically work like this: Prepare: An SQL statement template is created and sent to the database. Certain values are left unspecified, called parameters (labeled "?").

What are prepared statements IN MySQL?

A prepared statement in MySQL represents a precompiled statement. A statement is compiled and stored in a prepared statement and you can later execute this multiple times. Instead of values we pass place holders to this statement. If you want to execute several identical queries (that differ by values only).


1 Answers

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);
like image 96
Bill Karwin Avatar answered Sep 28 '22 18:09

Bill Karwin