【问题标题】:MySQL - how to add unique INT value without using AUTO_INCREMENT?MySQL - 如何在不使用 AUTO_INCREMENT 的情况下添加唯一的 INT 值?
【发布时间】:2017-08-11 16:52:48
【问题描述】:

我有一个 MySQL 表。我必须能够为不是 AUTO_INCREMENT 列的速度添加唯一的 INT 值。

CREATE TABLE ki
(
  id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT
  , comp_id INT(10) UNSIGNED NOT NULL
  , speed INT(4) UNSIGNED NOT NULL DEFAULT 0
  , position INT(4) UNSIGNED NOT NULL DEFAULT 0

  , PRIMARY KEY (id)

  , UNIQUE INDEX (comp_id, speed, position)
  , INDEX (comp_id)

  , FOREIGN KEY (comp_id)
      REFERENCES competitions (id)
        ON DELETE NO ACTION
        ON UPDATE CASCADE
) ENGINE=InnoDB CHARACTER SET latin1 COLLATE latin1_swedish_ci;

我想插入新行。

INSERT INTO ki (comp_id, speed, position) VALUES (1, 1, 0)
INSERT INTO ki (comp_id, speed, position) VALUES (1, 2, 0)
INSERT INTO ki (comp_id, speed, position) VALUES (1, 3, 0)
INSERT INTO ki (comp_id, speed, position) VALUES (1, 3, 0) -- error
INSERT INTO ki (comp_id, speed, position) VALUES (2, 1, 0)
INSERT INTO ki (comp_id, speed, position) VALUES (2, 3, 0)
INSERT INTO ki (comp_id, speed, position) VALUES (2, 2, 0)

每个 comp_id 的 speed 值从 1 开始。speed 值应始终为 comp_id 的最大速度值 + 1。

如果(1, 3, 0) 已经存在,插入应该是(1, max(speed) where comp_id = 1, 0)。换句话说,(1, 4, 0)

我不想修改现有的行。

如何在我的 SQL 查询中执行此操作?如前所述,速度必须是唯一的,如果同时有多个插入,这必须有效。

如果同时有多个插入,以下方式是否有效并保证唯一的速度值(从 1 开始的值)?

INSERT INTO ki (comp_id, speed, position) 
VALUES (
   1, 
   COALESCE((SELECT MAX(ki2.speed)  
     FROM ki AS ki2 
     WHERE ki2.comp_id = 1 
   ), 1) + 1,
   0
)

【问题讨论】:

标签: mysql sql database innodb


【解决方案1】:

使用INSERT INTO ... SELECT 声明:

INSERT INTO ki(comp_id, position, speed)
  SELECT 1, 0, max(speed)+1
  FROM ki

小心!这至少有两个陷阱:

  1. 插入第一行需要对空值进行特殊处理
  2. 更重要的是,这可能会导致竞争条件,因此您最好使用 AUTO_INCREMENT 处理可能导致插入失败时出现间隙的情况

虽然 1. 陷阱很容易通过用 coalesce(max(speed),0)+1 包装来处理,但第二个陷阱是一个真正的危险,通常您需要考虑到这一点,或者只需在 speed 列上创建 UNIQUE INDEX 和竞速查询在任何尝试中都会失败,但首先具有相同的值。

【讨论】:

  • 你 100% 确定 SELECT...max(speed)+1 会给我一个独特的价值吗?
  • 不,正如我的回答中提到的那样。
  • 我在回答中也提到了这一点。
  • 抱歉,我无法编写完成这项工作的查询。
【解决方案2】:

我假设您不能使用自动增量,因为您已经拥有其中之一?如果速度必须是唯一的,那么为什么不是桌面上的 PK 并摆脱自动增量列和自动增量速度呢?

但是,如果 Speed 应该有意义并在插入时定义,那么您将遇到不同的问题。在这种情况下,您定义了一个关于速度的唯一索引,如果该值已经存在,则让它在插入时失败。或者,如果速度不存在,则编写一个存储过程以插入,如果存在则更新记录。您选择的是数据含义和业务规则的函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-22
    • 2013-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-04
    • 2012-10-30
    • 1970-01-01
    相关资源
    最近更新 更多