On duplicate Key update.. database key? - php

I have a table (id, name, price, menu_id)
I have a page in which every item's name and price is shown, and the users can edit it.
But when I submit, it creates new rows.
The index is on the primary key. Should it be on something else?
I tried the following:
INSERT INTO gerechten
SET gerecht_naam = :naam, gerecht_prijs = :prijs, menu_id = :menuid
ON DUPLICATE KEY
UPDATE gerecht_naam = :naam, gerecht_prijs = :prijs

your query will transform to an update whenever any unique key crashes in your table. Up to you to decide where this key should be placed on. For example, your query could be:
INSERT INTO `gerechten` (`name`, `price`, `menu_id`)
VALUES (:name, :price, :menuid)
ON DUPLICATE KEY UPDATE
name = :name,
price = :price
with a unique index on name AND menu_id for example. (I believe there can be several times the same name as long as it is in a different menu)
Of course if there are various fields combinations that must be unique this is a problematic situation and maybe you should use a different approach, such as a select ... lock statement to check previous existence of the values being edited.

You need to add a UNIQUE key to the gerech_naam column and/or to the gerech_prijs (you can have two columns define uniqueness of a row).
If you were to implement these unique keys to the table, you have to be aware that you would still have a problem because if you change the name or the price it could possibly insert in the DB because the data you provide doesn't exist in the table.

Related

PHP MySQL Insert Query that won't insert if already exists

