mysql - MySQL中的 'insert if not exists'怎么办?

标签 mysql sql sql-insert primary-key unique-constraint

我首先通过谷歌搜索找到了这篇文章 How to write INSERT if NOT EXISTS queries in standard SQL 其中讨论了互斥表。

我有一个包含约 1400 万条记录的表。如果我想以相同的格式添加更多数据,有没有一种方法可以确保我想要插入的记录不存在,而不使用一对查询(即,一个要检查的查询和一个要插入的查询,结果集是空)?

字段上的唯一约束是否能保证插入在字段已经存在的情况下会失败?

看起来仅仅是一个约束,当我通过 PHP 发出插入时,脚本会发出嘎嘎声。

最佳答案

使用INSERT IGNORE INTO table

还有 INSERT … ON DUPLICATE KEY UPDATE 语法,您可以在 13.2.6.2 INSERT ... ON DUPLICATE KEY UPDATE Statement 中找到解释。

<小时/>

来自bogdan.org.ua的帖子根据Google's webcache :

18th October 2007

To start: as of the latest MySQL, syntax presented in the title is not possible. But there are several very easy ways to accomplish what is expected using existing functionality.

There are 3 possible solutions: using INSERT IGNORE, REPLACE, or INSERT … ON DUPLICATE KEY UPDATE.

Imagine we have a table:

CREATE TABLE `transcripts` (
`ensembl_transcript_id` varchar(20) NOT NULL,
`transcript_chrom_start` int(10) unsigned NOT NULL,
`transcript_chrom_end` int(10) unsigned NOT NULL,
PRIMARY KEY (`ensembl_transcript_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Now imagine that we have an automatic pipeline importing transcripts meta-data from Ensembl, and that due to various reasons the pipeline might be broken at any step of execution. Thus, we need to ensure two things:

  1. repeated executions of the pipeline will not destroy our > database
  1. repeated executions will not die due to ‘duplicate > primary key’ errors.

Method 1: using REPLACE

It’s very simple:

REPLACE INTO `transcripts`
SET `ensembl_transcript_id` = 'ENSORGT00000000001',
`transcript_chrom_start` = 12345,
`transcript_chrom_end` = 12678;

If the record exists, it will be overwritten; if it does not yet exist, it will be created. However, using this method isn’t efficient for our case: we do not need to overwrite existing records, it’s fine just to skip them.

Method 2: using INSERT IGNORE Also very simple:

INSERT IGNORE INTO `transcripts`
SET `ensembl_transcript_id` = 'ENSORGT00000000001',
`transcript_chrom_start` = 12345,
`transcript_chrom_end` = 12678;

Here, if the ‘ensembl_transcript_id’ is already present in the database, it will be silently skipped (ignored). (To be more precise, here’s a quote from MySQL reference manual: “If you use the IGNORE keyword, errors that occur while executing the INSERT statement are treated as warnings instead. For example, without IGNORE, a row that duplicates an existing UNIQUE index or PRIMARY KEY value in the table causes a duplicate-key error and the statement is aborted.”.) If the record doesn’t yet exist, it will be created.

This second method has several potential weaknesses, including non-abortion of the query in case any other problem occurs (see the manual). Thus it should be used if previously tested without the IGNORE keyword.

Method 3: using INSERT … ON DUPLICATE KEY UPDATE:

Third option is to use INSERT … ON DUPLICATE KEY UPDATE syntax, and in the UPDATE part just do nothing do some meaningless (empty) operation, like calculating 0+0 (Geoffray suggests doing the id=id assignment for the MySQL optimization engine to ignore this operation). Advantage of this method is that it only ignores duplicate key events, and still aborts on other errors.

As a final notice: this post was inspired by Xaprb. I’d also advise to consult his other post on writing flexible SQL queries.

关于mysql - MySQL中的 'insert if not exists'怎么办?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32373279/

相关文章:

mysql - 使用 MySQL 或 r,或两者都使用?

php - 无法在 php 中追加文件

mysql - SQL case 语句 - 根据另外 2 个表从第三个表中选择值

mysql - 连接到 Rails 中单独的 mysql 数据库

SQL 游标使用临时表中的表和字段名称

sql - 如何使用 select 查询的输出作为 insert 查询的输入?

sql - Oracle 中 select 语句结果的逗号分隔列表

sql - MYSQL 支持的最大记录数和表数是多少?

sql - 更新 32k 行的更新语句花费超过 24 小时

mysql - 在外键列上插入问题