如何防止重复插入 table

How to prevent duplicate inserts into a table

我想向Mysql中插入数据,当数据已经在table中时,不应再次插入。如何防止二次插入?

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;

结果是这样的:

您在 电子邮件地址 上没有唯一密钥。这是你最大的希望,因为系统中可以有许多 John Doe。因此,全名的唯一复合索引从来都不是一个好主意。

可以发出 INSERT IGNORE,它在重复违规后缓慢前进,就好像什么都没发生一样(这是非常不推荐的,在您的情况下是不可能的,因为您对电子邮件的独特约束不存在)。这样做的主要问题是您倾向于(阅读:可能会)失去对正在发生的事情的所有控制并留下不需要的数据。所以不要用它,除非你是专业人士。

可以发布 INSERT ON DUPLICATE KEY UPDATE (a.k.a.IODKU),它也需要唯一的密钥(也可以是唯一的组合)。因此,不会出现新行,而是更新该行。例如,可以插入一个包含 4 列的新行,但如果出现重复冲突,则可以仅对其中两列执行更新,例如

假设在下面一个看不见的列 id int 上的主键和 emailAddr

上的唯一键
insert person(firstName,lastName,emailAddr) values 'Joe','Smith','jsmith@email.com' 
on duplicate key update firstName='Joe',lastName='Smith'

emailAddr 上的唯一键使这项工作成功。每个 emailAddr 只剩下 1 行,永远。

因此,您可以有无限个 Joe Smiths,但每个电子邮件地址只能有 1 行。

上面 table 的创建 table 看起来像

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
);

您还可以在创建 table 后发出 ALTER TABLE 命令来添加约束。根据其中的数据,调用可能会失败。

Mysql Insert on Duplicate Key Update, and Alter Table 手册页。

我再说一遍,如果没有正确的模式设置,IODKU 将无法工作,您将留下不需要的行。所以不要偷懒。设置架构 first 允许它成功(使用唯一键),然后 继续使用 IODKU。

您需要添加一个唯一的 constraint/index 并忽略由重复引起的错误。如果这是您的查询:

INSERT INTO MyGuests(firstname, lastname, email)
    VALUES ('John', 'Doe', 'john@example.com');

并且您想防止所有三列都被重新插入,那么您可以添加唯一性为:

create unique index unq_myguests_firstname_lastname_email on myguests(firstname, lastname, email);

然后,将 insert 表述为:

INSERT INTO MyGuests(firstname, lastname, email)
    VALUES ('John', 'Doe', 'john@example.com')
    ON DUPLICATE KEY UPDATE firstname = VALUES(firstname);

ON DUPLICATE KEY UPDATE 部分除了忽略错误外什么都不做。