I've been doing some research and haven't found anything that I've been able to make work, unfortunately, and I think that stems from not understanding the MySQL construct in the examples I've been looking at.
What I'm trying to do is run an insert query, and do a check on values in 3 specific columns to ensure they don't exist, then insert, else do nothing.
My Table is pretty basic: id(int11), user(varchar(45)), label(varchar(255)), agent(varchar(255)), empid(varchar(10)).
My id is my Primary, with Auto increment, and here is my code I currently have that works on inserting, but doesn't have the handling in place for duplicates:
$i = 0;
foreach ($agents as $ag){
$sql = mysql_query("INSERT INTO `pms_users`
(`id`,`user`,`label`,`agent`,`empid`)
VALUES
(NULL, '$user','$group','$labels[$i]','$ag')");
$i ++;
}
The three columns I need to check against are the $user, $group, and $ag.
Add a unique index for (user, label, empid). Then the database won't allow you to create duplicates.
ALTER TABLE pms_users
ADD UNIQUE INDEX (user, label, empid);
If you can only have one row per combination of user, label and agent, you should define them as a unique constraint:
ALTER TABLE pms_users ADD CONSTRAINT pms_users_unq UNIQUE (`user`, `label`, `agent`);
And then let the database do the heavy lifting with an insert-ignore statement:
INSERT IGNORE INTO `pms_users`
(`user`, `label`, `agent`, `empid`)
VALUES ('some_user', 'some_label', 'some_agent', 123)
You can try insert on duplicate key update query.. It checks duplicate keys. If they exist MySQL do update query if not exist MySQL doing insert query.
Sure in your database you should declare unique keys.
Here is MySQL documentation for this case
https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html

IF EXISTS MySQL

I'm from a mssql background so it's difficult to get used to MySQL.
I have a table called users_settings. Within this table there are three columns; uid, name, value. Uid is a integer and refers to the user that owns that setting, the name is the name of the setting, the value, well, you guessed it, is the value.
What I'm trying to do is update these settings if it already exists, but if it doesn't, insert a new row.
My current query is as such (Note I'm using prepared statements):
IF EXISTS (SELECT * FROM users_settings WHERE name = ? AND uid = ?) THEN
UPDATE users_settings SET value = ? WHERE name = ? AND uid = ?;
ELSE
INSERT INTO users_settings (uid, name, value) VALUES (?, ?, ?);
END IF;
The issue I'm having is that when I attempt to prepare my statement, it returns false, which therefore suggests that the syntax is incorrect. After looking in to this, it looks like it's a SQL syntax error.
Would anybody be able to point me in the relative direction as to what may be occurring here, and where I may have got my syntax incorrect?
IN MySQL, if as a statement can only used in programming blocks -- stored procedures, functions, and triggers (this is not to be confused with if as a function, which can be used in almost any SQL statement).
You can do what you want in MySQL with a single statement, insert . . . on duplicate key update. For this to work, you need a unique index on name and uid:
create unique index users_settings_name_uid on users_settings(name, uid);
And then:
INSERT INTO users_settings (uid, name, value)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE value = VALUES(value);
There are two ways to fulfill your request in MySQL:
If you want to update an existing row or insert a new one if it does not exist then you should use INSERT ... ON DUPLICATE KEY UPDATE:
INSERT INTO users_settings (uid, `name`, `value`)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE `value` = VALUES(`value`);
This relies on an unique index that contains the columns uid and name. If it does not already exist, you can create it:
ALTER TABLE users_settings
ADD UNIQUE INDEX uid_name (uid, `name`);
You need it anyway because you want a single entry in the table for each user and setting name.
If you want to insert a row in the table and replace (discard) another one that already exists then you can use REPLACE:
REPLACE INTO users_settings (uid, `name`, `value`)
VALUES (?, ?, ?);
The syntax of REPLACE is similar with the one of INSERT (but it does not support ON DUPLICATE KEY UPDATE for obvious reasons). Internally it does a DELETE followed by an INSERT (it is just a shortcut). It discards the existing row (if any) and insert the new one. It also relies on the presence of the above mentioned index (that you have no matter how you update the values in the table).
For your situation both approaches have the same outcome because there is a single column (value) that is updated or replaced. In other situations only one of them is good.
Choose the one that you feel more appropriate for your workflow and your coding style.
INSERT INTO persona_opcion(nPerCodigo,nOpcCodigo,nPerOpcEstado)
SELECT '$codPer','$idOpc',1
FROM persona_opcion
WHERE NOT EXISTS(
SELECT nPerCodigo,nOpcCodigo,nPerOpcEstado
FROM persona_opcion
WHERE nOpcCodigo='$idOpc'
and nPerCodigo='$codPer'
)
LIMIT 1;
enter link description here

Updating a MySQL record with an auto-increment field as PK

I have a MySQL table with an auto-incrementing primary key (UID). The user can bring up a record in this table via a PHP form, where the UID is a $_GET variable. I would like the database to update the chosen record if it exists, but every time the user hits submit, a new record is created. This is what I've tried so far:
//Present the form
$form = $con->prepare("SELECT Name, Date, Time FROM forms WHERE UID = :uid");
$data = array('uid'=>$_GET['uid']);
$form->execute($data);
$row = $form->fetch(PDO::FETCH_ASSOC);
//Write new record to database. If the UID exists, update the record.
INSERT INTO forms (Name, Date, Time) VALUES (:name, :date, :time)
ON DUPLICATE KEY UPDATE Name=VALUES(Name),Date=VALUES(Date),Time=VALUES(Time);
This doesn't work. Do I need another unique key in the table, or am I missing something obvious?
INSERT INTO forms (`Name`, `Date`, `Time`) VALUES (:name, :date, :time)
ON DUPLICATE KEY UPDATE `Name`=:name, `Date`=:date, `Time`=:time;
This should be the query; I removed VALUES() from your code and added backticks and corrected your parameters.
And I recommend you to use backticks around column names so it doesn't get confused with other similar SQL keywords as example.

Avoid entering duplicate entries based on date, without using select statement

I am running a insert statement to insert data, but I want to check for any duplicate entries based on date and then do an entry.
All I want is if today a user enters product_name='x', 'x' is unique so that no one can enter product name x again today. But of course the next day they can.
I do not want to run a select before the insert to do the checking. Is there an alternative?
You can either use
1. Insert into... on duplicate update
2. insert.. ignore
This post will answer your question
"INSERT IGNORE" vs "INSERT ... ON DUPLICATE KEY UPDATE"
You can use the mysql insert into... on duplicate update syntax which will basically enter in a new row if one isn't there, or if the new row would have caused a key constraint to kick in, then it can be used to update instead.
Lets say you have the following table:
MyTable
ID | Name
1 | Fluffeh
2 | Bobby
3 | Tables
And ID is set as the primary key in the database (meaning it CANNOT have two rows with the same value in it) you would normally try to insert like this:
insert into myTable
values (1, 'Fluffster');
But this would generate an error as there is already a row with ID of 1 in it.
By using the insert on duplicate update the query now looks like this:
insert into myTable
values (1, 'Fluffster')
on duplicate key update Name='Fluffster';
Now, rather than returning an error, it updates the row with the new name instead.
Edit: You can add a unique index across two columns with the following syntax:
ALTER TABLE myTable
ADD UNIQUE INDEX (ID, `name`);
This will now let you use the syntax above to insert rows while having the same ID as other rows, but only if the name is different - or in your case, add the constraint on the varchar and date fields.
Lastly, please do add this sort of information into your question to start with, would have saved everyone a bit of time :)

Database normalization and lazy development

I believe the question have emerged as my irritation of doing twice as much work as I could imagine is necessary.
I accept the idea that I could be lacking experience with both MySQL and PHP to think of a simpler solution.
My issue is that I have several tables (and I'd might be adding more) and of these is a parent table, only containing two fields - an id (int) and a name identifying it.
At this moment, I have seven tables with at least 15 fields in each one. Every table has a field, containing the id which I can link to the parent table.
All of these data isn't required to be filled - you will just have to create that one entry in the parent table. For the other tables, I have separate forms.
Now, these forms are made for updating the data in the fields, which means I have to pull out the data from the table if any data is available.
What I would like to do is when I receive the data from my form, I could just use an UPDATE query in my model. But if the table I want to update doesn't have an entry for that specific id, I need to do an insert.
So, my current pseudo code is like this:
$sql = "SELECT id FROM table_x WHERE parent_id = ".$parent_id;
$res = $mysql_query($sql);
if( mysql_num_rows($res) == 1 )
{
$sql = "UPDATE table_x SET ... WHERE parent_id = ".$parent_id;
}
else
{
$sql = "INSERT INTO table_x VALUES ( ... )";
}
mysql_query($sql);
I have two do this for every table I have - can I do something different or smarter or is this just the way it has to be done? Cause this seems very inefficient to me.
Use
INSERT ... ON DUPLICATE KEY UPDATE Syntax
It will insert if record not found,
otherwise, it will update existing record,
and you can skip the check before insert - details
This assuming relation for each 7 table to the parent table is 1:1
Or use REPLACE instead of INSERT - it's an insert, but will do an DELETE and then INSERT when a unique key (such as the primary key) is violated.
in mysql you can do this:
INSERT INTO table
(
col1,
col2
) VALUES(
'val1',
'val2'
) ON DUPLICATE KEY UPDATE table SET
col2 = 'val2'
take a look at the documentation for more information
mysql_query("UPDATE table table_x ..... WHERE parent_id=".$parent_id);
if (mysql_affected_rows()==0) {
mysql_query("INSERT INTO .....");
}

Categories