How to prevent duplicate inserts into a table

≡放荡痞女 提交于 2019-12-25 03:32:58

问题


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:


回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/33318726/how-to-prevent-duplicate-inserts-into-a-table

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!