INSERT ...ON DUPLICATE KEY UPDATE when key is not always known? - php

I'm trying to update a record if the key is known else I want to insert it and get the inserted id, currently I have:
if(isset($data['applicationId']))
{
//update
$sql="
UPDATE myTable SET data='jsonstring' WHERE id = {$data['applicationId']}
";
}
else
{
//insert and get id
$sql="
INSERT INTO myTable SET data='jsonstring'
";
}
Is it possible to simplify the above to one query using INSERT ...ON DUPLICATE KEY UPDATE even when the key is not always known ?
I've tried this:
INSERT INTO myTable
(
id,
data
)
VALUES
(
?, # <- I may not know this!!
'jsonstring'
)
ON DUPLICATE KEY UPDATE
data = 'jsonstring'
Thanks for any suggestions.

Yes, you can do that, assumed id is your primary key and auto_increment. You will have two different queries, one if you know the applicationId and one when you not knowing it.
The first, when you know it:
INSERT INTO myTable
(
id,
data
)
VALUES
(
1337, # <- insert id
'jsonstring'
)
ON DUPLICATE KEY UPDATE
data = 'jsonstring';
And the one if the applicationId is unknown:
INSERT INTO myTable
(
id,
data
)
VALUES
(
NULL, # <- This will cause mysql to use a auto_increment value
'jsonstring'
)
ON DUPLICATE KEY UPDATE
data = 'jsonstring';
So you can conclude this to:
$sql="INSERT INTO myTable
(
id,
data
)
VALUES
(" .
isset($data['applicationId']) ? $data['applicationId'] : 'NULL'
.",
'jsonstring'
)
ON DUPLICATE KEY UPDATE
data = 'jsonstring';
";
But be aware of How can I prevent SQL-injection in PHP?
Happy coding

Please forgive because your question is not 100% clear. However, the concept I can tell is that you want to be able to ask more than 1 query on 1 sql statement. That can be done with a multi-query command. However, if you want some of your data from a query placed in your next query I do not think it will work. Link provided for multi_query
http://php.net/manual/en/mysqli.quickstart.multiple-statement.php

First, Simple update query will run. If it runs successfully, it will not go to if condition and your ID will be the one which was used in updating.
And, if that ID is not available (means update query fails, $Query will be false), so pointer jumps to if condition and insert the query. Now, new Inserted ID we can get.
$ID=$data['applicationId'];
$Query=mysql_query("UPDATE myTable SET data='jsonstring' WHERE id='$ID' ");
if(!$Query)
{
$InsertQuery=mysql_query("INSERT INTO myTable SET data='jsonstring'");
$ID=mysql_insert_id();
}
So, $ID will be your ID.(either updated or currently inserted)

Related

insert or replace id exists or is difrent

