I'm working on a CSV import script in PHP attached to a MySQL database. I want to give the users the option to either insert new rows if duplicates are found or update them.
I can't use ON DUPLICATE KEY UPDATE because the column cannot be unique, otherwise it won't cater for when they want to have duplicates.
How would I go about this?
Use 2 queries - a select query to determine if the row exists, then based on that result either an insert or update query.
I would script it for use on the command line. In your loop, check if an entry with the same key already exists. If it does, prompt the user to decide what to do using fgets(STDIN).
why not just add a UNIQUE key to the table, possibly spanning multiple fields?
here is an example given the following simple phonebook table:
CREATE TABLE phonebook (
firstname VARCHAR(255),
lastname VARCHAR(255),
home VARCHAR(50),
mobile VARCHAR(50)
)
you can easily add a key making firstname AND lastname together unique.
ALTER TABLE phonebook ADD UNIQUE (firstname, lastname)
that way you can use the ON DUPLICATE KEY UPDATE statement to easily update the phone numbers when the name is already on the list:
INSERT INTO phonebook (firstname, lastname, home, mobile)
VALUES ("john", "doe", "12345", "45678")
ON DUPLICATE KEY UPDATE home = "12345", mobile = "45678"
everything else is getting unnecessarily complex.
Related
I have a MySQL table that has Auto-increment on the ID field. However I need to create, via php, two rows with the same id.
I've tried using $last_id = intval(mysql_insert_id()); But just can't get to set the id on the second row. I am very new to php and SQL has never been my closest friend.
$sql = "INSERT INTO 'table name' (name, age, phone) VALUES ({$name}, {$age}, {$phone});"
$result = mysqli_query($conn, $sql);
Then I would like to run the same insert statement again, maybe with the phone being different, but with the ID being the same.
Your problem here is the auto_increment ID field. This is a primary key, since any auto_increment field must be defined as the table's primary key and therefore cannot have duplicate records.
What you could do is create and additional field for your "ID" field that you want to duplicate and then you can insert normally and leave the auto incrementing field do it's thing.
I want to insert data into Mysql, and when the data is already in the table, it should not be inserted again. How to prevent the second insert?
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "INSERT INTO MyGuests(firstname, lastname, email)
VALUES ('John', 'Doe', 'john#example.com')";
// use exec() because no results are returned
$conn->exec($sql);
echo "Table MyGuests created successfully";
} catch(PDOException $e) {
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
The result is like this:
You do not have a unique key on the email address. That is your best hope, as many John Doe's can be in the system. So a unique composite index on full name is not ever a good idea.
One can issue an INSERT IGNORE which plods along after a duplicate violation as if nothing happens (this is highly unrecommended, and in your case not possible because your unique constraint on email is not present). The major problem with doing this is that your tend (read: probably will) lose all control of flow of what is happening and be left with undesired data. So don't use it, unless you are a pro.
One can issue and INSERT ON DUPLICATE KEY UPDATE (a.k.a. IODKU) that also requires a unique key (can be a unique composite too). As such, a new row would not occur but an update to the row. As an example, a new row with 4 columns could be inserted, but on duplication violation, an update could be performed on just two of the columns, such as
assuming in below a PK on an unseen column id int, and a unique key on emailAddr
insert person(firstName,lastName,emailAddr) values 'Joe','Smith','jsmith#email.com'
on duplicate key update firstName='Joe',lastName='Smith'
It is the unique key on emailAddr that makes this work. Left with only 1 row per emailAddr, ever.
So, you can have unlimited Joe Smiths, but only 1 row per email address.
The create table for the above table could look like
create table person
( id int auto_increment primary key,
firstName varchar(50) not null,
lastName varchar(50) not null,
emailAddr varchar(150) not null,
unique key(emailAddr) -- without this, IODKU will not work
);
You can also issue ALTER TABLE commands to add constraints after the table is created. Depending on the data therein, the call may fail.
Mysql Insert on Duplicate Key Update, and Alter Table manual pages.
I will say it again, without the proper schema setup, IODKU will not work and you will be left with undesired rows. So don't be lazy about it. Setup schema first allowing it to success (with unique keys), then move on toward using IODKU.
You need to add a unique constraint/index and ignore errors caused by the duplication. If this is your query:
INSERT INTO MyGuests(firstname, lastname, email)
VALUES ('John', 'Doe', 'john#example.com');
And you want to prevent all three columns from being re-inserted, then you can add the unique as:
create unique index unq_myguests_firstname_lastname_email on myguests(firstname, lastname, email);
Then, phrase the insert as:
INSERT INTO MyGuests(firstname, lastname, email)
VALUES ('John', 'Doe', 'john#example.com')
ON DUPLICATE KEY UPDATE firstname = VALUES(firstname);
The ON DUPLICATE KEY UPDATE portion does nothing, except ignore the errors.
Here is what I want to do. Insert if the unique index (code) doesn't exist in the table already. If it exists then simply update the row.
I can't use primary key because it is Auto Increment ID. Here is the code
$sql="INSERT INTO codes (code,registration,country)
VALUES ('$war','$regi','$country') ON DUPLICATE KEY UPDATE code='$war', registration='$regi', country='$country'";
But it doesn't work because I think it is checking for duplicate primary key. So when I try to insert the row in which the value of column code is same as previous row I get Duplicate entry 'xxx' for key 'code' error. So how to make this work for unique index code ?
Ahmar
ON DUPLICATE KEY UPDATE works with UNIQUE indexes as well as PRIMARY KEY values. Try setting one of the values you are trying to update to be UNIQUE on your database table.
All you have to do is set code to be a unique index. Then, anytime you try to do an insert where code matches it will update instead.
Alter this code as needed
alter table `table` add unique index(`code`);
You are correct, having a primary key on your table will not allow you to insert duplicate key values.
In the past, I have used something like this:
SELECT COUNT(*)
FROM codes
WHERE code = '$war'
Then if the count is > 0, you know there's a duplicate and you do:
UPDATE codes
SET registration = '$regi', country = '$country'
WHERE code = '$war'
Otherwise you do:
INSERT INTO codes (code, registration, country)
VALUES ('$war', '$regi', '$country')
However, if we assume you're using MySQL, you might be able to make use of either INSERT IGNORE or REPLACE.
If you use:
INSERT IGNORE codes (code, registration, country)
VALUES ('$war', '$regi', '$country')
The values will be inserted if the code does not already exist. If the code does exist, no record is inserted and MySQL will silently discard the statement without generating an error.
I think what you probably want is this:
REPLACE INTO codes (code, registration, country)
VALUES ('$war', '$regi', '$country')
REPLACE INTO behaves just like INSERT INTO if the record is new. But if the primary key is duplicated, it will perform an UPDATE instead.
Again, INSERT IGNORE and REPLACE INTO are for MySQL only.
Reference: http://www.tutorialspoint.com/mysql/mysql-handling-duplicates.htm
This question already has answers here:
MySQL 'UPDATE ON DUPLICATE KEY' without a unique column?
(3 answers)
Closed 10 months ago.
I know about INSERT ... ON DUPLICATE KEY UPDATE but that won't work because the criteria that I will use to check for an existing row is not a unique or primary key. In fact, it will be 2 different fields. It couldn't even be unique key because the values will not be unique.
This is my dummy insert statement
INSERT INTO
videos
(
first_name,
last_name,
addresss,
plan
)
VALUES
(
:first_name,
:last_name,
:addresss,
:plan
)
So I want to say if there's a row already WHERE last_name = :last_name AND plan = :plan, then update it, otherwise, add a new row.
I could do this with multiple queries, but I'm just trying to see if there's a way to do this with one shot without going back and forth with it. This will be done in a loop, so if I have to do it in multiple queries it will probably double the number of queries.
Just define a unique index on the two columns:
create unique index videos_lastname_plan on videos(lastname, plan);
The documentation clearly states:
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, MySQL
performs an UPDATE of the old row.
So, a unique index on two clumns is perfectly fine. The statement is:
INSERT INTO videos (first_name, last_name, addresss, plan)
VALUES (:first_name, :last_name, :addresss, :plan)
on duplicate key update address = VALUES(address), first_name = VALUES(first_name);
I'm creating a messaging system and I'm trying to set it up so it will have a "conversation view" and so users can reply to a message. To do this I have to have a primary ID for each conversation in the table and then a separate unique ID for each message.
My problem is that when I try replying to a message I get this error:
Duplicate entry '98' for key 1
It looks like it isn't allowing me to use the same ID in a column, but I don't have a 'unique' thing set in the table AFAIK.
I also tried to drop the PRIMARY for the id column but got this error:
The message is:
#1075 - Incorrect table definition; there can be only one auto column and it must be defined as a key
I don't understand why it won't let me insert the same ID into the id column, because as you know I need an ID for each conversation.
The mysql_query that I'm using to insert the reply into the table is:
$sql = "INSERT INTO messages (id, message_id, to_user, message, subject, from_user, date, time, date_short)
VALUES ('$id', '$message_id', '$to', '$message', '$subject', '$user', '$date', '$time', '$date_short')";
mysql_query($sql) or die(mysql_error());
Thanks in advance!
Your primary key can not be repeated, otherwise it isn't so useful as a key, is it? The primary key must uniquely identify the record.
The reason you're getting the error is that the column is set to be auto-number. You have not added that column to a separate key, which is a requirement for auto-number columns in MySQL.
Add it to a key/index with that column first, then remove the PK attribute. Make sure you have some PK in the table.
You can't have auto_increment without a key
I suspect you have AUTO_INCREMENT setup on your id field. If this is the case, then the values in the id column must be unique.
Either remove the AUTO_INCREMENT attribute on that column (by redefining the column without AUTO_INCREMENT via an ALTER TABLE command), or don't specify the id value in your INSERT statement.
First, untick AUTO_INCREMENT option on your column and as the second step, try to drop the index again
PRIMARY KEYs are also unique. auto_increment columns must be primary keys. You can't drop PRIMARY KEY from a column without making it not auto_increment.
However, I don't think you should change your table like this. You should keep your IDs and either create a new table with the data you need to update, or use UPDATE instead of INSERT.
Columns with primary keys can't have duplicates, otherwise they lose their uniqueness. MySQL will prevent same values. Having to alter primary key vales is also bad news. You may want to re-approach what you're doing and possibly create more tables.