SQL仅在记录不存在时插入表中[重复]

问题描述 投票:62回答:3

这个问题在这里已有答案:

我想运行一组查询来将一些数据插入到SQL表中,但前提是满足某些条件的记录。该表有4个字段:id(主要),fund_iddateprice

我在查询中有3个字段:fund_iddateprice

所以我的查询会是这样的:

INSERT INTO funds (fund_id, date, price)
    VALUES (23, '2013-02-12', 22.43)
    WHERE NOT EXISTS (
       SELECT * 
       FROM funds 
       WHERE fund_id = 23
         AND date = '2013-02-12'
    );

因此,如果匹配fund_iddate的记录尚不存在,我只想插入数据。如果以上是正确的,那么我觉得这是一种非常低效的方法,因为每次都必须运行一个额外的select语句。

有没有更好的方法来实现上述目标?

编辑:为了澄清,fund_iddate都不是独特的领域;将存在共享相同fund_id或日期的记录,但没有记录应具有与另一个相同的fund_id和日期。

mysql sql sql-insert
3个回答
57
投票

这可能是实现此目的的简单解决方案:

INSERT INTO funds (ID, date, price)
SELECT 23, DATE('2013-02-12'), 22.5
  FROM dual
 WHERE NOT EXISTS (SELECT 1 
                     FROM funds 
                    WHERE ID = 23
                      AND date = DATE('2013-02-12'));

附:或者(如果ID是主键):

 INSERT INTO funds (ID, date, price)
    VALUES (23, DATE('2013-02-12'), 22.5)
        ON DUPLICATE KEY UPDATE ID = 23; -- or whatever you need

this Fiddle


40
投票

虽然我最初标记为选择的答案是正确的,并达到了我所要求的更好的方法(其他人承认但没有进入)。应在由fund_iddate组成的表上创建复合唯一索引。

ALTER TABLE funds ADD UNIQUE KEY `fund_date` (`fund_id`, `date`);

然后在插入记录时添加遇到冲突时的条件:

INSERT INTO funds (`fund_id`, `date`, `price`)
    VALUES (23, DATE('2013-02-12'), 22.5)
        ON DUPLICATE KEY UPDATE `price` = `price`; --this keeps the price what it was (no change to the table) or:

INSERT INTO funds (`fund_id`, `date`, `price`)
    VALUES (23, DATE('2013-02-12'), 22.5)
        ON DUPLICATE KEY UPDATE `price` = 22.5; --this updates the price to the new value

这将为子查询提供更好的性能,并且表的结构更优越。它伴随着一个警告,即您的唯一键列中不能包含NULL值,因为它们仍然被MySQL视为值。


6
投票

假设您无法修改DDL(以创建唯一约束)或仅限于能够编写DML,那么针对整个表检查值的过滤结果是否为null

FIDDLE

insert into funds (ID, date, price) 
select 
    T.* 
from 
    (select 23 ID,  '2013-02-12' date,  22.43 price) T  
        left join 
    funds on funds.ID = T.ID and funds.date = T.date
where 
    funds.ID is null
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.