I have this code in php to insert into database
$sqlx="INSERT INTO bruno_wallet (foto, data, nome, evento,horarios,obs,horas,valorhora,totalparcial,props,id_do_mes,nome_id )
VALUES ('$ii', '$data','$nome[0]','$evento' ,'$horarios','$obs','$numeros_horas','$valor_horas','$total_parcial','$props',' $id_postt','$nomeid') " ;
but it always inserts news values.
I want to : insert if its new and replace if old values if it exists
You shouldn't be using the INSERT command then. First find if it already is in your database then insert or leave it as it is.
You can use DUPLICATE KEY UPDATE if you have only primary key in table.
Note than: if you have any other key like Unique Key etc than it will not work.
$sqlx="INSERT INTO bruno_wallet (foto, data, nome, evento,horarios,obs,horas,
valorhora,totalparcial,props,id_do_mes,nome_id )
VALUES ('$ii', '$data','$nome[0]','$evento' ,'$horarios','$obs',
'$numeros_horas','$valor_horas','$total_parcial','$props','$id_postt','$nomeid')
ON DUPLICATE KEY UPDATE
foto = '$ii', data = '$data', nome = '$nome[0]', evento = '$evento', horarios = '$horarios',
obs = '$obs', horas = '$numeros_horas', valorhora = '$valor_horas',
totalparcial = '$total_parcial', props = '$props', id_do_mes = '$id_postt', nome_id = '$nomeid'
";
Explanation:
From dev.mysql.com: You can use the VALUES(col_name) function in the
UPDATE clause to refer to column values from the INSERT portion of the
INSERT ... ON DUPLICATE KEY UPDATE
If foto is a primary key than after ist insertion every time this query will update the record.
Hi here is simple and easy solution try it.
$result = mysql_query("SELECT * FROM bruno_wallet WHERE foto = '$ii' "); //in where condition add whatever condition you want
if( mysql_num_rows($result) > 0) {
$sqlx = "UPDATE bruno_wallet SET foto ='$ii', data = '$data', nome = '$nome[0]', evento = '$evento' ,horarios = '$horarios',obs = '$obs',horas = '$numeros_horas',valorhora = '$valor_horas',totalparcial = '$total_parcial',props = '$props',id_do_mes = ' $id_postt',nome_id = '$nomeid' WHERE foto = '$ii' "; //in where condition add whatever condition you want
}
else
{
$sqlx="INSERT INTO bruno_wallet (foto, data, nome, evento,horarios,obs,horas,valorhora,totalparcial,props,id_do_mes,nome_id )
VALUES ('$ii', '$data','$nome[0]','$evento' ,'$horarios','$obs','$numeros_horas','$valor_horas','$total_parcial','$props',' $id_postt','$nomeid') " ;
}
You cannot do that this way, an INSERT command is always an additional row in your database. You can however do something with subqueries, But the better practice is to do this in code.
You should run SELECT using the columns and values you have, If exists run a insert else run a update.
The problem you present is impossible to solve, since the database will not have anything to update if all columns match, I hope you understand how that would work, and that the way you intend it is not logical. Also you are not mentioning what your "matchcolumns" are. so if what matches what it should be an update...
If you do need to proceed this way, Please provide us more information so we can assist
If you are using MYSQL you can use INSERT ... ON DUPLICATE KEY UPDATE from Mysql manual
When doing an insert where a unique key is present the existing record will be updated with the fields you specify.
The easiest way to solve this is to check if the data sent exists in the database already. If the data is already in the database run an update query and run insert if not.
Run this first
Select * from bruno_wallet where nome_id='$nomeid';
Now fetch the data and set if to any variable. For this purpose am going to call it $info
Now run
if(!$info)
{
"INSERT INTO bruno_wallet (foto, data, nome, evento,horarios,obs,horas,valorhora,totalparcial,props,id_do_mes,nome_id )
VALUES ('$ii', '$data','$nome[0]','$evento' ,'$horarios','$obs','$numeros_horas','$valor_horas','$total_parcial','$props',' $id_postt','$nomeid') " ;
}else{
Run update query
}
`

MySQL stops running queries after if statement

I've been stuck on this for a few hours now ...
Here's my code:
$SQLQuery1 = $db_info->prepare("SELECT COUNT(ID) FROM menusize WHERE typesize=:typesize");
$SQLQuery1->bindValue(':typesize',$_POST['typesize'],PDO::PARAM_STR);
$SQLQuery1->execute();
if($SQLQuery1->fetchColumn() > 0) {
$SQLQuery2 = $db_info->prepare("INSERT INTO menucatagorysize (menucatagory_ID,menusize_ID) VALUES (:catagoryid,(SELECT ID FROM menusize WHERE typesize=:typesize))");
$SQLQuery2->bindValue(':typesize',$_POST['typesize'],PDO::PARAM_STR);
$SQLQuery2->bindValue(':catagoryid',$_POST['catagoryid'],PDO::PARAM_STR);
$SQLQuery2->execute();
} else {
$SQLQuery2 = $db_info->prepare("INSERT INTO menusize (typesize) VALUES (:typesize);
SET #menusizeid=LAST_INSERT_ID();
INSERT INTO menucatagorysize (menusize_ID,menucatagory_ID) VALUES (#menusizeid,:catagoryid)");
$SQLQuery2->bindValue(':typesize',$_POST['typesize'],PDO::PARAM_STR);
$SQLQuery2->bindValue(':catagoryid',$_POST['catagoryid'],PDO::PARAM_STR);
$SQLQuery2->execute();
}
$SQLQuery3 = $db_info->prepare("SELECT DISTINCT(menuitem_ID) FROM menuprice WHERE menucatagory_ID=:catagoryid");
$SQLQuery3->bindValue(':catagoryid',$_POST['catagoryid'],PDO::PARAM_STR);
$SQLQuery3->execute();
$rows = $SQLQuery3->fetchAll(PDO::FETCH_ASSOC);
So, it will run through the if statement fine, running $SQLQuery1 and $SQLQuery2 (Which ever one is required) without any problems, errors or warnings. But, if it runs the else { part of the code, it will not run $SQLQuery3. Any thoughts?
Thanks :D
EDIT: Got it to work by doing $SQLQuery2=NULL in the else statement ... Sucks that I still cant figure out why it wouldnt work the original way.
It appears that you're trying to enforce a uniqueness constraint over the typesize column of your menusize table from within your application code. However, the database can do this for you—which will make your subsequent operations much simpler:
ALTER TABLE menusize ADD UNIQUE (typesize)
Now, one can simply attempt to insert the posted value into the table and the database will prevent duplicates arising. Furthermore, as documented under INSERT ... ON DUPLICATE KEY UPDATE Syntax:
If a table contains an AUTO_INCREMENT column and INSERT ... ON DUPLICATE KEY UPDATE inserts or updates a row, the LAST_INSERT_ID() function returns the AUTO_INCREMENT value. Exception: For updates, LAST_INSERT_ID() is not meaningful prior to MySQL 5.1.12. However, you can work around this by using LAST_INSERT_ID(expr). Suppose that id is the AUTO_INCREMENT column. To make LAST_INSERT_ID() meaningful for updates, insert rows as follows:
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;
Therefore, you can do:
$db_info->prepare('
INSERT INTO menusize (typesize) VALUES (:typesize)
ON DUPLICATE KEY UPDATE typesize=LAST_INSERT_ID(typesize)
')->execute(array(
':typesize' => $_POST['typesize']
));
$db_info->prepare('
INSERT INTO menucatagorysize
(menusize_ID, menucatagory_ID)
VALUES
(LAST_INSERT_ID(), :catagoryid)
')->execute(array(
':catagoryid' => $_POST['catagoryid']
));
$stmt = $db_info->prepare('
SELECT DISTINCT menuitem_ID
FROM menuprice
WHERE menucatagory_ID = :catagoryid
');
$stmt->execute(array(
':catagoryid' => $_POST['catagoryid']
));
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
// etc.
}
(As an aside, the English word is spelled cat*e*gory, not cat*a*gory.)

How to detect if a record has been modified in MySQL and php

I am coding an application using php/MySQL. I got to a scenario where I need to update a record if it exists but if it does not exist then insert a new record.
Please note that I can NOT add unique indexes so I can not use REPLACE or INSERT INTO... ON DUPLICATE KEY UPDATE. also I don't know the primary key for the record that I am trying to update.
this is my update statement
UPDATE surveys_answers_controller
SET controller_id = $field['answer']
WHERE group_id = $group_id AND question_id = $field['question_id']
note that neither group_id nor question_id are a primary key in this table but a foreign keys.
I tried to use $db->lastInsertId() but it is always returning 1 wether it update a record or not. I am not sure why!
this is what I tried
$update_answer = $db->processQuery('UPDATE surveys_answers_controller
SET controller_id = ?
WHERE group_id = ? AND question_id = ? ',
array($field['answer'], $group_id, $field['question_id']) );
$last_id = $db->lastInsertId();
if(empty($last_id)){
$update_answer = $db->processQuery('INSERT INTO surveys_answers_controller( controller_id, group_id, question_id)VALUES(?,?,?)',
array($field['answer'], $group_id, $field['question_id']) );
}
$last_id is always returning 1 for some reason whether it did modify a record or not and that is why the insert statement is ignored.
I am using PDO to connect to the database not mysqli.
How can I write a query that check for existing record and it update it if exists otherwise it inserts it?
Thanks
Use PDOStatement::rowCount() instead of $db->lastInsertId. This finds the number of rows affected by the last update/insert/delete. If zero then do the insert.

How to get the id of the duplicated entry?

$query = "INSERT IGNORE INTO `user` (`name`, `email`) VALUES ( '".$name."', '".$email."')";
$res = mysql_query($query) or die("Query failed ".mysql_error() );
$last id = mysql_insert_id();
mysql_insert_id() return 0 if there is a duplicated entry.
Is there a way to get the ID of the duplicated entry ? or do I have to do 2 query ( SELECT + INSERT ) ?
There is no way with an INSERT to get the ID of the existing (duplicate) entry.
Still, you should not do a SELECT + INSERT because you would need to lock the table for concurrency (to ensure that nothing has changed between SELECT and INSERT).
In this case, if the insert fails, and you want to update the existing record instead, use INSERT ... ON DUPLICATE KEY UPDATE.
If you just want to fail, but have the existing ID, then fail, and do a SELECT to get the existing entry.

Check if exists, if so, update by 1++, if not insert

Hey guys quick question, I currently have an insert statement
$query= "INSERT into new_mail VALUES ('$to1', '0')"; where fields are username, and message_number
Currently what I would do to check if the entry exists, is do a select query then check the number of rows with mysql_num_rows (php). If rows==1 then I get the current message_number and set it equal to
$row['message_number']+1.
Then I update that entry with another query.
Is there an easier way to do all this in just mysql with just one query (check if exists, if not insert, if so update message_number, increase by 1)?
Depending on how your table is structured, you may be able to use the ON DUPLICATE KEY UPDATE (link to the MySQL manual) feature of INSERT:
INSERT into new_mail VALUES ('$to1', '0') ON DUPLICATE KEY UPDATE message_number=message_number+1
Use INSERT...ON DUPLICATE KEY UPDATE. The MySQL manual has an example which does almost exactly what you need:
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
To make this work you need to add a UNIQUE index on the column that you use to check for duplicates. There is one important warning though:
In general, you should try to avoid using an ON DUPLICATE KEY clause on tables with multiple unique indexes.
Got a little confused by your question and your table structures but I think you want something like this.
INSERT INTO new_mail (username, message_number)
VALUES ($username, $message_number)
ON DUPLICATE KEY UPDATE message_number=message_number + 1;
This is presuming username is your primary key (more likely something like userid). Hope this helps.
EDIT: The ON DUPLICATE KEY UPDATE answers are better, but you could do this (eludes the select query):
Assuming you're using the mysqli extenson:
$db = //Some construction of mysqli object;
$sql = 'UPDATE tablename SET RowValue = RowValue + 1 WHERE message_number = ?';
$updateStatement = $db->prepare($sql);
$updateStatement->bind_param('i', $message_number);
$message_number = //Set message number;
$updateStatement->execute();
if ($updateStatement->affectedRows == 0) {
$sql = 'INSERT INTO tablename (RowValue, message_number) VALUES (?, ?)';
$insertStatement = $db->prepare($sql);
$insertStatement->bind_param('ii', $rowValue, $messageNumber);
$rowValue = something;
$messageNumber = something;
$insertStatement->execute();
}

Categories