On insert I am catching the unique constraint mysql_errno() 1062.
This works fine but I want to find the existing row to re-instate or modify it.
Is there are method to obtain the row id on insert fail? I tried mysql_insert_id() but realised that would only return the row I'm inserting (or failed to insert) therefore, I get 0.
Is there no option but to issue another mysql_query and simply perform a select on the duplicate value?
I just want to make sure there is no better, quicker, more economical way to do this.
If you are attempting to insert a row if new or update existing values then REPLACE INTO is what you need. Also consider INSERT ... ON DUPLICATE KEY UPDATE Syntax if there are constraints involved as REPLACE INTO will DELETE and then INSERT.
You'd have to check the table for any "unique" keys (SHOW CREATE TABLE will list them all), and then query the table for the associated values in the insert query you'd attempted. So if you're inserting fields A,B,C,D and B,C have the unique key on them, then:
SELECT id, B, C FROM table WHERE B=$B and C=$C;
Related
I have a MySQL query that looks like this:
INSERT INTO beer(name, type, alcohol_by_volume, description, image_url) VALUES('{$name}', {$type}, '{$alcohol_by_volume}', '{$description}', '{$image_url}')
The only problem is that name is a unique value, which means if I ever run into duplicates, I get an error like this:
Error storing beer data: Duplicate entry 'Hocus Pocus' for key 2
Is there a way to ensure that the SQL query does not attempt to add a unique value that already exists without running a SELECT query for the entire database?
You could of course use INSERT IGNORE INTO, like this:
INSERT IGNORE INTO beer(name, type, alcohol_by_volume, description, image_url) VALUES('{$name}', {$type}, '{$alcohol_by_volume}', '{$description}', '{$image_url}')
You could use ON DUPLICATE KEY as well, but if you just don't want to add a row INSERT IGNORE INTO is a better choice. ON DUPLICATE KEY is better suited if you want to do something more specific when there are a duplicate.
If you decide to use ON DUPLICATE KEY - avoid using this clause on tables with multiple unique indexes. If you have a table with multiple unique indexes ON DUPLICATE KEY-clause could be giving unexpected results (You really don't have 100% control what's going to happen)
Example: - this row below only updates ONE row (if type is 1 and alcohol_by_volume 1 (and both columns are unique indexes))
ON DUPLICATE KEY UPDATE beer SET type=3 WHERE type=1 or alcohol_by_volume=1
To sum it up:
ON DUPLICATE KEY just does the work without warnings or errors when there are duplicates.
INSERT IGNORE INTO throws a warning when there are duplicates, but besides from that just ignore to insert the duplicate into the database.
As it just so happens, there is a way in MySQL by using ON DUPLICATE KEY UPDATE. This is available since MySQL 4.1
INSERT INTO beer(name, type, alcohol_by_volume, description, image_url)
VALUES('{$name}', {$type}, '{$alcohol_by_volume}', '{$description}',
'{$image_url}')
ON DUPLICATE KEY UPDATE type=type;
You could also use INSERT IGNORE INTO... as an alternative, but the statement would still throw a warning (albeit, instead of an error).
Yes, there is. You can use the ON DUPLICATE KEY clause of mysql INSERT statement. The syntax is explained here
INSERT INTO beer(name, type, alcohol_by_volume, ...)
VALUES('{$name}', {$type}, '{$alcohol_by_volume}', ...)
ON DUPLICATE KEY UPDATE
type={$type}, alcohol_by_volume = '{$alcohol_by_volume}', ... ;
Yes, by first selecting the name from the database, and if the result of the query is not null (zero records), then the name already exists, and you have to get another name.
Quite simply - your code needs to figure out what it wants to do if something's trying to insert a duplicate name. As such, what you need to do first is run a select statement:
SELECT * FROM beer WHERE name='{$name}'
And then run an 'if' statement off of that to determine if you got a result.
if results = 0, then go ahead and run your insert.
Else ... whatever you want to do. Throw an error back to the user? Modify the database in a different way? Completely ignore it? How is this insert statement coming about? A mass update from a file? User input from a web page?
The way you're reaching this insert statement, and how it should affect your work flow, should determine exactly how you're handling that 'else'. But you should definitely handle it.
But just make sure that the select and insert statements are in a transaction together so that other folks coming in to do the same sort of stuff isn't an issue.
I have a table which has one unique column. I will insert records into it using PHP.
If there is a record with this unique column, do not insert, Else, insert.
Should I first select and decide whether insert or not.
Or
Insert anyway and ignore duplicate errors?
Which one more efficient?
use INSERT INGORE syntax.. you shoud not be worry about checking the data before inserting.
Quoted from mysql manual
INSERT IGNORE in the treatment of new rows that contain unique key
values that duplicate old rows: The new rows are used to replace the
old rows rather than being discarded
i'm new to php . i'm just wondering which PHP script can detects if a MySQL database's table contains data . If yes , it will update the data with the submitted form data. If not(blank) it will insert the form data into it.
I know how to insert data using php just wondering how can i CHECK if data exist in a table.
Thanks and have a nice day .
You are looking for INSERT ... ON DUPLICATE KEY UPDATE.
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
Just append the ON DUPLICATE KEY UPDATE x=y, z=a to your current INSERT and if the unique value you try to insert already exists, the row containing it is updated.
MySQL can help with that depending on your way to check (primary key ?) - see http://www.xaprb.com/blog/2006/02/21/flexible-insert-and-update-in-mysql/
Checking if data exists in a database is a read operation, so you'd use a SELECT statement. If the SELECT statement returns a non-empty recordset, then you know the data exists. Bonus: you also know the id number of the data you're looking for, for use in your update operation.
The INSERT... ON DUPLICATE KEY UPDATE is great if you know the unique id number of the row you're updating... which you might now.
The only issue with using a SELECT statement is that the operation is not guaranteed to be atomic - that is, this might happen:
- you run the SQL statement and get an empty set
- a different process inserts that form data into the database
- the first process, that ran the select statement, inserts the same form data
Good luck!
I've always used the method of checking a table to see if a row exists, and then update it with my new data or insert it if it doesn't exist, but it's got me thinking what would be wrong with simply doing an update, if no rows are affected, then do an insert statement, that could potentially speed up my script and put less load on the server.
Anyone foresee any problems with this?
What's wrong with REPLACE?
REPLACE works exactly like INSERT, except that if an old row in the table has the same value as a new row for a PRIMARY KEY or a UNIQUE index, the old row is deleted before the new row is inserted.
If by "see if a row exists" you mean by primary key, you might be interested by 12.2.5.3. INSERT ... ON DUPLICATE KEY UPDATE Syntax :
If you specify ON DUPLICATE KEY
UPDATE, and a row is inserted that
would cause a duplicate value in a
UNIQUE index or PRIMARY KEY, an UPDATE
of the old row is performed. For
example, if column a is declared as
UNIQUE and contains the value 1, the
following two statements have
identical effect:
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
UPDATE table SET c=c+1 WHERE a=1;
Maybe you can use this ?
Compared to what you said, tt's doing exactly the other way arround : trying to insert, and if there is a DUPLICATE KEY error, it updates the line... But it allows you not to check if the line exists first.
Still, it only works by primary key / unique index ; not with any kind of where clause.
the REPLACE statement does the same thing, if a row doesn't exist it will insert it, if it exists it will update it.
INSERT IGNORE is also useful here.
Is it possible to insert a row, but only if one of the values already in the table does not exist?
I'm creating a Tell A Friend with referral points for an ecommerce system, where I need to insert the friend's email into the database table, but only if it doesn't already exist in the table. This is because I don't want any more than 1 person getting the referral points once the new customer signs up and purchases something. Therefore I want only one email ever once in the table.
I'm using PHP 4 and MySql 4.1.
This works if you have a unique index or primary key on the column (EmailAddr in this example):
INSERT IGNORE INTO Table (EmailAddr) VALUES ('test#test.com')
Using this if a record with that email already exists (duplicate key violation) instead of an error, the statement just fails and nothing is inserted.
See the MySql docs for more information.
If the column is a primary key or a unique index:
INSERT INTO table (email) VALUES (email_address) ON DUPLICATE KEY UPDATE
email=email_address
Knowing my luck there's a better way of doing it though. AFAIK there's no equivalent of "ON DUPLICATE KEY DO NOTHING" in MySQL. I'm not sure about the email=email_Address bit, you could play about and see if it works without you having to specify an action. As someone states above though, if it has unique constraints on it nothing will happen anyway. And if you want all email addresses in a table to be unique there's no reason to specify it as unique in your column definition.
Most likely something like:
IF NOT EXISTS(SELECT * FROM myTable WHERE Email=#Email) THEN INSERT INTO blah blah
That can be rolled into one database query.
A slight modification/addition to naeblis's answer:
INSERT INTO table (email) VALUES (email_address)
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id)
This way you don't have to throw email=email_address in there and you get the correct value for LAST_INSERT_ID() if the statement updates.
Source: MySQL Docs: 12.2.5.3
MySQL offers REPLACE INTO http://dev.mysql.com/doc/refman/5.0/en/replace.html:
REPLACE works exactly like INSERT,
except that if an old row in the table
has the same value as a new row for a
PRIMARY KEY or a UNIQUE index, the
old row is deleted before the new row
is inserted.
I'm not sure if I got it, but what about a
try {
mysql_query($sql);
}
catch(Exception $e) {
}
combined with an unique field index in MySQL?
if it throws an exception then you know that you got a duplicated field.
Sorry if that don't answer your question..
If the email field was the primary key then the constraints on the table would stop a duplicate from being entered.