【问题标题】:Insert if not exists, no unique key如果不存在则插入,没有唯一键
【发布时间】:2020-03-26 09:36:11
【问题描述】:

我希望 name 列在这里是唯一的。 由于无法添加其他问题唯一键,无法用于重复键更新。

我尝试使用插入选择,但不起作用。

INSERT INTO test2 (NAME, hotStatus)
SELECT 'A', 1 WHERE NOT EXISTS (SELECT 1 FROM test2 WHERE NAME = 'A' LIMIT 1);

表格是:

CREATE TABLE `test2` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(10),
  `hotStatus` tinyint(1),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;
@Test
public void testInsert() throws InterruptedException {
    final int COUNT = 20;

    Thread[] ta = new Thread[COUNT];
    for (int i = 0; i < COUNT; i++) {
        int hotStatus = i % 2;
        ta[i] = new Thread(() -> getConn()
                .update("INSERT INTO test2 (NAME, hotStatus) " +
                        "SELECT 'A', ? WHERE NOT EXISTS (SELECT 1 FROM test2 WHERE NAME = 'A' LIMIT 1);", 
                        hotStatus));
    }
    for (Thread t : ta) {
        t.start();
    }
    for (Thread t : ta) {
        t.join();
    }
}

在运行测试之前该表是空的。 在我运行这个测试后,test2 中还有十几个数据。

id  name hotStatus
3   A    1
4   A    0
5   A    0
6   A    0
7   A    1

我尝试选择更新,但无法锁定。

select * from test2 where name = 'A' for update;

我看到其他问题,但没有得到答案

【问题讨论】:

    标签: mysql


    【解决方案1】:

    找不到任何问题(子查询中超出的 LIMIT 除外)。

    INSERT INTO test2 (NAME, hotStatus)
    SELECT @name, 1 
    WHERE NOT EXISTS ( SELECT 1 
                       FROM test2 
                       WHERE NAME = @name );
    

    其中@name 变量用于插入name 值(可以像在问题中一样使用文字)。

    fiddle

    【讨论】:

    • 初始表没有数据,我在高并发下测试,大部分插入成功,最终得到了近20个名字为'A'的数据
    • @SpirytusRektyfikowany 最终产生近 20 个名称为“A”的数据您的解释看起来像 name 列必须是唯一的。请在您的问题中更详细地解释 因为无法添加其他问题唯一键 - 也许您应该解决该问题而不是这个问题?
    • 很现实的问题,因为其他部门要等很久
    猜你喜欢
    • 2017-09-05
    • 2017-09-19
    • 2010-12-30
    • 1970-01-01
    • 1970-01-01
    • 2018-09-17
    • 1970-01-01
    • 2011-04-11
    • 2019-01-24
    相关资源
    最近更新 更多